chore(gosec): reviewed per-site #nosec waivers for the 8 reported findings (18 real sites) - #427
Merged
Merged
Conversation
…dings (18 real sites) Each gosec finding got an individually reviewed inline waiver with a site-specific justification, so the advisory golangci job can go to zero and backend#1305 can later drop --issues-exit-code=0. The advertised backlog of 8 was an artifact of golangci-lint's default issues.max-same-issues=3: the 13 G304s share one message text, so only 3 surfaced per run (which 3 flapped with cache state). The real, uncapped backlog is 18: 4x G204, 13x G304, 1x G115. All 18 are waived here; waiving only the visible 8 would have been whack-a-mole. Hardening was considered per site and deliberately not bolted on: the meaningful control (symlink rejection on the dataset walk, re-checked at stream time) already exists, and filepath.Clean wrappers would silence gosec without confining anything. Comment-only change; no behavior touched. Verified with the CI-pinned golangci-lint v2.12.2 (go1.26.3): 0 issues with --max-same-issues=0 --max-issues-per-linter=0. Part of tracebloc/backend#1305 (epic #930, Layer 1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit dce4f3c. Configure here.
saadqbal
approved these changes
Jul 29, 2026
saadqbal
left a comment
Collaborator
There was a problem hiding this comment.
Approve — careful PR 👍 Every one of the 18 rationales checks out against the code: the rejectSymlink walks, the writeTarFile Lstat re-check, the LimitReader cap, the compile-time argv on both exec sites, and the guarded byte(r) in slug are all real. No waiver hides a site where its justification is false.
Two low-severity notes, neither blocking:
- The G204 waivers on the helm/nodeboot Runner seams sit at the choke point, so they blanket future callers too — the 'every caller passes the literal helm/k3d' property can't be enforced from there. Fine for now (all current callers are literal); a tiny allow-listed exec wrapper would be the durable fix if we ever want one.
- stream.go's Lstat→Open is technically a TOCTOU pair; a non-issue under the local-operator threat model, just noting the 'symlinks re-rejected at stream time' wording doesn't fully close that window.
Good to merge.
LukasWodka
added a commit
that referenced
this pull request
Jul 29, 2026
…#1305) Backlog is zero after the reviewed #nosec waivers (#427): findings now fail the job. max-same-issues: 0 so repeated findings can never hide behind the default cap of 3 again (the '8 findings were really 18' lesson). Branch-protection required-flip follows once this merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
added a commit
that referenced
this pull request
Jul 29, 2026
…#1305) Backlog is zero after the reviewed #nosec waivers (#427): findings now fail the job. max-same-issues: 0 so repeated findings can never hide behind the default cap of 3 again (the '8 findings were really 18' lesson). Branch-protection required-flip follows once this merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
added a commit
that referenced
this pull request
Jul 29, 2026
* ci(golangci): drop the advisory flag + uncap max-same-issues (backend#1305) Backlog is zero after the reviewed #nosec waivers (#427): findings now fail the job. max-same-issues: 0 so repeated findings can never hide behind the default cap of 3 again (the '8 findings were really 18' lesson). Branch-protection required-flip follows once this merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci(golangci): drop the advisory flag + uncap max-same-issues (backend#1305) Backlog is zero after the reviewed #nosec waivers (#427): findings now fail the job. max-same-issues: 0 so repeated findings can never hide behind the default cap of 3 again (the '8 findings were really 18' lesson). Branch-protection required-flip follows once this merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * build: make ci runs lint-full — mirror the now-failing golangci gate (Bugbot) golangci-lint fails PRs on findings since this branch; make ci skipping it broke the 'make ci mirrors CI exactly' rule (green local, red PR). lint-full's guard already gives install instructions when the tool is missing, which is correct mirroring rather than a soft skip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * build: pin lint-full to the CI golangci version via go run (Bugbot) lint-full ran whatever golangci-lint was on PATH while CI pins v2.12.2 -- with ci depending on lint-full, version drift could green a local run that reds the PR gate. Now runs the exact pinned version through the Makefile's own 'go run tool@version' pattern (like errcheck/ staticcheck/govulncheck): no PATH dependency, no brew-version drift. GOLANGCI_LINT var removed (unused); lockstep note added on both sides. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
Per-site, individually reviewed inline
#nosecwaivers for the gosec backlog the advisory golangci job reports, so the job goes to 0 findings and the follow-up in tracebloc/backend#1305 can drop--issues-exit-code=0(and eventually flip the check to required). Comment-only change — no behavior touched.The 8 findings are actually 18
The "8 findings" sized on #423 are an artifact of golangci-lint's default
issues.max-same-issues: 3: all 13 G304s share the identical message text ("Potential file inclusion via variable"), so any given run surfaces only 3 of them — and which 3 flaps with analysis-cache state (reproduced locally: cold-cache runs consistently showed one triple, warm-cache reruns showed different triples; CI caches too, via golangci-lint-action). 3 G304 + 3 same-texted G204 + 1 differently-texted G204 + 1 G115 = the reported 8.Uncapped (
--max-same-issues=0 --max-issues-per-linter=0) the real backlog is 18: 4x G204, 13x G304, 1x G115. Waiving only the visible 8 would have been whack-a-mole — each waived G304 would just let the cap surface a previously hidden one. All 18 are reviewed and waived here.Recommendation for the backend#1305 follow-up that drops the advisory flag: consider also setting
issues.max-same-issues: 0(or a high cap) in.golangci.yml, so a future PR that introduces several instances of the same mistake shows all of them instead of 3.Threat model in one line
This is a customer-installed local CLI that runs with the invoking operator's privileges on the operator's own machine: every "variable" input at these sites is a compile-time constant, the operator's own flag/arg/env/config, or a path enumerated by our own walk of the operator-chosen dataset root — there is no privilege boundary for injection or traversal to cross.
Per-site review
internal/cli/prepare_host.go:113bash -c+installerRunScript("prepare-host"), built only from theinstallerURLconst. No runtime input.internal/cli/upgrade.go:123upgradePlanFor(runtime.GOOS)returns compile-time constants (bash -c installerRunScript("")); only the GOOS branch varies. gosec can't see through the struct.internal/helm/upgrade.go:56Runnervar; every caller passes the literal"helm"; args are the operator's own release/kubeconfig flags, exec'd as an argv array (no shell interpolation anywhere).internal/nodeboot/nodeboot.go:35k3d/helm/docker) with argv from package consts + the operator's own cluster/release names; no shell.internal/config/config.go:125config.jsonunder~/.traceblocor the operator's explicit$TRACEBLOC_CONFIG_DIRoverride, as the invoking user.internal/cli/home_local_fallback.go:113os.Executable()(thetb.cmdshim ownership probe); whoever controls that directory already controls the binary itself.internal/cli/ingest.go:78tracebloc ingest validate <path>).internal/cli/installlog.go:37internal/cli/update_check.go:167config.Dir()+ constant filename; contents JSON-validated before use.internal/push/detect.go:30internal/push/image_resolution.go:30internal/push/preflight.go:45internal/push/preflight.go:81internal/push/preflight.go:805LimitReader.internal/push/stream.go:472srccomes from the symlink-rejecting walk and theLstatguard directly above re-rejects symlinks at stream time (existing defense-in-depth, Bugbot r4/r8).internal/push/tabular.go:391DiscoverTabular's symlink-rejecting walk of the operator-chosen root.internal/push/text.go:165byBase/byStem, maps keyed only by files the symlink-vetted walk found on disk — a manifest entry can select among them but cannot point outside the dataset dir.internal/slug/slug.go:90r < 128guard bounds them, sobyte(r)is a lossless ASCII conversion.Hardening considered, none bolted on
Per-site hardening was weighed before each waiver (preferring a fix over a waiver where one was real):
rejectSymlinkon every Discover walk plus a stream-timeLstatre-check inwriteTarFile(added for Bugbot r4/r8 on the push PRs). The waivers cite it rather than duplicate it.filepath.Clean(...)would silence gosec without confining anything (most of these paths already flow throughfilepath.Join, which Cleans) — cosmetic linter-dodging, rejected in favor of honest, reviewable waivers.slug.gocould dodge G115 by switching tob.WriteRune(r), but that hides the deliberate ASCII-only byte write behind an equivalent call; the explicit waiver documents why the conversion is safe.Verification
.golangci.yml: 8 reported with default caps, 18 uncapped, membership flap across cache states confirmed.golangci-lint run --max-same-issues=0 --max-issues-per-linter=0→ 0 issues (exit 0).gofmt -lclean,go build ./...andgo test ./...green.This unblocks removing
--issues-exit-code=0from.github/workflows/golangci.yml— deliberately not done in this PR; that's the follow-up tracked in tracebloc/backend#1305.Part of tracebloc/backend#1305
🤖 Generated with Claude Code
Note
Low Risk
Comment-only linter suppressions with documented rationale; no logic, I/O, or exec behavior is modified.
Overview
Adds comment-only inline
#nosecannotations at 18 call sites so the advisory golangci-lint job (with gosec) can report 0 findings, paving the way to drop--issues-exit-code=0in a follow-up (backend#1305). No runtime behavior changes.The waivers cover the full backlog golangci’s default caps hide (4× G204, 13× G304, 1× G115): CLI config/install paths, dataset preflight reads, helm/nodeboot test
execseams, and a bounded ASCIIbyte(r)in slug. Each comment documents why the site is acceptable for a local operator-run CLI (fixed paths, operator-chosen files under symlink-vetted walks, compile-time shell scripts, argv-only helm/docker/k3d invocations).Reviewed by Cursor Bugbot for commit dce4f3c. Bugbot is set up for automated code reviews on this repo. Configure here.