Skip to content

deps: bump hono to >= 4.12.34 (CVE-2026-69207, ReDoS in CORS middleware) #460

Description

@pcornelissen

Bump hono to >= 4.12.34 (CVE-2026-69207, ReDoS in CORS middleware)

What & why

pnpm-lock.yaml resolves hono to 4.12.30 for apps/api and apps/proxy.
That version is affected by CVE-2026-69207 / GHSA-8j4g-w8fx-2239 ("ReDoS in
CORS middleware via Access-Control-Request-Headers"), fixed in 4.12.34.

Following your SECURITY.md ("Vulnerabilities in third-party dependencies that
are already publicly known — open a regular issue or PR to bump the dependency
instead"), this is a public issue rather than a private report.

Reachability in this codebase

The vulnerable path is only reached when a cors() call has no allowHeaders
set, so Hono reflects and parses the request's Access-Control-Request-Headers.
I checked all six cors() calls in the repo:

Location allowHeaders set?
apps/api/src/index.ts:244 yes
apps/api/src/index.ts:254 yes
apps/api/src/index.ts:263 (/.well-known/*) no
apps/api/src/index.ts:271 yes
apps/api/src/index.ts:284 yes
apps/api/src/request-body-limits.ts:37 yes
apps/proxy/src/index.ts:237 yes

The /.well-known/* block sets only origin: "*" and allowMethods, so it
falls back to Hono's default allowHeaders: [] and hits the quadratic split
requestHeaders.split(/\s*,\s*/).

This is reachable unauthenticated: cors() answers the OPTIONS preflight
itself and never calls next(), so no route under /.well-known/ even needs to
exist (there are some anyway, at apps/api/src/mcp/oauth.ts:70 and :79).

Rough timing of the split alone on Node, using a header value made of
whitespace: 5,000 chars → 15 ms, 20,000 → 246 ms, 40,000 → 993 ms, 80,000 →
3,918 ms, cleanly quadratic. At Node's default 16 KB header limit, one request blocks
the event loop for roughly 150 ms, so a handful of requests per second is enough
to saturate an API instance. This is the realistic-DoS case your SECURITY.md
distinguishes from unrealistic traffic volumes, so flagging it explicitly.

Two things to change

  1. Bump hono to >= 4.12.34 (current is 4.13.x) in apps/api/package.json
    and apps/proxy/package.json.
  2. Also update the pinned override. package.json pins
    "@modelcontextprotocol/sdk>hono": "4.12.30" in pnpm.overrides. A normal
    pnpm update raises the app ranges but leaves that copy on the vulnerable
    version, so the override has to move to 4.12.34 (or higher) as well.

As defense in depth it is also worth giving the /.well-known/* block an
explicit allowHeaders, so the reflect-and-parse path is not taken regardless
of the Hono version.

How to test

  • pnpm why hono shows no remaining 4.12.30 resolution after the bump
  • pnpm typecheck and pnpm lint pass

A PR with the fix is attached. It bumps both app ranges and the pinned override
to ^4.12.34 (pnpm resolves that to 4.13.1), regenerates the lockfile, and adds
an explicit allowHeaders to the /.well-known/* block. Happy to adjust the
version or drop the defense-in-depth part if you'd rather keep the change
minimal.

AI assistance

Used AI to scan the dependency tree and locate the reachable cors() call; the
CVE match, the reachability table, and the override note were verified by hand
against pnpm-lock.yaml and the GHSA advisory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions