samples/restApi: sanitize caller-controlled log fields (G706)#125
Open
randomizedcoder wants to merge 1 commit into
Open
samples/restApi: sanitize caller-controlled log fields (G706)#125randomizedcoder wants to merge 1 commit into
randomizedcoder wants to merge 1 commit into
Conversation
15 log.Printf sites across samples/restApi/handlers/{utils,dcgm}.go
concatenated req.Host, req.URL, and err.Error() into the format string
using %v. Since req.Host comes from an attacker-controlled HTTP header,
this lets a malicious client inject \n/\r\n/\x00/ANSI escapes into the
log stream, forging fake entries or abusing terminal log viewers
(gosec G706, CWE-117).
Introduces a `logRequestError(req *http.Request, msg string)` helper in
utils.go that formats all caller-controlled fields with %q, which is
gosec's recognized taint-cleanser. Go's %q renders LF/CR as \n\r,
nulls as \x00, ANSI ESC as \x1b, Unicode line/paragraph separators
(U+2028/2029) as
/
, and escapes embedded double quotes —
so no raw control character survives into the log line regardless of
which field carried the payload.
Adds samples/restApi/handlers/utils_test.go with a 15-case table-driven
test exercising positive, boundary, corner, and attacker categories.
Every case asserts the blanket security invariant via a loop over
{LF, CR, NUL, ESC, BEL, BS, U+2028, U+2029} that none of these raw
bytes appears in the captured log output. Attacker payloads include
classic log-forgery (newline-injected fake entry), CRLF, null-byte
truncation, BEL/backspace terminal abuse, ANSI clear-screen, Unicode
line separator, and a mixed all-attacks-at-once case. A separate
TestLogRequestError_NilURL guards the defensive nil-URL path.
Side effect: the log line format changes from
error: <host><url>: <msg> (no separator between host and URL — a wart)
to
error: host="..." url="..." msg="..."
which is more grep-friendly. No external system should be parsing
these sample logs structurally.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: randomizedcoder <dave.seddon.ca@gmail.com>
fcd6a6b to
5c4df4b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi 👋
Same static-analysis run as #124 — gosec also flagged G706 (log injection via taint analysis) at 15 sites across
samples/restApi/handlers/{utils,dcgm}.go. All instances are this pattern:req.Hostis set from theHost:header, so a client can stuff\n,\r\n,\x00, ANSI escapes, etc. into it and forge log entries or abuse terminal log tails. Sample code → likely to be copy-pasted → worth fixing.What this PR does
Adds a tiny helper in
handlers/utils.go:%qis gosec's recognized taint-cleanser — Go renders LF/CR as\n/\r, NUL as\x00, ANSI ESC as\x1b, U+2028/U+2029 as/, and backslash-escapes embedded quotes. No raw control character survives into the log line regardless of which field carried the payload.All 15 G706 sites in
utils.go(9) anddcgm.go(6) now call the helper.TDD + table-driven tests with nasty cases
Added
samples/restApi/handlers/utils_test.go(15-caseTestLogRequestError+ 1TestLogRequestError_NilURL). Categories:\x1b[2J, U+2028, U+2029, embedded quote, 10 KB string, and a mixed-all-attacks caseEvery case enforces a blanket security invariant via a loop over
{LF, CR, NUL, ESC, BEL, BS, U+2028, U+2029}— none of those raw bytes may appear anywhere in the captured log line. Tests are GPU-less (log.SetOutput(&buf)+ synthetic*http.Request).Heads-up on log line format
The format changes from
error: <host><url>: <msg>(which had no separator between Host and URL — a small wart) toerror: host="..." url="..." msg="...". More grep-friendly, but if anything downstream is structurally parsing these sample logs I can do a tighter%v→%qswap that preserves the wire format. Happy to switch.Why this is low risk
pkg/code touched.go build ./samples/...).go vet,gofmt, and the 16 new tests all green.Test plan
go build ./samples/restApi/...go test -v -count=1 ./samples/restApi/handlers/...— 16/16 passgo vet ./samples/restApi/...gofmt -l samples/restApi/handlers/— empty🤖 Generated with Claude Code