chore: clear all reachable vulnerabilities, and scan for them in CI - #8
Merged
Conversation
govulncheck reported three vulnerabilities reachable from this code. Nothing
was scanning, so they sat there: a version number does not announce itself.
GO-2026-6293 echo v4.11.3 -- an encoded slash (%2F) bypasses route-level
protection and exposes static files. Reachable from the
e.Static call in main.go. Fixed in v4.15.3.
GO-2025-3553 golang-jwt/jwt v3 -- memory exhaustion parsing headers.
"Fixed in: N/A" -- v3 is unmaintained, so the only way out is
v5.
GO-2024-2687 golang.org/x/net v0.17.0 -- HTTP/2 CONTINUATION flood.
Fixed in v0.23.0.
govulncheck now reports zero.
The jwt migration is the only one with real API change: StandardClaims becomes
RegisteredClaims, holding exp and iat as NumericDate rather than int64. The
wire format is identical -- both marshal the same JSON numbers -- so tokens
signed before the upgrade keep validating and the deploy does not log everyone
out mid-session. Asserted rather than assumed: a test builds a token the way v3
built one and checks it still parses.
v5 also validates exp by default, which v3 did not do unless asked, and
WithValidMethods makes the algorithm check an enforced parse option rather than
a test the keyfunc has to remember. Tests cover expiry, alg=none confusion and
a wrong signing key.
go.mod said 1.21 while the image built on 1.24, so the enforced language
version was never the shipped one. Current x/crypto and x/net require 1.26, so
both are now 1.26 and the builder image moves with it -- verified by building
the backend stage, since a directive the builder cannot satisfy breaks the
image rather than the tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The new CI step failed on its first run, correctly. go-version-file pins the toolchain from the go directive, and the Go 1.26.0 standard library carries 20 known vulnerabilities fixed in 1.26.1 -- including two reachable through echo.StartServer, in crypto/x509 name-constraint checking. Worth noting how it was missed locally: govulncheck reports the standard library of whatever toolchain runs it, and mine is 1.27.1, so a local scan came back clean while the version CI would actually build with did not. The dependency upgrades were the visible problem; the toolchain was the one only CI could see. Both go.mod and the builder image are now 1.27. Co-Authored-By: Claude Opus 5 <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.
govulncheckfound three vulnerabilities reachable from this code. Nothingwas scanning for them, so they sat there — a version number does not announce
itself.
%2F) bypasses route-level protection and exposes static files, reachable frome.Staticinmain.gogovulnchecknow reports zero, and CI runs it on every push so this cannotquietly rot again.
The jwt migration is the only real change
v3 has no fix, so the only way out was v5.
StandardClaimsbecomesRegisteredClaims, which holdsexp/iatasNumericDateinstead ofint64.The wire format is identical — both marshal the same JSON numbers — so
tokens signed before this deploy keep validating and nobody is logged out
mid-session. That is the claim that matters, so it is asserted rather than
assumed: a test builds a token the way v3 built one and checks it still parses.
Two things improve as a side effect:
expby default; v3 did not unless asked.WithValidMethodsmakes the algorithm check an enforced parse option ratherthan a test the keyfunc has to remember to perform.
Tests cover expiry,
alg=noneconfusion, and a wrong signing key.A build break this nearly shipped
go.modsaid1.21while the Dockerfile built on1.24, so the enforcedlanguage version was never the shipped one. Current
x/cryptoandx/netrequire
1.26— andgo mod tidysilently raised the directive to1.26.0,which the
1.24builder cannot satisfy. That breaks the image build, notthe tests, so CI would have stayed green while the deploy failed.
Both are
1.26now, the builder image moves with it, and I verified bybuilding the backend stage rather than trusting that it would work.
🤖 Generated with Claude Code