Skip to content

chore: clear all reachable vulnerabilities, and scan for them in CI - #8

Merged
keonik merged 2 commits into
mainfrom
chore/clear-vulnerabilities
Sep 12, 2026
Merged

chore: clear all reachable vulnerabilities, and scan for them in CI#8
keonik merged 2 commits into
mainfrom
chore/clear-vulnerabilities

Conversation

@keonik

@keonik keonik commented Sep 12, 2026

Copy link
Copy Markdown
Owner

govulncheck found three vulnerabilities reachable from this code. Nothing
was scanning for them, so they sat there — a version number does not announce
itself.

ID Problem Fix
GO-2026-6293 echo 4.11.3 — an encoded slash (%2F) bypasses route-level protection and exposes static files, reachable from e.Static in main.go v4.15.3
GO-2025-3553 golang-jwt/jwt v3 — memory exhaustion parsing headers N/A — v3 is unmaintained
GO-2024-2687 x/net 0.17.0 — HTTP/2 CONTINUATION flood v0.23.0

govulncheck now reports zero, and CI runs it on every push so this cannot
quietly rot again.

The jwt migration is the only real change

v3 has no fix, so the only way out was v5. StandardClaims becomes
RegisteredClaims, which holds exp/iat as NumericDate instead of int64.

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:

  • v5 validates exp by default; v3 did not unless asked.
  • WithValidMethods makes the algorithm check an enforced parse option rather
    than a test the keyfunc has to remember to perform.

Tests cover expiry, alg=none confusion, and a wrong signing key.

A build break this nearly shipped

go.mod said 1.21 while the Dockerfile built on 1.24, so the enforced
language version was never the shipped one. Current x/crypto and x/net
require 1.26 — and go mod tidy silently raised the directive to 1.26.0,
which the 1.24 builder cannot satisfy. That breaks the image build, not
the tests, so CI would have stayed green while the deploy failed.

Both are 1.26 now, the builder image moves with it, and I verified by
building the backend stage rather than trusting that it would work.

🤖 Generated with Claude Code

Gray Fay and others added 2 commits September 12, 2026 01:09
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>
@keonik
keonik merged commit 1e01653 into main Sep 12, 2026
3 checks passed
@keonik
keonik deleted the chore/clear-vulnerabilities branch September 12, 2026 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant