Add gosec to CI; fix the one real finding it surfaced
Part of the same security-hardening pass as the last two commits. make
lint was go vet only; govulncheck and gitleaks already scanned deps and
secrets on every push, but nothing read this repo's own source for
risky patterns (weak crypto, injection shapes, insecure cookies, ...).
New `make security-code` runs gosec, wired into ci.yaml's security job
alongside the other two. G104 (unchecked error) is excluded at the
Makefile level: every one of its 41 initial hits was this codebase's
existing, deliberate idiom for a best-effort write or an already-
reviewed json.Unmarshal of its own JSONB, predating gosec, and the rule
cannot tell that apart from a mistake -- seventeen individual #nosec
comments would hide a future real G104 regression in the suppression
noise rather than surface it. Reasoning is on the Makefile target.
Of the 12 remaining hits:
- Genuinely real: oidc.go's callback logged error_description (and,
two call sites down, identity.Subject) via %s before the request's
state was even checked against its cookie -- an attacker-reachable
value going into the log unquoted. Switched to %q, matching
identity.Username's existing treatment, so a value holding a
newline can't forge a second log line.
- False positives, annotated inline rather than globally suppressed:
4x G124 on cookies that already set Secure via cookieSecure(...)
(a function call, not the literal `true` the rule wants), 3x G202
on sqlArgs-built queries that only ever splice in a "$N"
placeholder, never a value, and the remaining 5x G706 on log lines
that were already %q-quoted -- gosec's taint analysis doesn't
model format verbs, so it flags the tainted argument regardless.
Also fixed handleMe's swallowed Scan error (gosec's catch, pre-fix):
a transient DB error left hash/dismissed at their zero values and the
response claimed no password and no onboarding dismissal regardless
of the truth, rather than surfacing a 500.
Checked both workflow files for the injection class letsvisit found
there (a `${{ }}` expression spliced straight into a `run:` block):
every one here already goes through `env:` as a quoted shell variable,
documented in ci.yaml's own header comment. Nothing to fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -143,6 +143,7 @@ BUILDX_BUILDER ?= terdut
|
||||
TRIVY_VERSION := 0.73.0
|
||||
GOVULNCHECK_VERSION := v1.1.4
|
||||
GITLEAKS_VERSION := v8.30.0
|
||||
GOSEC_VERSION := v2.29.0
|
||||
|
||||
# --pull, not --no-cache: refresh the base image without discarding the layer cache.
|
||||
DOCKER_BUILD_FLAGS ?= --pull
|
||||
@@ -222,6 +223,26 @@ release: push helm-package helm-push ## Publish image + chart (the workflow's on
|
||||
security-go: ## Scan Go deps for known CVEs (govulncheck)
|
||||
go run golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION) ./...
|
||||
|
||||
# Code-level, not dependency- or secret-level: gosec reads this repo's own source for
|
||||
# known-dangerous patterns (weak crypto, SQL/command injection shapes, insecure file
|
||||
# permissions, …) rather than its module graph or working tree for leaked credentials,
|
||||
# which is what security-go and security-secrets above already cover.
|
||||
#
|
||||
# G104 (unchecked error) is excluded. Every hit it found here on first run was this
|
||||
# codebase's existing, deliberate idiom for a best-effort write or an already-reviewed
|
||||
# json.Unmarshal of this server's own JSONB (see the "best-effort" comments in
|
||||
# middleware.go and the //nolint:errcheck lines in alerts.go/deadman.go) -- a style that
|
||||
# predates gosec and that G104 cannot distinguish from a mistake. Reaching the same
|
||||
# green result by adding a dozens of individual #nosec comments would not add
|
||||
# information; it would just make a future *real* G104 regression one more suppressed
|
||||
# line instead of a visible one. Same reasoning as the chi-advisories note on
|
||||
# security-go above: what gosec reports here (nothing, beyond G104) is the useful
|
||||
# property, not a loophole. -exclude-generated skips web.go's embedded, build-time-only
|
||||
# assets.
|
||||
.PHONY: security-code
|
||||
security-code: ## Scan this repo's own source for risky patterns (gosec)
|
||||
go run github.com/securego/gosec/v2/cmd/gosec@$(GOSEC_VERSION) -exclude-generated -exclude=G104 ./...
|
||||
|
||||
# --no-git scans the working tree rather than the history, so this catches a secret on the
|
||||
# way in. It is not a history audit and finding nothing here says nothing about what is
|
||||
# already committed. --redact because the finding is printed into a CI log.
|
||||
|
||||
Reference in New Issue
Block a user