Hono 4.12.18 Is a Patch-Now Release: Fix the Cache Leak Before It Leaks User Data
Hono 4.12.18 landed on May 6, 2026 with three security fixes, and one of them is exactly the kind of bug busy teams miss: authenticated responses getting cached and reused for the wrong user.
Hono 4.12.18 is not a “read it later” release
On May 6, 2026, Hono shipped `v4.12.18`. This is one of those releases where the version number looks tiny and the actual risk is not.
The headline issue is ugly in a very real-world way: Hono's cache middleware could ignore Vary: Authorization and Vary: Cookie, which means a cached response for one authenticated user could be served to another one. The advisory spells it out pretty plainly in `GHSA-p77w-8qqv-26rm`: affected apps can leak user-specific data when they cache authenticated responses without also marking them private.
That alone is enough reason to patch. Hono 4.12.18 also fixes a JSX SSR CSS declaration injection issue and a JWT NumericDate validation bug in verify(). All three affect versions < 4.12.18.
My take: if your team uses Hono in production, especially for API routes with auth, this is the sort of release you install first and discuss second.
The cache bug is the one most teams could actually ship
The cache middleware bug matters because the broken code does not look obviously broken.
A lot of teams do some version of this:
import { Hono } from 'hono'
import { cache } from 'hono/cache'
const app = new Hono()
app.use('/api/*', cache({ cacheName: 'api-cache' }))
app.get('/api/me', async (c) => {
const user = await getUserFromSession(c)
c.header('Vary', 'Authorization')
return c.json({
id: user.id,
email: user.email,
plan: user.plan,
})
})At a glance, that feels reasonable. You are telling caches that the response varies by authorization. The problem, according to the advisory, is that Hono's middleware did not treat Vary: Authorization or Vary: Cookie as a reason to skip caching. So the middleware could still store a user-specific response and hand it back to the next request.
That is the nasty kind of bug. No exception. No red test. No dramatic failure. Just the wrong user seeing the wrong data.
The advisory rates it moderate severity with a CVSS score of 5.3. I would not get too relaxed because of that number. Cross-user data leaks are the kind of “moderate” issue that turns into a very non-moderate incident once support tickets start landing.
What to change right now
First, upgrade:
npm install hono@^4.12.18Then audit your routes.
Look for these patterns:
cache()applied to/api/*,/app/*, or any authenticated route treehandlers that return user-specific JSON or HTML
responses that rely on
Vary: AuthorizationorVary: Cookieroutes missing
Cache-Control: privateorno-store
If a route depends on who the user is, my default advice is simple: do not cache it unless you have a very deliberate design for per-user caching.
A safer version looks like this:
app.get('/api/me', async (c) => {
const user = await getUserFromSession(c)
c.header('Cache-Control', 'private, no-store')
return c.json({
id: user.id,
email: user.email,
plan: user.plan,
})
})And if you are using middleware-level caching broadly, pull it back to clearly public endpoints instead of trying to be clever.
app.use('/api/public/*', cache({ cacheName: 'public-api-cache' }))That is less elegant, sure. It is also much harder to leak account data that way.
The JSX SSR fix is another good reason to patch this week
The second advisory, `GHSA-qp7p-654g-cw7p`, covers Hono's JSX SSR renderer. The bug: untrusted input inside a style object could inject additional CSS declarations into the rendered style attribute.
This does **not** become JavaScript execution. That part matters. But it is still not harmless. The advisory calls out things like full-page overlays, UI manipulation, and outbound requests through CSS url(...) values.
Here is the kind of code I would stop trusting immediately:
const accent = c.req.query('accent')
return c.html(
<div style={{ color: accent }}>
Billing settings
</div>
)Even if you never intended to let users style anything, untrusted values have a way of sneaking into templating code through query params, profile settings, or CMS data.
The boring fix is the correct fix: whitelist values.
const accent = c.req.query('accent')
const safeColor = accent === 'red' ? '#dc2626' : '#111827'
return c.html(
<div style={{ color: safeColor }}>
Billing settings
</div>
)If you render JSX on the server, search for style={{ and check whether any value comes from user input, request data, or stored content you do not fully control.
The JWT bug is lower severity, but still worth checking
The third fix, `GHSA-hm8q-7f3q-5f36`, is about exp, nbf, and iat validation in hono/utils/jwt.
The short version is that malformed claim values could bypass time-based checks instead of being rejected. The advisory says this mostly matters when your own app issues malformed tokens, or when the signing key is already under attacker control. So yes, this is less scary than the cache bug.
Still, I would treat it as a reminder to stop being sloppy with token creation. If you issue JWTs yourself, make sure time claims are actual finite numbers, not strings, not null, not weird coercion bait.
const now = Math.floor(Date.now() / 1000)
const payload = {
sub: user.id,
iat: now,
nbf: now,
exp: now + 60 * 60,
}This is not the one I would lose sleep over. But it is absolutely the one I would patch while I am already patching the other two.
What I would do today if I owned a Hono app
Upgrade every app and package using
honoto4.12.18or newer.Grep for
cache(and review every authenticated route touched by that middleware.Add
Cache-Control: private, no-storeto user-specific responses unless you have a strong reason not to.Grep for server-rendered JSX
styleobjects fed by request or user data.Sanity check JWT issuance so
exp,nbf, andiatare numeric Unix timestamps.
None of this is glamorous. It is just the difference between “we upgraded a patch release” and “we quietly avoided a user-data leak.”
That is the real story of Hono 4.12.18. Not a flashy feature. Just a reminder that patch releases are sometimes where the important work happens.