Skip to content

Update dependency @hono/node-server to v2 [SECURITY]#188

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-hono-node-server-vulnerability
Open

Update dependency @hono/node-server to v2 [SECURITY]#188
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-hono-node-server-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
@hono/node-server 1.19.72.0.5 age confidence

@​hono/node-server has authorization bypass for protected static paths via encoded slashes in Serve Static Middleware

CVE-2026-29087 / GHSA-wc8c-qw6v-h7f6

More information

Details

Summary

When using @​hono/node-server's static file serving together with route-based middleware protections (e.g. protecting /admin/*), inconsistent URL decoding can allow protected static resources to be accessed without authorization.

In particular, paths containing encoded slashes (%2F) may be evaluated differently by routing/middleware matching versus static file path resolution, enabling a bypass where middleware does not run but the static file is still served.

Details

The routing layer and the node-server static handler normalize request paths differently. The router preserves %2F as a literal string when matching routes, while the static handler decodes %2F into / before resolving the filesystem path.

Example request:

  • /admin%2Fsecret.html

This may:

  • fail to match middleware intended for /admin/*, but
  • still be resolved by the static handler as /admin/secret.html under the configured static root.

This does not allow access outside the configured static root and is not a path traversal vulnerability.

Impact

An unauthenticated attacker could bypass route-based authorization protections for protected static resources by supplying paths containing encoded slashes.

Applications relying solely on route-based middleware to protect static subpaths under the same static root may have exposed those resources.

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


@​hono/node-server: Middleware bypass via repeated slashes in serveStatic

CVE-2026-39406 / GHSA-92pp-h63x-v22m

More information

Details

Summary

A path handling inconsistency in serveStatic allows protected static files to be accessed by using repeated slashes (//) in the request path.

When route-based middleware (e.g., /admin/*) is used for authorization, the router may not match paths containing repeated slashes, while serveStatic resolves them as normalized paths. This can lead to a middleware bypass.

Details

The routing layer and serveStatic handle repeated slashes differently.

For example:

  • /admin/secret.txt => matches /admin/*
  • //admin/secret.txt => may not match /admin/*

This inconsistency allows a request such as:

GET //admin/secret.txt

to bypass middleware registered on /admin/* and access protected files.

Impact

An attacker can access static files that are intended to be protected by route-based middleware by using repeated slashes in the request path.

This can lead to unauthorized access to sensitive files under the static root.

This issue affects applications that rely on serveStatic together with route-based middleware for access control.

Severity

  • CVSS Score: 5.3 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Node.js Adapter for Hono: Path traversal in serve-static on Windows via encoded backslash (%5C)

GHSA-frvp-7c67-39w9

More information

Details

The same as the hono core Path traversal in serve-static on Windows via encoded backslash (%5C).

Summary

On Windows hosts, an encoded backslash (%5C) in the request path decodes to \, which the Windows path resolver treats as a separator. serve-static then resolves a single URL segment such as admin\secret.txt into a nested file under the root and serves it, letting an attacker read static files meant to be protected behind prefix-mounted middleware. Directory escape (..) remains blocked.

Details

The router splits paths only on /, so /admin%5Csecret.txt is one segment and middleware on /admin/* does not run. The serve-static guard rejects ./.. and consecutive separators but lets a lone \ through; on Windows the file resolver re-splits it into the protected subtree.

This affects Windows hosts serving static files via the Node, Bun, or Deno adapters that guard a static subtree with prefix-mounted middleware.

Impact

An unauthenticated attacker can read static files under a middleware-guarded prefix on Windows hosts. The read stays within the configured root; escape outside the root is not possible.

Severity

  • CVSS Score: 5.9 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Release Notes

honojs/node-server (@​hono/node-server)

v2.0.5

Compare Source

Security Fix

Fixed a security issue in Serve Static Middleware where prefix-mounted middleware could be bypassed on Windows. This only affects applications running on Windows that use Serve Static Middleware. Affected users are encouraged to upgrade to this version.

See GHSA-frvp-7c67-39w9 for details.

v2.0.4

Compare Source

What's Changed

Full Changelog: honojs/node-server@v2.0.3...v2.0.4

v2.0.3

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/node-server@v2.0.2...v2.0.3

v2.0.2

Compare Source

What's Changed

Full Changelog: honojs/node-server@v2.0.1...v2.0.2

v2.0.1

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/node-server@v2.0.0...v2.0.1

v2.0.0

Compare Source

Now, we release the second major version of the Hono Node.js adapter 🎉 🎉 🎉

The Hono Node.js adapter is now up to 2.3x faster

v2 of the Hono Node.js adapter reaches up to 2.3x the throughput of v1 — that's the peak number, measured on the body-parsing scenario of bun-http-framework-benchmark. The other scenarios (Ping, Query) get a smaller but real boost too.

Install or upgrade with:

npm i @​hono/node-server@latest

v2

The Node.js adapter is going through a major version bump to v2. That said, the public API stays the same — the headline of this release is the large performance improvement described above.

What does the Node.js adapter do?

A quick refresher on what the Node.js adapter actually does — it exists so that Hono applications can run on Node.js. Hono is built on the Web Standards APIs, but you cannot serve those directly from Node.js. The adapter bridges the Web Standards APIs and the Node.js APIs, which is what lets a Hono app — and more generally a Web-Standards-style app — run on top of Node.js.

If you write the following code and run node ./index.js, a server starts up on localhost:3000. And it really is plain Node.js underneath.

import { Hono } from 'hono'
import { serve } from '@​hono/node-server'

const app = new Hono()
app.get('/', (c) => c.text('Hello World!'))

serve(app)

The early performance story

The very first implementation of the Node.js adapter looked roughly like this in pseudocode:

export const getRequestListener = (fetchCallback: FetchCallback) => {
  return async (incoming: IncomingMessage, outgoing: ServerResponse) => {
    const method = incoming.method || 'GET'
    const url = `http://${incoming.headers.host}${incoming.url}`

    // ...

    const init = {
      method: method,
      headers: headerRecord,
    }

    // app is a Hono application
    const res = await app.fetch(new Request(url, init))
    const buffer = await res.arrayBuffer()
    outgoing.writeHead(res.status, resHeaderRecord)
    outgoing.end(new Uint8Array(buffer))
  }
}

So the flow was:

  • a request comes in as an IncomingMessage
  • it gets converted into a Request object and handed to the app
  • the Response returned by the app is written back to the outgoing ServerResponse

In diagram form:

IncomingMessage => Request => app => Response => ServerResponse

This is, frankly, inefficient. So whenever Hono went head-to-head with other Node.js frameworks we kept losing — all we could do was shrug and say "well, it's slow on Node.js."

Introducing LightweightRequest / LightweightResponse

The huge step forward that fixed this was a legendary PR from @​usualoma:

#​95

It made things up to 2.7x faster.

SS

I previously wrote about this in detail in this post:

https://zenn.dev/yusukebe/articles/7ac501716ae1f7?locale=en

In short, the trick is wonderfully simple. It just follows the golden rule of performance tuning: don't do work you don't have to do. Lightweight versions of Request and Response are constructed and used first — and that path is fast. Only when something actually needs the contents of the Request, e.g. when you call req.json(), does a real new Request() get instantiated under the hood and used from then on. The result is fast, and behavior stays correct.

…but body parsing was still slow

"Fast" here was for a very simple "Hello World" benchmark — a GET that just returns text.

There are many ways to benchmark, but the one we tend to reach for is this:

https://github.com/SaltyAom/bun-http-framework-benchmark

It tests three scenarios: Ping, Query, and Body. Let's pit Hono against the major Node.js frameworks:

SS

As you can see, the Body case is very slow. The handler being measured is essentially this:

import { Hono } from 'hono'
import { serve } from '@​hono/node-server'

const app = new Hono()

app.post('/json', async (c) => {
  const data = await c.req.json()
  return c.json(data)
})

serve(app)

c.req.json() is the slow part. The reason is well understood: inside the Node.js adapter, when json() is called the LightweightRequest path can't be used, so a real new Request() ends up being constructed.

perf: optimize request body reading

The 2.3x figure above comes from one PR specifically — PR #​301 by @​mgcrea:

The PR bundles a few changes, but the key one is "optimize request body reading". Quoting from the PR description:

The fix overrides text(), json(), arrayBuffer(), and blob() on the request prototype to read directly from the Node.js IncomingMessage using event-based I/O.

In other words, in the json() case above, we no longer convert into a Request at all — we read the body straight off the Node.js APIs. A classic fast path. That alone gives a large jump in body-parsing throughput.

The same PR also includes two other tuning improvements:

  • URL construction fast-path — skip building a URL object except in edge cases
  • buildOutgoingHttpHeaders optimization — skip the set-cookie header comparison when there are no cookies

v2 ships several other performance PRs as well — newHeadersFromIncoming and signal fast-paths, Response fast-paths and responseViaCache improvements, method-key caching, a regex-based buildUrl rewrite, and more (see the full list below). They all add up, but #​301 is by far the largest single contributor, which is why it gets the spotlight here.

v2 performance

Now let's measure the final v2 build.

First, comparing against the v1 Node.js adapter. dev here is v2. Body improves by 2.3x, and the other scenarios get faster too:

SS

Next, the same comparison against other frameworks. With the Body score jumping, Hono passes Koa and Fastify and takes first place:

SS

[!CAUTION]
Updated: The h3 entry in the earlier framework comparison was an older snapshot. Its successor srvx now ships a FastResponse mode, and in srvx's own benchmark (h3js/srvx/test/bench-node) srvx-fast (≈68,560 req/sec) beats hono-fast (≈59,477 req/sec). The methodology is different from the benchmarks above, but worth being upfront: with FastResponse enabled, srvx is faster than Hono v2 in that setup.

Breaking changes

There are two breaking changes in v2.

Dropped support for Node.js v18

Node.js v18 reached end-of-life, so v2 requires Node.js v20 or later.

Removed the Vercel adapter

The Vercel adapter (@hono/node-server/vercel) has been removed. It is no longer needed for Vercel's modern runtimes, so the recommendation is to deploy without it.

If you still need the previous behavior, the old adapter was a one-liner on top of getRequestListener and you can write the same thing in your own project:

import type { Hono } from 'hono'
import { getRequestListener } from '@​hono/node-server'

export const handle = (app: Hono) => {
  return getRequestListener(app.fetch)
}

Then use it the same way you used handle from @hono/node-server/vercel before.

All changes

A full list of what landed in PR #​316.

Performance
Features
Breaking changes
Fixes & refactors
Build & tooling

Wrap-up

So that's v2 of the Node.js adapter — significantly faster, with the same API. Just upgrading should give you a real performance boost. No more "Hono is slow on Node.js" excuses. Please use Hono — fast not only on Cloudflare, Bun, and Deno, but now also on Node.js.

v1.19.15

Compare Source

v1.19.14

Compare Source

What's Changed

  • fix: add custom inspect to lightweight Request/Response to prevent TypeError on console.log by @​usualoma in #​340

Full Changelog: honojs/node-server@v1.19.13...v1.19.14

v1.19.13

Compare Source

Security Fix

Fixed an issue in Serve Static Middleware where inconsistent handling of repeated slashes (//) between the router and static file resolution could allow middleware to be bypassed. Users of Serve Static Middleware are encouraged to upgrade to this version.

See GHSA-92pp-h63x-v22m for details.

v1.19.12

Compare Source

What's Changed

Full Changelog: honojs/node-server@v1.19.11...v1.19.12

v1.19.11

Compare Source

What's Changed
  • fix: do not overwrite Content-Length in the fast path pattern if Content-Length already exists. by @​usualoma in #​309

Full Changelog: honojs/node-server@v1.19.10...v1.19.11

v1.19.10

Compare Source

Security Fix

Fixed an authorization bypass in Serve Static Middleware caused by inconsistent URL decoding (%2F handling) between the router and static file resolution. Users of Serve Static Middleware are encouraged to upgrade to this version.

See GHSA-wc8c-qw6v-h7f6 for details.

v1.19.9

Compare Source

What's Changed

Full Changelog: honojs/node-server@v1.19.8...v1.19.9

v1.19.8

Compare Source

What's Changed
New Contributors

Full Changelog: honojs/node-server@v1.19.7...v1.19.8


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@changeset-bot

changeset-bot Bot commented Mar 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6abe217

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@renovate renovate Bot changed the title fix(deps): update dependency @hono/node-server to v1.19.10 [security] fix(deps): update dependency @hono/node-server to v1.19.10 [security] - autoclosed Mar 12, 2026
@renovate renovate Bot closed this Mar 12, 2026
@renovate
renovate Bot deleted the renovate/npm-hono-node-server-vulnerability branch March 12, 2026 01:39
@renovate renovate Bot changed the title fix(deps): update dependency @hono/node-server to v1.19.10 [security] - autoclosed fix(deps): update dependency @hono/node-server to v1.19.10 [security] Mar 12, 2026
@renovate renovate Bot reopened this Mar 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-hono-node-server-vulnerability branch 2 times, most recently from 994752d to 9bdb61e Compare March 12, 2026 04:42
@renovate renovate Bot changed the title fix(deps): update dependency @hono/node-server to v1.19.10 [security] fix(deps): update dependency @hono/node-server to v1.19.13 [security] Apr 8, 2026
@renovate
renovate Bot force-pushed the renovate/npm-hono-node-server-vulnerability branch from 9bdb61e to 38a6f5a Compare April 8, 2026 09:30
@renovate renovate Bot changed the title fix(deps): update dependency @hono/node-server to v1.19.13 [security] Update dependency @hono/node-server to v1.19.13 [SECURITY] Apr 8, 2026
@renovate
renovate Bot force-pushed the renovate/npm-hono-node-server-vulnerability branch from 38a6f5a to f23f679 Compare May 12, 2026 12:32
@renovate
renovate Bot force-pushed the renovate/npm-hono-node-server-vulnerability branch from f23f679 to 6abe217 Compare July 21, 2026 22:57
@renovate renovate Bot changed the title Update dependency @hono/node-server to v1.19.13 [SECURITY] Update dependency @hono/node-server to v2 [SECURITY] Jul 21, 2026
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.

0 participants