docs(#3024): document secure HTTP client construction for Go - #6628
Conversation
E2E tests did not runE2E tests run automatically for org/repo members and collaborators on pull requests. For other contributors, a maintainer must add the See E2E testing guide for details. |
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can start a comment with 'qodo' or '@qodo' to chat about any finding |
PR Summary by QodoDocument SSRF-safe HTTP fetching for Go contributors
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Site previewPreview: https://01b154e4-site.fullsend-ai.workers.dev Commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
waynesun09
left a comment
There was a problem hiding this comment.
Review-only pass on the new Secure HTTP clients section. Four MEDIUM findings, all inline:
- The
fetch.FetchURLrecommendation is missing the constraints that decide when it is actually usable — and the doc's own second worked example falls outside them. - The pre-resolve-and-pin dial advice conflicts with the redirect allowance three bullets later.
- The unscoped "must" checklist contradicts accepted in-repo code (
internal/cli/fetchskill.go). - The IP-pinning bullet omits the SNI / certificate-verification caveat that makes it safe to follow.
No blocking verdict — the section is a good addition, and every finding is a wording or scoping fix within it.
|
/fs-fix address findings from @waynesun09 This is a good change. Just needs a few fixups. |
|
/fs-fix address feedback, rebase and resolve conflicts. |
|
Thanks @waynesun09 — all four are fair and verified against head. Fixed in 6d7e362:
Also extended the size bullet to cover |
Add a "Secure HTTP clients" section to the Go contributing guide covering the SSRF protections any code that fetches config/user-supplied URLs must apply: prefer the shared internal/fetch.FetchURL helper, and if a custom client is unavoidable, enforce HTTPS-only (incl. redirects), internal-IP rejection via netutil, disabled proxies, timeouts, and size limits. Points to internal/fetch/fetch.go as the canonical reusable helper and internal/repos/manifest.go's fetchManifestURL/safeDialContext as a worked example (from PR fullsend-ai#3002). Also surfaces the topic in the AGENTS.md Go Code row so it is discoverable. Closes fullsend-ai#3024 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Shai Revivo <srevivo@redhat.com>
…ction dial guidance Address review feedback on the "Secure HTTP clients" section: - State fetch.FetchURL's envelope (non-empty AllowedDomains is mandatory, GET/200-only, no headers, buffered body, port 443) and list the real reasons to fall back to a custom client, incl. "host set not knowable up front" — which is why manifest.go's fetchManifestURL deliberately does not use FetchURL. - Add a scope sentence carving out fixed first-party endpoints (e.g. the loopback fetch service in internal/cli/fetchskill.go) so the "must" list does not generate false findings against accepted code. - Require per-connection IP validation inside DialContext (like safeDialContext); warn that pre-resolve-and-pin is safe only when redirects are blocked, and that an allowed redirect hop must re-check scheme and IP. - Note the dial swaps only the address: keep the original hostname on the request so SNI/cert verification still work; never rewrite the URL to the IP or use InsecureSkipVerify. - Also bound json.NewDecoder bodies, not just io.ReadAll. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Shai Revivo <srevivo@redhat.com>
6d7e362 to
196be23
Compare
|
@rh-hemartin can you merge? |
waynesun09
left a comment
There was a problem hiding this comment.
Second review-only pass, scoped to the rewritten Secure HTTP clients section at head (36bee79). The round-1 findings were addressed; these four are defects in the new text, verified against the code at this SHA.
- The new rationale for per-connection validation inverts the DNS-rebinding defense (IP pinning is the defense, not the risk) — and contradicts its own exemplar, which pins too.
- The scope carve-out's "loopback fetch service" is not what the code does: the fetch server binds
0.0.0.0per ADR 0046. - The carve-out asserts its exemplar bounds the response body;
fetchskill.godecodes an unbounded body, which line 342 explicitly forbids. - The named "worked example to copy" does not enforce the section's first mandatory control (HTTPS-only on the initial request) — that gate lives in its caller.
No blocking verdict; all four are wording/scoping fixes inside the new section. Since this doc is meant to be applied mechanically by review agents, the self-contradictions in (2)-(4) and the inverted rationale in (1) are worth correcting before it lands.
Signed-off-by: Shai Revivo <srevivo@redhat.com>
|
Addressed all four round-two findings in 165db4d:
make lint passes. |
|
@waynesun09 i think it is ready for merge |
What
Adds a Secure HTTP clients section to
docs/contributing/go-code.mddocumenting the SSRF protections required for any Go code that fetches config- or user-supplied URLs, and surfaces the topic in theAGENTS.md"Go Code" row so it's discoverable.Why
Per #3024: on PR #3002 the code agent co-authored an HTTP fetcher with no timeout, no size limit,
http://accepted, and no SSRF protection against redirects to private IPs. Review agents caught these across two rounds. These are deterministic, well-known patterns that can be codified so they're applied on the first commit.Deviation from the issue's literal proposal (please note)
The issue proposed documenting how to hand-roll
safeDialContext+ custom transport for each new client, citinginternal/repos/manifest.goas the pattern to copy. While investigating I foundinternal/fetch/fetch.go— a reusable, SSRF-hardenedFetchURL(ctx, url, FetchPolicy)that already implements more than manifest.go's hand-rolled version (HTTPS-only, domain allowlist, DNS pre-resolution + IP validation, DNS-rebinding-safe IP pinning, port restriction, redirect blocking, timeout, size limit).So the guidance leads with "use
internal/fetch.FetchURL" and treats the property checklist as the fallback for when a custom client is genuinely unavoidable. Copy-pastingsafeDialContextinto every new call site would be the wrong lesson. Both files are cited as references.Change
docs/contributing/go-code.md: new## Secure HTTP clientssection (prefer the shared helper; required properties for custom clients: HTTPS incl. redirects, internal-IP rejection vianetutil,Proxy = nil, timeout,io.LimitReader).AGENTS.md: add "secure HTTP client construction" to the Go Code row's "when to read" list.Validation
fetch.FetchURL,fetch.DefaultPolicy,netutil.CheckIP/IsInternal,manifest.gohelpers).make lintpasses.Closes #3024
🤖 Generated with Claude Code