From 359803cc6be83ea22b70292559a0222397fa62b7 Mon Sep 17 00:00:00 2001 From: favonia Date: Sat, 4 Nov 2023 06:36:03 -0500 Subject: [PATCH] fix: limit the number of bytes read from an HTTP response --- internal/config/network_probe.go | 7 ++----- internal/monitor/base.go | 3 +++ internal/monitor/healthchecks.go | 2 +- internal/monitor/uptimekuma.go | 3 ++- internal/provider/protocol/httpcore.go | 5 ++++- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/config/network_probe.go b/internal/config/network_probe.go index 682d2b27..4b3e27c4 100644 --- a/internal/config/network_probe.go +++ b/internal/config/network_probe.go @@ -2,7 +2,6 @@ package config import ( "context" - "io" "net/http" "time" @@ -24,10 +23,8 @@ func ProbeURL(ctx context.Context, url string) bool { if err != nil { return false } - defer resp.Body.Close() - - _, err = io.ReadAll(resp.Body) - return err == nil + err = resp.Body.Close() + return err != nil } // ShouldWeUse1001 quickly checks 1.1.1.1 and 1.0.0.1 and notes whether 1.0.0.1 should be used. diff --git a/internal/monitor/base.go b/internal/monitor/base.go index 0c1d64ff..a16083b7 100644 --- a/internal/monitor/base.go +++ b/internal/monitor/base.go @@ -9,6 +9,9 @@ import ( //go:generate mockgen -typed -destination=../mocks/mock_monitor.go -package=mocks . Monitor +// maxReadLength is the maximum number of bytes read from an HTTP response. +const maxReadLength int64 = 102400 + // Monitor is a dead man's switch, meaning that the user will be notified when the updater fails to // detect and update the public IP address. No notifications for IP changes. type Monitor interface { diff --git a/internal/monitor/healthchecks.go b/internal/monitor/healthchecks.go index 89e4a5e9..97968b86 100644 --- a/internal/monitor/healthchecks.go +++ b/internal/monitor/healthchecks.go @@ -130,7 +130,7 @@ func (h *Healthchecks) ping(ctx context.Context, ppfmt pp.PP, endpoint string, m return false } defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + body, err := io.ReadAll(io.LimitReader(resp.Body, maxReadLength)) if err != nil { ppfmt.Warningf(pp.EmojiError, "Failed to read HTTP(S) response from the %s endpoint of Healthchecks: %v", diff --git a/internal/monitor/uptimekuma.go b/internal/monitor/uptimekuma.go index 02042f73..b5e2c5c0 100644 --- a/internal/monitor/uptimekuma.go +++ b/internal/monitor/uptimekuma.go @@ -3,6 +3,7 @@ package monitor import ( "context" "encoding/json" + "io" "net/http" "net/url" "slices" @@ -135,7 +136,7 @@ func (h *UptimeKuma) ping(ctx context.Context, ppfmt pp.PP, param UptimeKumaRequ defer resp.Body.Close() var parsedResp UptimeKumaResponse - if err = json.NewDecoder(resp.Body).Decode(&parsedResp); err != nil { + if err = json.NewDecoder(io.LimitReader(resp.Body, maxReadLength)).Decode(&parsedResp); err != nil { ppfmt.Warningf(pp.EmojiError, "Failed to parse the response from Uptime Kuma: %v", err) return false } diff --git a/internal/provider/protocol/httpcore.go b/internal/provider/protocol/httpcore.go index d117ea3a..85966d05 100644 --- a/internal/provider/protocol/httpcore.go +++ b/internal/provider/protocol/httpcore.go @@ -10,6 +10,9 @@ import ( "github.com/favonia/cloudflare-ddns/internal/pp" ) +// maxReadLength is the maximum number of bytes read from an HTTP response. +const maxReadLength int64 = 102400 + type httpCore struct { url string method string @@ -41,7 +44,7 @@ func (h *httpCore) getIP(ctx context.Context, ppfmt pp.PP) (netip.Addr, bool) { } defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + body, err := io.ReadAll(io.LimitReader(resp.Body, maxReadLength)) if err != nil { ppfmt.Warningf(pp.EmojiError, "Failed to read HTTP(S) response from %q: %v", h.url, err) return invalidIP, false