{"id":"GHSA-4m76-xfj5-7975","kind":"vulnerability","aliases":["GHSA-4m76-xfj5-7975"],"related":[],"title":"`mount()` and `app.mount()` can forward a path that bypasses middleware scoped inside the mount prefix","description":"### Summary\n\n`mount()` and `app.mount()` remove the mount prefix from the request path and forward the rest to the mounted application. Two mistakes in that step let a crafted request reach a route of the mounted application that the outer application protects with path-scoped middleware, such as an authentication check on `/app/admin/*`. The outer application routes on the original path, so the middleware does not run.\n\n### Details\n\n1. **Dynamic prefix** (all affected versions): for a mount such as `/api/:tenant/*`, the prefix was removed by the length of the route pattern, not of the matched prefix. A request with a longer or shorter first segment is cut in the middle, so `/api/a/xxxxx/admin/secret` reaches the mounted application as `/admin/secret`.\n2. **Re-normalization** (since 4.12.21): the forwarded path was built from the decoded request path and assigned to `url.pathname`, which turns a decoded backslash into `/` and collapses `..`. `/app/public%5C..%5Cadmin/secret` reaches the mounted application as `/admin/secret`.\n\nThe fix removes the prefix segment by segment from the raw pathname, using the matched parameter values for its length. Route patterns that cannot be handled safely now throw: duplicate parameter names and a wildcard inside the last segment such as `/assets*`. A trailing slash in an `app.mount()` prefix no longer removes an extra segment.\n\n### Impact\n\nAn unauthenticated client can reach a route of a mounted application that the outer application protects with path-scoped middleware.\n\nThis affects applications that use `mount()` or `app.mount()` and rely on middleware registered on a sub-path inside the mount prefix for authentication or authorization.\n\n### Workarounds\n\nRegister the authentication middleware inside the mounted application.","summary":"Hono's mount() and app.mount() strip the mount prefix incorrectly, so a crafted request reaches a route in the mounted app without passing the outer app's middleware. An unauthenticated attacker can reach routes the outer app meant to protect, such as an /app/admin/* check.","severity":"medium","cvss":5.3,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"hono","fixed":["4.13.16"],"affected":"< 4.13.16","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["bun","cloudflare-workers","cwe-288","deno","hono","node","package"],"not_affected_if":["auth-inside-mounted-app","no-mount-usage"],"how_to_check":"- Look for `mount(` or `app.mount(` calls in your code and check whether auth middleware is registered on a sub-path inside the mount prefix.\n- Check the installed hono version with `npm ls hono`; versions below `4.13.16` are affected.","fix":"- hono: move to `4.13.16`\n- Per the advisory's workaround: register the authentication middleware inside the mounted application.","status":"open","published_at":"2026-11-01T02:33:42+00:00","first_seen_at":"2026-11-09T22:53:17+00:00","triaged_at":"2026-11-09T22:56:35+00:00","updated_at":"2026-11-09T22:56:35+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-09T22:56:35Z","model":"claude-haiku-5-5","output":{"fix":"- hono: move to `4.13.16`\n- Per the advisory's workaround: register the authentication middleware inside the mounted application.","reach":"internet","title":"Hono: mount paths can bypass path-scoped auth middleware","impact":"medium","summary":"Hono's mount() and app.mount() strip the mount prefix incorrectly, so a crafted request reaches a route in the mounted app without passing the outer app's middleware. An unauthenticated attacker can reach routes the outer app meant to protect, such as an /app/admin/* check.","audience":"developers","category":"package","nicknames":[],"who_cares":["hono","node","bun","deno","cloudflare-workers"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"unauthenticated requests reach protected routes in the mounted application","analyst_note":"","how_to_check":"- Look for `mount(` or `app.mount(` calls in your code and check whether auth middleware is registered on a sub-path inside the mount prefix.\n- Check the installed hono version with `npm ls hono`; versions below `4.13.16` are affected.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-mount-usage","auth-inside-mounted-app"],"who_is_affected":"Applications that use mount() or app.mount() and rely on middleware registered on a sub-path inside the mount prefix for authentication or authorization. Apps that enforce auth inside the mounted application, or that do not mount sub-applications, are not affected by the path bypass.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000803,"input_tokens":5110,"output_tokens":583,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-288':32B '/admin/secret':200C,237C '/api':161C '/api/a/xxxxx/admin/secret':194C '/app/admin':80B,134C '/app/public':229C '/assets':279C '1':150C '2':201C '4.12.21':206C '4m76':18A,23A '5c':230C '5cadmin/secret':231C '7975':20A,25A 'affect':154C,316C 'app':57B,62B,73B 'app.mount':3A,41B,85C,285C,322C 'applic':101C,117C,121C,137C,198C,235C,304C,308C,317C,349C 'assign':218C 'attack':67B 'authent':131C,338C,344C 'author':340C 'backslash':225C 'built':211C 'bun':27B 'bypass':9A 'cannot':261C 'check':81B,132C 'client':296C 'cloudflar':29B 'cloudflare-work':28B 'collaps':228C 'craft':49B,109C 'cut':189C 'cwe':31B 'decod':214C,224C 'deno':33B 'detail':149C 'duplic':267C 'dynam':151C 'extra':291C 'first':186C 'fix':239C 'forward':5A,95C,208C 'ghsa':17A,22A 'ghsa-4m76-xfj5':16A,21A 'handl':263C 'hono':26A,34B,37B 'impact':293C 'incorrect':46B 'insid':12A,273C,333C,346C 'last':275C 'length':169C,257C 'let':107C 'longer':183C,288C 'match':177C,252C 'meant':74B 'middl':192C 'middlewar':10A,64B,127C,145C,314C,326C,345C 'mistak':103C 'mount':1A,14A,39B,44B,56B,83C,88C,100C,116C,158C,197C,234C,303C,320C,335C,348C 'name':269C 'node':35B 'normal':204C 'origin':141C 'outer':61B,72B,120C,136C,307C 'packag':36B 'paramet':253C,268C 'pass':59B 'path':7A,93C,125C,142C,209C,216C,312C,332C 'path-scop':124C,311C 'pathnam':249C 'pattern':173C,259C 'prefix':15A,45B,89C,152C,164C,178C,242C,286C,336C 'protect':76B,122C,309C 'raw':248C 're':203C 're-norm':202C 'reach':51B,69B,111C,195C,232C,298C 'regist':327C,342C 'reli':324C 'remov':86C,166C,240C,289C 'request':50B,92C,110C,180C,215C 'rest':97C 'rout':53B,70B,113C,138C,172C,258C,300C 'run':148C 'safe':264C 'scope':11A,126C,313C 'segment':187C,243C,245C,276C,292C 'shorter':185C 'sinc':205C 'slash':282C 'step':106C 'strip':42B 'sub':331C 'sub-path':330C 'summari':82C 'tenant':162C 'throw':266C 'trail':281C 'turn':222C 'two':102C 'unauthent':66B,295C 'url.pathname':220C 'use':250C,319C 'valu':254C 'version':155C 'wildcard':272C 'without':58B 'workaround':341C 'worker':30B 'xfj5':19A,24A","nicknames":[],"mitigations":[],"who_affected":"Applications that use mount() or app.mount() and rely on middleware registered on a sub-path inside the mount prefix for authentication or authorization. Apps that enforce auth inside the mounted application, or that do not mount sub-applications, are not affected by the path bypass.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["hono"],"ptokens":["hono"],"labels":["bun","cloudflareworkers","cwe288","deno","hono","medium","node","npm","package"],"campaign_type":null,"search_a":"'4m76':18A,23A '7975':20A,25A 'app.mount':3A 'bypass':9A 'forward':5A 'ghsa':17A,22A 'ghsa-4m76-xfj5':16A,21A 'hono':26A 'insid':12A 'middlewar':10A 'mount':1A,14A 'path':7A 'prefix':15A 'scope':11A 'xfj5':19A,24A","search_b":"'-288':32B '/app/admin':80B 'app':57B,62B,73B 'app.mount':41B 'attack':67B 'bun':27B 'check':81B 'cloudflar':29B 'cloudflare-work':28B 'craft':49B 'cwe':31B 'deno':33B 'hono':34B,37B 'incorrect':46B 'meant':74B 'middlewar':64B 'mount':39B,44B,56B 'node':35B 'outer':61B,72B 'packag':36B 'pass':59B 'prefix':45B 'protect':76B 'reach':51B,69B 'request':50B 'rout':53B,70B 'strip':42B 'unauthent':66B 'without':58B 'worker':30B","search_c":"'/admin/secret':200C,237C '/api':161C '/api/a/xxxxx/admin/secret':194C '/app/admin':134C '/app/public':229C '/assets':279C '1':150C '2':201C '4.12.21':206C '5c':230C '5cadmin/secret':231C 'affect':154C,316C 'app.mount':85C,285C,322C 'applic':101C,117C,121C,137C,198C,235C,304C,308C,317C,349C 'assign':218C 'authent':131C,338C,344C 'author':340C 'backslash':225C 'built':211C 'cannot':261C 'check':132C 'client':296C 'collaps':228C 'craft':109C 'cut':189C 'decod':214C,224C 'detail':149C 'duplic':267C 'dynam':151C 'extra':291C 'first':186C 'fix':239C 'forward':95C,208C 'handl':263C 'impact':293C 'insid':273C,333C,346C 'last':275C 'length':169C,257C 'let':107C 'longer':183C,288C 'match':177C,252C 'middl':192C 'middlewar':127C,145C,314C,326C,345C 'mistak':103C 'mount':83C,88C,100C,116C,158C,197C,234C,303C,320C,335C,348C 'name':269C 'normal':204C 'origin':141C 'outer':120C,136C,307C 'paramet':253C,268C 'path':93C,125C,142C,209C,216C,312C,332C 'path-scop':124C,311C 'pathnam':249C 'pattern':173C,259C 'prefix':89C,152C,164C,178C,242C,286C,336C 'protect':122C,309C 'raw':248C 're':203C 're-norm':202C 'reach':111C,195C,232C,298C 'regist':327C,342C 'reli':324C 'remov':86C,166C,240C,289C 'request':92C,110C,180C,215C 'rest':97C 'rout':113C,138C,172C,258C,300C 'run':148C 'safe':264C 'scope':126C,313C 'segment':187C,243C,245C,276C,292C 'shorter':185C 'sinc':205C 'slash':282C 'step':106C 'sub':331C 'sub-path':330C 'summari':82C 'tenant':162C 'throw':266C 'trail':281C 'turn':222C 'two':102C 'unauthent':295C 'url.pathname':220C 'use':250C,319C 'valu':254C 'version':155C 'wildcard':272C 'workaround':341C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-01T02:33:42+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-4m76-xfj5-7975","url":"https://github.com/honojs/hono/security/advisories/GHSA-4m76-xfj5-7975","severity":"medium","published_at":"2026-11-01T02:33:42+00:00","modified_at":"2026-11-01T02:33:42+00:00","first_seen_at":"2026-11-09T22:53:17+00:00","fetched_at":"2026-11-09T22:53:17+00:00","note":null}],"documents":[{"id":110465,"url":"https://github.com/honojs/hono/security/advisories/GHSA-4m76-xfj5-7975","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}