HONO · GHSA-h25j-2p75-qj33 · Package
FIX → 4.13.18
Hono's mount() and app.mount() forward a wrong path when a custom getPath adds a prefix, so the mounted app sees a different path than the outer app routed. An unauthenticated client can reach mounted routes that the outer app's path-scoped middleware was meant to protect.
first public Nov 11, 2026 · 1 source
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Applications that use Hono's mount() or app.mount() together with a custom getPath that adds a prefix, such as a host name for host-based routing, and rely on middleware scoped to a sub-path inside the mount prefix for authentication or authorization. Applications on standard getPath behavior are unaffected apart from a change in percent-encoding of forwarded paths.
Not affected if no-mount, no-path-scoped-middleware, standard-getpath, versions-outside-4.13.16-4.13.17
Who cares bun, cloudflare-workers, deno, hono, host-based-routing, node
npm ls hono; affected versions are 4.13.16 and 4.13.17.getPath and mount( to see whether a custom getPath that prepends a prefix (such as a host name) is combined with mounted sub-apps.The fix for GHSA-4m76-xfj5-7975 in 4.13.16 made mount() and app.mount() remove the mount prefix from the raw request path by counting the segments of the routed path. When a custom getPath adds a prefix to the routed path, for example the host name for host-based routing, the routed path has more segments than the raw path, and one segment too many is removed. The mounted application then receives a different path from the one the outer application routed and protected.
With getPath returning /<host>/<path> and a mount on /<host>, a request for /admin/secret reached the mounted application as /secret, and a request for /public/admin/secret reached it as /admin/secret. The outer application routed on /<host>/public/admin/secret, so middleware registered on /<host>/admin/* did not run, while the mounted application served its route.
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
Upgrade to 4.13.18
hono 4.13.18/admin/secretThe forwarded path is now taken from the routed path (c.req.path) with the matched prefix removed, so the outer and the mounted application always see the same path. Because the routed path is decoded, the middleware checks that turning it back into a URL does not change its meaning, and responds with 400 otherwise: encoded dot segments, repeated trailing slashes under strict: false that a mounted Hono application would strip again, a request URL whose authority contains ?, # or \, and percent escapes that do not survive re-parsing. A mount path with an optional regular expression parameter such as /:id{[0-9]+}? is not supported and throws; register /mount and /mount/:id{[0-9]+} separately.
The original percent encoding of the forwarded path is not preserved, for example %41 can become A. Standard getPath is unaffected apart from this.
An unauthenticated client can reach a route of a mounted application that the outer application protects with path-scoped middleware, when the application uses a custom getPath that prepends a prefix to the path.
This issue affects applications on 4.13.16 and 4.13.17 that use mount() or app.mount() together with a custom getPath that adds a prefix, and rely on middleware registered on a sub-path inside the mount prefix for authentication or authorization.