Total Recall: Hono Middleware's Unintentional Session Sharing
Jan 27, 2026·6 min read·2 visits
Executive Summary (TL;DR)
Hono < 4.11.7 contains a critical flaw in its `hono/cache` middleware. By failing to respect RFC 9111 directives (specifically `Cache-Control: private` and `Set-Cookie`), the middleware caches sensitive, user-specific responses. This allows attackers to perform Web Cache Deception attacks, potentially hijacking sessions or viewing private data simply by requesting the same resource after a victim.
The Hono framework's cache middleware was a little too eager to help, ignoring standard HTTP caching headers like `private` and `no-store`. This resulted in a shared cache implementation that cheerfully stored and served sensitive user sessions and cookies to unauthenticated attackers.
The Hook: Speed at the Cost of Secrets
In the modern JavaScript ecosystem, speed is the religion, and Hono is one of its high priests. Marketed as an "Ultrafast" web framework for the Edges (Cloudflare Workers, Deno, Bun), it promises low latency and high throughput. And how do we achieve speed? Caching. Caching is the magic pixie dust that turns database-heavy slogs into instant HTTP 200 responses.
But here is the thing about magic: if you don't control it, it burns your house down. The hono/cache middleware is designed to be a shared cache—a mechanism that sits between your users and your logic, storing responses so the next person asking for the same thing gets it faster. Ideally, a shared cache is supposed to act like a neutral librarian, handing out public books but refusing to let strangers read your personal diary.
Prior to version 4.11.7, Hono’s librarian was functionally illiterate regarding privacy labels. It didn't care if the book was stamped "TOP SECRET" or "PRIVATE DIARY." If the status code was 200 OK, Hono made a copy and put it on the public shelf. This vulnerability is a textbook example of Web Cache Deception (WCD), where the application logic does everything right (setting private headers), but the infrastructure layer (the middleware) ignores them completely.
The Flaw: RFC 9111? Never Heard of Her
The root of this vulnerability lies in a blatant disregard for RFC 9111, the sacred text governing HTTP Caching. In a compliant HTTP stack, a shared cache must look for specific signals before storing a response. The most critical of these are Cache-Control: private, Cache-Control: no-store, and the presence of a Set-Cookie header. These are the universal signs for "Do Not Clone."
Developers using Hono likely wrote their endpoints correctly. They might have explicitly set c.header('Cache-Control', 'private') on a user profile endpoint. In a sane world, this tells downstream caches to back off. However, the vulnerable hono/cache middleware had a very simple decision tree: Is it a successful response? If yes, cache it.
This created a massive dissonance between developer intent and runtime behavior. The application code was shouting "Private!", but the middleware was functionally deaf. Because this runs at the application layer (especially in runtimes like Node.js, Bun, or Deno where the middleware is the cache), there is no upstream safety net. If Alice logs in and the response includes a Set-Cookie header with her session ID, the middleware caches that specific response. When Bob comes along five seconds later and requests the same login page or profile endpoint, the middleware sees a cache hit and serves him Alice’s session cookie. Bob is now Alice. Congratulations on the unexpected identity theft.
The Code: The Smoking Gun
Let's look at the crime scene. The vulnerability existed because the logic for determining cacheability was practically non-existent. It defaulted to "yes." The fix introduced in version 4.11.7 adds a new function, shouldSkipCache, which actually performs the necessary due diligence.
Here is the logic that was missing, now implemented in the patch (Commit 12c511745b3f1e7a3f863a23ce5f921c7fa805d1):
// The new sheriff in town
const shouldSkipCache = (res: Response) => {
const vary = res.headers.get('Vary')
// 1. If the response varies on EVERYTHING, don't cache it.
if (vary && vary.includes('*')) {
return true
}
const cacheControl = res.headers.get('Cache-Control')
// 2. The Regex of Redemption
// It looks for 'private', 'no-store', or 'no-cache'
if (
cacheControl &&
/(?:^|,Ps*)(?:private|no-(?:store|cache))(?:Ps*(?:=|,|$))/i.test(cacheControl)
) {
return true
}
// 3. The Cookie Guard
// If we are setting a session, we are definitely not sharing this.
if (res.headers.has('Set-Cookie')) {
return true
}
return false
}The previous version essentially lacked this entire block. It is startlingly simple: if the response sets a cookie, or if the header says private, return true (skip caching). The use of a case-insensitive regex (/i) to parse the Cache-Control header is robust enough to catch variations like Private or no-STORE, protecting developers who might not be consistent with their casing.
The Exploit: Session Hijacking for Dummies
Exploiting this does not require complex buffer overflows or heap spraying. It just requires timing. This is a standard Web Cache Deception attack, but strictly internal to the application server.
The Scenario:
- Target: A Hono application using
cache()middleware on the/api/userendpoint. - Victim (Alice): Authenticates and requests
/api/user. The server generates a JSON response containing her PII and potentially refreshes her session viaSet-Cookie. - The Middleware: Ignores the
privateheader andSet-Cookie. It keys the cache entry by the URL/api/userand stores the full response body and headers. - Attacker (Bob): Requests
/api/userfrom his own machine, without any authentication headers. - The Leak: The middleware finds the cache hit for
/api/user. It serves Alice's JSON and, crucially, herSet-Cookieheader to Bob.
The beauty (and horror) of this exploit is that the attacker doesn't even need to be authenticated. They just need to request the resource while the cache entry is "hot."
The Fix: A Lesson in RFC Compliance
The mitigation is straightforward: Update Hono to version 4.11.7 or later. The patch forces the middleware to respect the boundaries of HTTP caching protocols.
However, this incident serves as a critical lesson for developers building on top of "middleware" ecosystems. Middleware often abstracts away complexity, but when it abstracts away security controls (like header validation), it becomes a liability.
If you cannot update immediately, you must disable the cache middleware on any route that serves personalized content or sets cookies. There is no config-based workaround for the vulnerable versions; the code simply does not check the headers. You either patch it, or you turn it off.
> [!ALERT] > If you are running Hono on Node.js, Bun, or Deno, you are at higher risk. Cloudflare Workers might mitigate some of this if you are relying on Cloudflare's edge caching rules on top of Hono, but internal memory caching within the worker instance is still vulnerable.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Hono HonoJS | < 4.11.7 | 4.11.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-524 (Information Exposure Through Caching) |
| CVSS v3.1 | 5.3 (Medium) |
| Attack Vector | Network (AV:N) |
| Impact | Confidentiality Loss (Session Hijacking / PII) |
| Platform | Node.js, Deno, Bun, Cloudflare Workers |
| Patch Commit | 12c511745b3f1e7a3f863a23ce5f921c7fa805d1 |
MITRE ATT&CK Mapping
The software uses a web cache that does not verify the sensitivity of the data before storing it, potentially exposing private information to unauthorized actors.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.