Skip to content

chore(deps): move to echo v4.16.3, go-jose v4.1.6 and Go 1.26.10 - #508

Merged
unidoc-ahall merged 4 commits into
masterfrom
chore/echo-4.16.3-and-go-1.26.10
Nov 1, 2026
Merged

unidoc-ahall merged 4 commits into
masterfrom
chore/echo-4.16.3-and-go-1.26.10

Conversation

@unidoc-alip

@unidoc-alip unidoc-alip commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

What is wrong today

GitHub's dependency alerts list one critical and three high-severity security advisories against Echo, the web framework our server is built on. The critical one lets a request skip the server's login and permission checks. The high ones let an attacker make the server use up memory until it slows down or stops.

Every one of them is in an optional part of Echo that a server has to switch on: a built-in forwarding proxy, automatic unzipping of uploaded request bodies, and a request recorder for debugging. Our server uses none of these, so customers are not exposed today. We still update: the fix is a small patch release, it clears the alerts, and it means turning one of those features on later can't quietly bring the problem back.

A fifth alert, high severity, is in go-jose, a library our single sign-on login uses to read the identity token the sign-in provider sends back. This one can be reached today. A specially built token makes the server spend a long time on a key check that should take a moment. Each organization's admin chooses which sign-in provider to trust, so an admin who points it at a server they control can send such a token. On a shared, multi-organization installation, that can slow the server down for every customer. We measured it: one crafted sign-in holds a processor core for about 28 seconds before this change, and is turned away in about a thousandth of a second after it.

The Go team's own vulnerability scanner doesn't know about the Echo or go-jose advisories yet. It did find three other issues, which this PR also fixes:

  • Go itself (the version we build with, 1.26.9): a fix that stops trusting a set of compromised security certificates. Our server does use this code, every time it makes a secure connection to another service: single sign-on, S3 storage, email, Slack and Matrix.
  • Go's networking library: two bugs in its HTML reader. Our code never calls that part.

This PR fixes the weaknesses directly; there is no separate issue for it.

What this changes

  • Echo moves from version 4.16.0 to 4.16.3, the newest release in the same series.
  • The Go version used to build and test the server moves from 1.26.9 to 1.26.10, a patch release on the same line.
  • go-jose moves from 4.1.5 to 4.1.6, which refuses oversized or malformed keys before checking them.
  • Go's networking library moves from 0.60.0 to 0.62.0. That pulls five related Go-team libraries (encryption, background tasks, system, terminal and text) up to the versions it needs.
  • The local developer container now installs the same Go version.

No code changes, and nothing users see changes. One Echo change deserves a mention: 4.16.3 changes how Echo works out a visitor's IP address when the application hasn't told it how. Our server already gives Echo its own rule for this, so login rate limiting and sign-in tracking keep seeing the same addresses as before.

Verification

  • The server builds, and the code checks and unit tests pass on Go 1.26.10.
  • The database-backed tests also pass against a freshly built database.
  • The go-jose fix was checked by sending a crafted sign-in token through the same verification step our login uses: about 28 seconds of processing before, about a thousandth of a second after.
  • The Go vulnerability scanner found 1 issue our code reaches and 2 in libraries we include before this change, and 0 of either after.
  • One older finding remains: an unmaintained encryption package inside a Go library. It has no fix and our code never uses it. This PR doesn't change it.

Risk

Low. These are patch releases on versions we already use. The one behaviour change to know about: go-jose 4.1.6 refuses signing keys larger than 4096 bits. If an organization's sign-in provider signs with a key larger than that, its single sign-on would stop working until the limit is raised. The common providers use 2048-bit keys, and some use 4096, so we don't expect anyone to be affected. The automated builds pick up the new Go version on their own. The worst realistic outcome is a build or test failure on CI, which we'd see before merge, not a problem in production.

Dependabot reports four advisories against github.com/labstack/echo/v4
v4.16.0, all fixed in v4.16.1: GHSA-cxf3-9h37-7rr8 (critical, a rejected
WebSocket upgrade through the Proxy middleware leaves a raw tunnel that
skips route middleware), GHSA-9969-6676-49h5 (Proxy keeps WebSocket
connections after the client leaves), GHSA-h7wr-284f-5qvc (Decompress
has no limit on the decoded size) and GHSA-f48p-c9v4-h7xv (BodyDump
captures bodies with no size limit). The server registers only Recover,
BodyLimit, CORS and the request logger, so none of the four can be
reached today. The bump clears the alerts and keeps us on a supported
v4 release. The advisories are not in the Go vulnerability database
yet, so govulncheck does not report them.

v4.16.3 is the newest v4 release. v4.16.2 tightens the BasicAuth and
CSRF middleware, which we do not use. v4.16.3 makes Context.RealIP()
ignore forwarding headers when no IPExtractor is set. The server
already sets its own extractor (server.go), so the client IP that rate
limiting and login tracking see does not change.

