From ee1d921ef8839cb0683ff97f21a617364b4790fb Mon Sep 17 00:00:00 2001 From: Ansar Smagul Date: Tue, 24 Feb 2026 17:27:41 +0500 Subject: [PATCH 1/4] all: add nosec comments for false positive gosec warnings --- asset/server.go | 6 +-- certstore/truststore_darwin.go | 8 ++-- filter/filter.go | 16 +++---- filterliststore/filterliststore.go | 4 +- .../removejsconstant/removejsconstant.go | 4 +- proxy/proxy.go | 46 +++++++++---------- proxy/websocket.go | 12 ++--- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/asset/server.go b/asset/server.go index a2345a9..63011c0 100644 --- a/asset/server.go +++ b/asset/server.go @@ -107,7 +107,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { refererURL, err := url.Parse(raw) if err != nil { - log.Printf("assetserver: invalid referer URL %q: %v", raw, err) + log.Printf("assetserver: invalid referer URL %q: %v", raw, err) // #nosec G706 -- %q escapes special characters http.Error(w, "invalid referer", http.StatusBadRequest) return } @@ -139,7 +139,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { body, err := s.engine.assetBytes(refererURL.Hostname(), kind) if err != nil { - log.Printf("assetserver: failed to resolve asset %q: %v", r.URL.Path, err) + log.Printf("assetserver: failed to resolve asset %q: %v", r.URL.Path, err) // #nosec G706 -- %q escapes special characters http.Error(w, "asset resolution error", http.StatusInternalServerError) return } @@ -154,5 +154,5 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", strconv.Itoa(len(body))) w.WriteHeader(http.StatusOK) - w.Write(body) + w.Write(body) // #nosec G705 -- body is from internal asset storage, not user input } diff --git a/certstore/truststore_darwin.go b/certstore/truststore_darwin.go index a5ad8d7..d077ced 100644 --- a/certstore/truststore_darwin.go +++ b/certstore/truststore_darwin.go @@ -94,13 +94,13 @@ func (cs *DiskCertStore) installCATrust() error { } defer os.Remove(plistFile.Name()) - cmd = exec.Command("security", "trust-settings-export", "-d", plistFile.Name()) // #nosec G204 + cmd = exec.Command("security", "trust-settings-export", "-d", plistFile.Name()) // #nosec G204 G702 -- args are not user-controlled out, err = cmd.CombinedOutput() if err != nil { return fmt.Errorf("trust-settings-export: %w\n%s", err, out) } - plistData, err := os.ReadFile(plistFile.Name()) + plistData, err := os.ReadFile(plistFile.Name()) // #nosec G703 -- path is from os.CreateTemp, not user input if err != nil { return fmt.Errorf("read plist file: %w", err) } @@ -133,11 +133,11 @@ func (cs *DiskCertStore) installCATrust() error { if err != nil { return fmt.Errorf("create plist data: %w", err) } - err = os.WriteFile(plistFile.Name(), plistData, 0600) + err = os.WriteFile(plistFile.Name(), plistData, 0600) // #nosec G703 -- path is from os.CreateTemp, not user input if err != nil { return fmt.Errorf("write plist file: %w", err) } - cmd = exec.Command("security", "trust-settings-import", "-d", plistFile.Name()) // #nosec G204 + cmd = exec.Command("security", "trust-settings-import", "-d", plistFile.Name()) // #nosec G204 G702 -- args are not user-controlled out, err = cmd.CombinedOutput() if err != nil { return fmt.Errorf("trust-settings-import: %w\n%s", err, out) diff --git a/filter/filter.go b/filter/filter.go index d9bee6e..566a648 100644 --- a/filter/filter.go +++ b/filter/filter.go @@ -130,20 +130,20 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error parseURL = func(currentURL string, depth int) { defer wg.Done() if depth > includeMaxDepth { - log.Printf("filter: max depth %d exceeded when adding %q", includeMaxDepth, currentURL) + log.Printf("filter: max depth %d exceeded when adding %q", includeMaxDepth, currentURL) // #nosec G706 -- %q escapes special characters return } base, err := url.Parse(currentURL) if err != nil { - log.Printf("filter: error parsing url %q: %v", currentURL, err) + log.Printf("filter: error parsing url %q: %v", currentURL, err) // #nosec G706 -- %q escapes special characters return } visitedMu.Lock() if _, ok := visited[currentURL]; ok { visitedMu.Unlock() - log.Printf("filter: duplicate include %q skipped", currentURL) + log.Printf("filter: duplicate include %q skipped", currentURL) // #nosec G706 -- %q escapes special characters return } visited[currentURL] = struct{}{} @@ -151,7 +151,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error contents, err := f.filterListStore.Get(currentURL) if err != nil { - log.Printf("failed to get filter list %q from store: %v", currentURL, err) + log.Printf("failed to get filter list %q from store: %v", currentURL, err) // #nosec G706 -- %q escapes special characters return } defer contents.Close() @@ -162,7 +162,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error if after, ok := strings.CutPrefix(line, "!#include"); ok { includeURL, err := resolveInclude(base, after) if err != nil { - log.Printf("filter: error resolving include: %v", err) + log.Printf("filter: error resolving include: %v", err) // #nosec G706 -- err is from URL parsing, not arbitrary user input continue } @@ -174,7 +174,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error addRuleLine(line) } if err := scanner.Err(); err != nil { - log.Printf("filter: error scanning %q: %v", currentURL, err) + log.Printf("filter: error scanning %q: %v", currentURL, err) // #nosec G706 -- %q escapes special characters } } @@ -240,7 +240,7 @@ func (f *Filter) HandleRequest(req *http.Request) (*http.Response, error) { if isUserNavigation(req) { port := f.whitelistSrv.GetPort() if port <= 0 { - log.Printf("whitelist server not ready, falling back to simple block response for %q", redacted.Redacted(req.URL)) + log.Printf("whitelist server not ready, falling back to simple block response for %q", redacted.Redacted(req.URL)) // #nosec G706 -- sanitized by redacted.Redacted return f.networkRules.CreateBlockResponse(req), nil } @@ -282,7 +282,7 @@ func (f *Filter) HandleResponse(req *http.Request, res *http.Response) error { if isDocumentNavigation(req, res) { if err := f.injector.Inject(req, res); err != nil { // This injection error is recoverable, so we log it and continue processing the response. - log.Printf("error injecting assets for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("error injecting assets for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted } } diff --git a/filterliststore/filterliststore.go b/filterliststore/filterliststore.go index 21d1fb9..1c7924c 100644 --- a/filterliststore/filterliststore.go +++ b/filterliststore/filterliststore.go @@ -52,7 +52,7 @@ func (st *FilterListStore) Get(url string) (io.ReadCloser, error) { return nil, fmt.Errorf("create request: %v", err) } - resp, err := httpClient.Do(req) + resp, err := httpClient.Do(req) // #nosec G704 -- URL is from configured filter lists, not arbitrary user input if err != nil { return nil, fmt.Errorf("do request: %v", err) } @@ -104,7 +104,7 @@ func (st *FilterListStore) Get(url string) (io.ReadCloser, error) { case errors.Is(err, errNotExpires): continue case err != nil: - log.Printf("failed to parse cache TTL from %q, assuming default: %v", line, err) + log.Printf("failed to parse cache TTL from %q, assuming default: %v", line, err) // #nosec G706 -- %q escapes special characters break outer default: break outer diff --git a/networkrules/rulemodifiers/removejsconstant/removejsconstant.go b/networkrules/rulemodifiers/removejsconstant/removejsconstant.go index 074d7a5..2773f98 100644 --- a/networkrules/rulemodifiers/removejsconstant/removejsconstant.go +++ b/networkrules/rulemodifiers/removejsconstant/removejsconstant.go @@ -114,7 +114,7 @@ func removeFromInlineHTML(res *http.Response, keys [][]string) error { newScript, err := stripKeys(script, keys) if err != nil { - log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) + log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) // #nosec G706 -- %q escapes special characters modified.Write(script) continue parse } @@ -131,7 +131,7 @@ func removeFromJS(res *http.Response, keys [][]string) error { return httprewrite.BufferRewrite(res, func(src []byte) []byte { newScript, err := stripKeys(src, keys) if err != nil { - log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) + log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) // #nosec G706 -- %q escapes special characters return src } return newScript diff --git a/proxy/proxy.go b/proxy/proxy.go index 20f7377..bcd5a2f 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -139,7 +139,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (p *Proxy) proxyHTTP(w http.ResponseWriter, r *http.Request) { filterResp, err := p.filter.HandleRequest(r) if err != nil { - log.Printf("error handling request for %q: %v", redacted.Redacted(r.URL), err) + log.Printf("error handling request for %q: %v", redacted.Redacted(r.URL), err) // #nosec G706 -- sanitized by redacted.Redacted } if filterResp != nil { @@ -157,9 +157,9 @@ func (p *Proxy) proxyHTTP(w http.ResponseWriter, r *http.Request) { removeHopHeaders(r.Header) - resp, err := p.requestClient.Do(r) + resp, err := p.requestClient.Do(r) // #nosec G704 -- this is a proxy; forwarding requests is its purpose if err != nil { - log.Printf("error making request: %v", redacted.Redacted(err)) // The error might contain information about the hostname we are connecting to. + log.Printf("error making request: %v", redacted.Redacted(err)) // #nosec G706 -- sanitized by redacted.Redacted; the error might contain information about the hostname we are connecting to. http.Error(w, err.Error(), http.StatusBadGateway) return } @@ -193,14 +193,14 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { clientConn, _, err := hj.Hijack() if err != nil { - log.Printf("hijacking connection(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("hijacking connection(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } defer clientConn.Close() host, _, err := net.SplitHostPort(connReq.Host) if err != nil { - log.Printf("splitting host and port(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("splitting host and port(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } @@ -213,12 +213,12 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { tlsCert, err := p.certGenerator.GetCertificate(host) if err != nil { - log.Printf("getting certificate(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("getting certificate(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } if _, err := clientConn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")); err != nil { - log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } @@ -240,7 +240,7 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { msg := err.Error() if strings.Contains(msg, "tls: ") { - log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) + log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) // #nosec G706 -- sanitized by redacted.Redacted p.addTransparentHost(host) } @@ -249,7 +249,7 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { // decides it no longer needs the connection to the host. // To avoid excessive noise in the logs, we suppress these messages. if !strings.HasSuffix(msg, "connection reset by peer") && !strings.HasSuffix(msg, "An existing connection was forcibly closed by the remote host.") { - log.Printf("reading request(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("reading request(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted } } break @@ -270,19 +270,19 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { filterResp, err := p.filter.HandleRequest(req) if err != nil { - log.Printf("handling request for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("handling request for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted } if filterResp != nil { if _, err := io.Copy(io.Discard, req.Body); err != nil { - log.Printf("discarding body for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("discarding body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted break } if err := req.Body.Close(); err != nil { - log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted break } if err := filterResp.Write(tlsConn); err != nil { - log.Printf("writing filter response for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("writing filter response for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted break } @@ -295,11 +295,11 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { resp, err := p.requestTransport.RoundTrip(req) if err != nil { if strings.Contains(err.Error(), "tls: ") { - log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) + log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) // #nosec G706 -- sanitized by redacted.Redacted p.addTransparentHost(host) } - log.Printf("roundtrip(%s): %v", redacted.Redacted(connReq.Host), err) + log.Printf("roundtrip(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted // TODO: better error presentation response := fmt.Sprintf("HTTP/1.1 502 Bad Gateway\r\n\r\n%s", err.Error()) tlsConn.Write([]byte(response)) @@ -309,9 +309,9 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { removeHopHeaders(resp.Header) if err := p.filter.HandleResponse(req, resp); err != nil { - log.Printf("error handling response by filter for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("error handling response by filter for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted if err := resp.Body.Close(); err != nil { - log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) + log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted } response := fmt.Sprintf("HTTP/1.1 502 Bad Gateway\r\n\r\n%s", err.Error()) tlsConn.Write([]byte(response)) @@ -319,14 +319,14 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { } if err := resp.Write(tlsConn); err != nil { - log.Printf("writing response(%q): %v", redacted.Redacted(connReq.Host), err) + log.Printf("writing response(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted if err := resp.Body.Close(); err != nil { - log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) + log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted } break } if err := resp.Body.Close(); err != nil { - log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) + log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted } if req.Close || resp.Close { @@ -360,16 +360,16 @@ func (p *Proxy) addTransparentHost(host string) { // tunnel tunnels the connection between the client and the remote server // without inspecting the traffic. func (p *Proxy) tunnel(w net.Conn, r *http.Request) { - remoteConn, err := net.Dial("tcp", r.Host) + remoteConn, err := net.Dial("tcp", r.Host) // #nosec G704 -- this is a proxy; forwarding connections is its purpose if err != nil { - log.Printf("dialing remote(%s): %v", redacted.Redacted(r.Host), err) + log.Printf("dialing remote(%s): %v", redacted.Redacted(r.Host), err) // #nosec G706 -- sanitized by redacted.Redacted w.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) return } defer remoteConn.Close() if _, err := w.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")); err != nil { - log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(r.Host), err) + log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(r.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } diff --git a/proxy/websocket.go b/proxy/websocket.go index 78fb78b..d7bd7b0 100644 --- a/proxy/websocket.go +++ b/proxy/websocket.go @@ -15,7 +15,7 @@ func (p *Proxy) proxyWebsocketTLS(req *http.Request, tlsConfig *tls.Config, clie dialer := &tls.Dialer{NetDialer: p.netDialer, Config: tlsConfig} targetConn, err := dialer.Dial("tcp", req.URL.Host) if err != nil { - log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) return } @@ -32,7 +32,7 @@ func (p *Proxy) proxyWebsocket(w http.ResponseWriter, req *http.Request) { targetConn, err := p.netDialer.Dial("tcp", req.URL.Host) if err != nil { w.WriteHeader(http.StatusBadGateway) - log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } defer targetConn.Close() @@ -43,7 +43,7 @@ func (p *Proxy) proxyWebsocket(w http.ResponseWriter, req *http.Request) { } clientConn, _, err := hj.Hijack() if err != nil { - log.Printf("hijacking websocket client(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("hijacking websocket client(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return } @@ -58,7 +58,7 @@ func websocketHandshake(req *http.Request, targetConn io.ReadWriter, clientConn err := req.Write(targetConn) if err != nil { clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) - log.Printf("writing websocket request to backend(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("writing websocket request to backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return err } @@ -67,14 +67,14 @@ func websocketHandshake(req *http.Request, targetConn io.ReadWriter, clientConn resp, err := http.ReadResponse(targetReader, req) if err != nil { clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) - log.Printf("reading websocket response from backend(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("reading websocket response from backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return err } defer resp.Body.Close() err = resp.Write(clientConn) if err != nil { - log.Printf("writing websocket response to client(%s): %v", redacted.Redacted(req.URL.Host), err) + log.Printf("writing websocket response to client(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted return err } From 38beb080613e230c273e227d430db4ae9f2a87a7 Mon Sep 17 00:00:00 2001 From: Ansar Smagul Date: Tue, 24 Feb 2026 17:30:51 +0500 Subject: [PATCH 2/4] internal/asset/cosmetic: use fmt.Fprintf instead of WriteString(fmt.Sprintf(...)) --- internal/asset/cosmetic/injector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/asset/cosmetic/injector.go b/internal/asset/cosmetic/injector.go index 89ffc64..40a0a44 100644 --- a/internal/asset/cosmetic/injector.go +++ b/internal/asset/cosmetic/injector.go @@ -78,7 +78,7 @@ func generateBatchedCSS(selectors []string) string { batch := selectors[i:end] joinedSelectors := strings.Join(batch, ",") - builder.WriteString(fmt.Sprintf("%s{display:none!important;}", joinedSelectors)) + fmt.Fprintf(&builder, "%s{display:none!important;}", joinedSelectors) } return builder.String() From 523c0efc6c7af05de2df3e1d87a7412e71c55f20 Mon Sep 17 00:00:00 2001 From: Ansar Smagul Date: Tue, 24 Feb 2026 21:09:11 +0500 Subject: [PATCH 3/4] sysproxy: use uintptr for InternetSetOption constants to avoid integer overflow conversion --- sysproxy/system_windows.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sysproxy/system_windows.go b/sysproxy/system_windows.go index 416cf4a..11d5f0d 100644 --- a/sysproxy/system_windows.go +++ b/sysproxy/system_windows.go @@ -10,10 +10,10 @@ import ( ) var ( - wininet = windows.NewLazySystemDLL("wininet.dll") - internetSetOption = wininet.NewProc("InternetSetOptionW") - internetOptionSettingsChanged = 39 - internetOptionRefresh = 37 + wininet = windows.NewLazySystemDLL("wininet.dll") + internetSetOption = wininet.NewProc("InternetSetOptionW") + internetOptionSettingsChanged uintptr = 39 + internetOptionRefresh uintptr = 37 //go:embed exclusions/windows.txt platformSpecificExcludedHosts []byte @@ -56,8 +56,8 @@ func unsetSystemProxy() error { return nil } -func callInternetSetOption(dwOption int) { - ret, _, err := internetSetOption.Call(0, uintptr(dwOption), 0, 0) +func callInternetSetOption(dwOption uintptr) { + ret, _, err := internetSetOption.Call(0, dwOption, 0, 0) if ret == 0 { log.Printf("failed to call InternetSetOption with option %d: %v", dwOption, err) } From e6757529c7057fedc7b489446c9c4cf92cf3b047 Mon Sep 17 00:00:00 2001 From: Ansar Smagul Date: Tue, 24 Feb 2026 21:24:40 +0500 Subject: [PATCH 4/4] all: exclude G706 in .golangci.yml and remove inline #nosec G706 comments --- .golangci.yml | 3 ++ asset/server.go | 4 +- filter/filter.go | 16 +++---- filterliststore/filterliststore.go | 2 +- .../removejsconstant/removejsconstant.go | 4 +- proxy/proxy.go | 42 +++++++++---------- proxy/websocket.go | 12 +++--- 7 files changed, 43 insertions(+), 40 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index e0e7a05..f3e15f8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,6 +25,9 @@ linters: - errcheck settings: gosec: + # G706 (log injection): too many false positives. + excludes: + - G706 config: G302: "0644" G306: "0644" diff --git a/asset/server.go b/asset/server.go index 63011c0..7075946 100644 --- a/asset/server.go +++ b/asset/server.go @@ -107,7 +107,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { refererURL, err := url.Parse(raw) if err != nil { - log.Printf("assetserver: invalid referer URL %q: %v", raw, err) // #nosec G706 -- %q escapes special characters + log.Printf("assetserver: invalid referer URL %q: %v", raw, err) http.Error(w, "invalid referer", http.StatusBadRequest) return } @@ -139,7 +139,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { body, err := s.engine.assetBytes(refererURL.Hostname(), kind) if err != nil { - log.Printf("assetserver: failed to resolve asset %q: %v", r.URL.Path, err) // #nosec G706 -- %q escapes special characters + log.Printf("assetserver: failed to resolve asset %q: %v", r.URL.Path, err) http.Error(w, "asset resolution error", http.StatusInternalServerError) return } diff --git a/filter/filter.go b/filter/filter.go index 566a648..d9bee6e 100644 --- a/filter/filter.go +++ b/filter/filter.go @@ -130,20 +130,20 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error parseURL = func(currentURL string, depth int) { defer wg.Done() if depth > includeMaxDepth { - log.Printf("filter: max depth %d exceeded when adding %q", includeMaxDepth, currentURL) // #nosec G706 -- %q escapes special characters + log.Printf("filter: max depth %d exceeded when adding %q", includeMaxDepth, currentURL) return } base, err := url.Parse(currentURL) if err != nil { - log.Printf("filter: error parsing url %q: %v", currentURL, err) // #nosec G706 -- %q escapes special characters + log.Printf("filter: error parsing url %q: %v", currentURL, err) return } visitedMu.Lock() if _, ok := visited[currentURL]; ok { visitedMu.Unlock() - log.Printf("filter: duplicate include %q skipped", currentURL) // #nosec G706 -- %q escapes special characters + log.Printf("filter: duplicate include %q skipped", currentURL) return } visited[currentURL] = struct{}{} @@ -151,7 +151,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error contents, err := f.filterListStore.Get(currentURL) if err != nil { - log.Printf("failed to get filter list %q from store: %v", currentURL, err) // #nosec G706 -- %q escapes special characters + log.Printf("failed to get filter list %q from store: %v", currentURL, err) return } defer contents.Close() @@ -162,7 +162,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error if after, ok := strings.CutPrefix(line, "!#include"); ok { includeURL, err := resolveInclude(base, after) if err != nil { - log.Printf("filter: error resolving include: %v", err) // #nosec G706 -- err is from URL parsing, not arbitrary user input + log.Printf("filter: error resolving include: %v", err) continue } @@ -174,7 +174,7 @@ func (f *Filter) AddURL(listURL string, listName string, listTrusted bool) error addRuleLine(line) } if err := scanner.Err(); err != nil { - log.Printf("filter: error scanning %q: %v", currentURL, err) // #nosec G706 -- %q escapes special characters + log.Printf("filter: error scanning %q: %v", currentURL, err) } } @@ -240,7 +240,7 @@ func (f *Filter) HandleRequest(req *http.Request) (*http.Response, error) { if isUserNavigation(req) { port := f.whitelistSrv.GetPort() if port <= 0 { - log.Printf("whitelist server not ready, falling back to simple block response for %q", redacted.Redacted(req.URL)) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("whitelist server not ready, falling back to simple block response for %q", redacted.Redacted(req.URL)) return f.networkRules.CreateBlockResponse(req), nil } @@ -282,7 +282,7 @@ func (f *Filter) HandleResponse(req *http.Request, res *http.Response) error { if isDocumentNavigation(req, res) { if err := f.injector.Inject(req, res); err != nil { // This injection error is recoverable, so we log it and continue processing the response. - log.Printf("error injecting assets for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("error injecting assets for %q: %v", redacted.Redacted(req.URL), err) } } diff --git a/filterliststore/filterliststore.go b/filterliststore/filterliststore.go index 1c7924c..e7db6f3 100644 --- a/filterliststore/filterliststore.go +++ b/filterliststore/filterliststore.go @@ -104,7 +104,7 @@ func (st *FilterListStore) Get(url string) (io.ReadCloser, error) { case errors.Is(err, errNotExpires): continue case err != nil: - log.Printf("failed to parse cache TTL from %q, assuming default: %v", line, err) // #nosec G706 -- %q escapes special characters + log.Printf("failed to parse cache TTL from %q, assuming default: %v", line, err) break outer default: break outer diff --git a/networkrules/rulemodifiers/removejsconstant/removejsconstant.go b/networkrules/rulemodifiers/removejsconstant/removejsconstant.go index 2773f98..074d7a5 100644 --- a/networkrules/rulemodifiers/removejsconstant/removejsconstant.go +++ b/networkrules/rulemodifiers/removejsconstant/removejsconstant.go @@ -114,7 +114,7 @@ func removeFromInlineHTML(res *http.Response, keys [][]string) error { newScript, err := stripKeys(script, keys) if err != nil { - log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) // #nosec G706 -- %q escapes special characters + log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) modified.Write(script) continue parse } @@ -131,7 +131,7 @@ func removeFromJS(res *http.Response, keys [][]string) error { return httprewrite.BufferRewrite(res, func(src []byte) []byte { newScript, err := stripKeys(src, keys) if err != nil { - log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) // #nosec G706 -- %q escapes special characters + log.Printf("error removing JS constant for %q: %v", res.Request.URL, err) return src } return newScript diff --git a/proxy/proxy.go b/proxy/proxy.go index bcd5a2f..4c84699 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -139,7 +139,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (p *Proxy) proxyHTTP(w http.ResponseWriter, r *http.Request) { filterResp, err := p.filter.HandleRequest(r) if err != nil { - log.Printf("error handling request for %q: %v", redacted.Redacted(r.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("error handling request for %q: %v", redacted.Redacted(r.URL), err) } if filterResp != nil { @@ -159,7 +159,7 @@ func (p *Proxy) proxyHTTP(w http.ResponseWriter, r *http.Request) { resp, err := p.requestClient.Do(r) // #nosec G704 -- this is a proxy; forwarding requests is its purpose if err != nil { - log.Printf("error making request: %v", redacted.Redacted(err)) // #nosec G706 -- sanitized by redacted.Redacted; the error might contain information about the hostname we are connecting to. + log.Printf("error making request: %v", redacted.Redacted(err)) // The error might contain information about the hostname we are connecting to. http.Error(w, err.Error(), http.StatusBadGateway) return } @@ -193,14 +193,14 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { clientConn, _, err := hj.Hijack() if err != nil { - log.Printf("hijacking connection(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("hijacking connection(%s): %v", redacted.Redacted(connReq.Host), err) return } defer clientConn.Close() host, _, err := net.SplitHostPort(connReq.Host) if err != nil { - log.Printf("splitting host and port(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("splitting host and port(%s): %v", redacted.Redacted(connReq.Host), err) return } @@ -213,12 +213,12 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { tlsCert, err := p.certGenerator.GetCertificate(host) if err != nil { - log.Printf("getting certificate(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("getting certificate(%s): %v", redacted.Redacted(connReq.Host), err) return } if _, err := clientConn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")); err != nil { - log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(connReq.Host), err) return } @@ -240,7 +240,7 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { msg := err.Error() if strings.Contains(msg, "tls: ") { - log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) p.addTransparentHost(host) } @@ -249,7 +249,7 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { // decides it no longer needs the connection to the host. // To avoid excessive noise in the logs, we suppress these messages. if !strings.HasSuffix(msg, "connection reset by peer") && !strings.HasSuffix(msg, "An existing connection was forcibly closed by the remote host.") { - log.Printf("reading request(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("reading request(%s): %v", redacted.Redacted(connReq.Host), err) } } break @@ -270,19 +270,19 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { filterResp, err := p.filter.HandleRequest(req) if err != nil { - log.Printf("handling request for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("handling request for %q: %v", redacted.Redacted(req.URL), err) } if filterResp != nil { if _, err := io.Copy(io.Discard, req.Body); err != nil { - log.Printf("discarding body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("discarding body for %q: %v", redacted.Redacted(req.URL), err) break } if err := req.Body.Close(); err != nil { - log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) break } if err := filterResp.Write(tlsConn); err != nil { - log.Printf("writing filter response for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing filter response for %q: %v", redacted.Redacted(req.URL), err) break } @@ -295,11 +295,11 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { resp, err := p.requestTransport.RoundTrip(req) if err != nil { if strings.Contains(err.Error(), "tls: ") { - log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("adding %s to ignored hosts", redacted.Redacted(host)) p.addTransparentHost(host) } - log.Printf("roundtrip(%s): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("roundtrip(%s): %v", redacted.Redacted(connReq.Host), err) // TODO: better error presentation response := fmt.Sprintf("HTTP/1.1 502 Bad Gateway\r\n\r\n%s", err.Error()) tlsConn.Write([]byte(response)) @@ -309,9 +309,9 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { removeHopHeaders(resp.Header) if err := p.filter.HandleResponse(req, resp); err != nil { - log.Printf("error handling response by filter for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("error handling response by filter for %q: %v", redacted.Redacted(req.URL), err) if err := resp.Body.Close(); err != nil { - log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("closing body for %q: %v", redacted.Redacted(req.URL), err) } response := fmt.Sprintf("HTTP/1.1 502 Bad Gateway\r\n\r\n%s", err.Error()) tlsConn.Write([]byte(response)) @@ -319,14 +319,14 @@ func (p *Proxy) proxyConnect(w http.ResponseWriter, connReq *http.Request) { } if err := resp.Write(tlsConn); err != nil { - log.Printf("writing response(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing response(%q): %v", redacted.Redacted(connReq.Host), err) if err := resp.Body.Close(); err != nil { - log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) } break } if err := resp.Body.Close(); err != nil { - log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("closing body(%q): %v", redacted.Redacted(connReq.Host), err) } if req.Close || resp.Close { @@ -362,14 +362,14 @@ func (p *Proxy) addTransparentHost(host string) { func (p *Proxy) tunnel(w net.Conn, r *http.Request) { remoteConn, err := net.Dial("tcp", r.Host) // #nosec G704 -- this is a proxy; forwarding connections is its purpose if err != nil { - log.Printf("dialing remote(%s): %v", redacted.Redacted(r.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("dialing remote(%s): %v", redacted.Redacted(r.Host), err) w.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) return } defer remoteConn.Close() if _, err := w.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")); err != nil { - log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(r.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing 200 OK to client(%s): %v", redacted.Redacted(r.Host), err) return } diff --git a/proxy/websocket.go b/proxy/websocket.go index d7bd7b0..78fb78b 100644 --- a/proxy/websocket.go +++ b/proxy/websocket.go @@ -15,7 +15,7 @@ func (p *Proxy) proxyWebsocketTLS(req *http.Request, tlsConfig *tls.Config, clie dialer := &tls.Dialer{NetDialer: p.netDialer, Config: tlsConfig} targetConn, err := dialer.Dial("tcp", req.URL.Host) if err != nil { - log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) return } @@ -32,7 +32,7 @@ func (p *Proxy) proxyWebsocket(w http.ResponseWriter, req *http.Request) { targetConn, err := p.netDialer.Dial("tcp", req.URL.Host) if err != nil { w.WriteHeader(http.StatusBadGateway) - log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("dialing websocket backend(%s): %v", redacted.Redacted(req.URL.Host), err) return } defer targetConn.Close() @@ -43,7 +43,7 @@ func (p *Proxy) proxyWebsocket(w http.ResponseWriter, req *http.Request) { } clientConn, _, err := hj.Hijack() if err != nil { - log.Printf("hijacking websocket client(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("hijacking websocket client(%s): %v", redacted.Redacted(req.URL.Host), err) return } @@ -58,7 +58,7 @@ func websocketHandshake(req *http.Request, targetConn io.ReadWriter, clientConn err := req.Write(targetConn) if err != nil { clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) - log.Printf("writing websocket request to backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing websocket request to backend(%s): %v", redacted.Redacted(req.URL.Host), err) return err } @@ -67,14 +67,14 @@ func websocketHandshake(req *http.Request, targetConn io.ReadWriter, clientConn resp, err := http.ReadResponse(targetReader, req) if err != nil { clientConn.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")) - log.Printf("reading websocket response from backend(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("reading websocket response from backend(%s): %v", redacted.Redacted(req.URL.Host), err) return err } defer resp.Body.Close() err = resp.Write(clientConn) if err != nil { - log.Printf("writing websocket response to client(%s): %v", redacted.Redacted(req.URL.Host), err) // #nosec G706 -- sanitized by redacted.Redacted + log.Printf("writing websocket response to client(%s): %v", redacted.Redacted(req.URL.Host), err) return err }