govulncheck on go1.26.9 also finds GO-2026-6809 reachable (crypto/x509
does not distrust compromised intermediate certificates, which affects
every outbound TLS connection), fixed in go1.26.10. It also flags
GO-2026-6866 and GO-2026-6860 in golang.org/x/net/html, which our code
does not call, fixed in x/net v0.62.0.

- go.mod: go 1.26.9 -> 1.26.10; echo/v4 v4.16.0 -> v4.16.3;
  golang.org/x/net v0.60.0 -> v0.62.0, which also raises x/crypto
  v0.58.0, x/sync v0.24.0, x/sys v0.49.0, x/term v0.47.0 and x/text
  v0.43.0 to the versions x/net requires
- devenv/Dockerfile: GO_VERSION 1.26.9 -> 1.26.10

Docs say "Go 1.26+" and golang:1.26, so they need no change.

Verified on go1.26.10: go build, go vet and go test ./... pass, and the
Postgres-backed db, refs and api tests pass against a freshly migrated
database. govulncheck v1.9.0 reports 0 reachable vulnerabilities (was
1) and 0 in imported packages (was 2). The one remaining module-level
finding is GO-2026-5932 (x/crypto/openpgp, no fix available, not
called).
go-jose v4.1.5 and earlier (GHSA-mgcc-cww5-fp2q, CVE-2026-116587, high)
pass the RSA modulus and primes of a JWK straight to
rsa.PrivateKey.Validate() without a size check. On Go 1.24+ that call
is cubic in the size of the primes, so one crafted JWK can hold a CPU
core for a long time.

We pull go-jose in through coreos/go-oidc. The OIDC callback hands the
provider's ID token to IDTokenVerifier.Verify (api_oidc.go), which
parses any embedded "jwk" header before it checks the signature. The
provider comes from the discovery URL an org admin configures, so any
org admin who points it at their own server controls that token. On a
multi-tenant deployment that is a way to exhaust the shared server's CPU.

Measured through go-oidc's Verify with the advisory's crafted header
(only the prime size varies): v4.1.5 took 3.5s at 16384-bit and 27.9s at
32768-bit, growing about 8x per doubling. v4.1.6 rejects the same
token in about 1ms with "JWK contains an RSA key that is too large".

- go.mod: github.com/go-jose/go-jose/v4 v4.1.5 -> v4.1.6 (indirect;
  v4.1.6 declares go 1.24.0, no other module moves)

Verified on go1.26.10: go build, go vet and go test ./... pass.
govulncheck v1.9.0 still reports 0 reachable vulnerabilities; the Go
vulnerability database does not list this advisory yet.
@unidoc-alip unidoc-alip changed the title chore(deps): move to echo v4.16.3 and Go 1.26.10 chore(deps): move to echo v4.16.3, go-jose v4.1.6 and Go 1.26.10 Oct 30, 2026

@unidoc-ahall unidoc-ahall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving 9ff80fb.

What I checked

  • The diff is only go.mod, go.sum and devenv/Dockerfile (GO_VERSION 1.26.10). No source changes.
  • On Go 1.26.10 (toolchain fetched from the go line): 'go mod verify' reports all modules verified; 'go mod tidy -diff' is clean (go.mod/go.sum are consistent, nothing missing or extra); go build ./... and go vet ./... are clean.
  • 'go test ./...' against the test database passes in every package (cmd/isms, api, client, db, i18n, mail, refs, risk, store, tui).
  • go-jose 4.1.6: confirmed in the module source that it adds a limit of 4096 bits on RSA key modulus (MaxRSAModulusBits = 4096), which matches the described mitigation and the risk note (providers with larger keys would fail).
  • Echo 4.16.3's IP-extraction change: the server sets its own echo IPExtractor (api/server.go), which is what rate limiting reads via c.RealIP(), so the behaviour change in the default does not apply here.

Non-blocking

  • The go-jose DoS needs an admin-controlled OIDC provider; worth a line in release notes for operators of shared installs, and for anyone using a provider with a key above 4096 bits.
  • Before merging, rebuild the devenv image so local Go matches CI (the Dockerfile fetches the release tarball by version).

What I did not do

  • Did not run govulncheck (I did not want to download and execute an external tool here), so the scanner numbers in the description (1 reachable and 2 imported before, 0 after) are not independently verified. Did not reproduce the 28 s vs 1 ms crafted-token measurement, and did not test against a real OIDC provider.

@unidoc-ahall
unidoc-ahall merged commit fb5593e into master Nov 1, 2026
2 checks passed
@unidoc-ahall
unidoc-ahall deleted the chore/echo-4.16.3-and-go-1.26.10 branch November 1, 2026 21:32
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.

2 participants