{"id":"GHSA-h25j-2p75-qj33","kind":"vulnerability","aliases":["GHSA-h25j-2p75-qj33"],"related":[],"title":"`mount()` and `app.mount()` forward a wrong path when a custom `getPath` adds a prefix, bypassing middleware scoped inside the mount prefix","description":"### Summary\n\nThe 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.\n\n### Details\n\nWith `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 `/admin/secret` route.\n\nThe 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.\n\nThe original percent encoding of the forwarded path is not preserved, for example `%41` can become `A`. Standard `getPath` is unaffected apart from this.\n\n### Impact\n\nAn 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.\n\nThis 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.","summary":"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.","severity":"medium","cvss":5.3,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"hono","fixed":["4.13.18"],"affected":">= 4.13.16, <= 4.13.17","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["bun","cloudflare-workers","cwe-288","deno","hono","host-based-routing","node","package"],"not_affected_if":["no-mount","no-path-scoped-middleware","standard-getpath","versions-outside-4.13.16-4.13.17"],"how_to_check":"- Check the installed version with `npm ls hono`; affected versions are `4.13.16` and `4.13.17`.\n- Search the codebase for `getPath` and `mount(` to see whether a custom getPath that prepends a prefix (such as a host name) is combined with mounted sub-apps.\n- Confirm whether auth or authorization middleware is registered on a sub-path inside a mount prefix.","fix":"- `hono` `4.13.18`","status":"open","published_at":"2026-11-11T08:55:11+00:00","first_seen_at":"2026-11-11T08:59:08+00:00","triaged_at":"2026-11-11T09:01:18+00:00","updated_at":"2026-11-11T09:01:18+00:00","category":"package","confidence":0.85,"triage":{"at":"2026-11-11T09:01:18Z","model":"claude-haiku-5-5","output":{"fix":"- `hono` `4.13.18`","reach":"internet","title":"Hono: mount with custom getPath lets requests skip path-scoped middleware","impact":"medium","summary":"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.","audience":"developers","category":"package","nicknames":[],"who_cares":["hono","node","cloudflare-workers","deno","bun","host-based-routing"],"confidence":0.85,"fix_status":"available","needs_auth":"no","worst_case":"unauthenticated clients reach protected mounted application routes","analyst_note":"","how_to_check":"- Check the installed version with `npm ls hono`; affected versions are `4.13.16` and `4.13.17`.\n- Search the codebase for `getPath` and `mount(` to see whether a custom getPath that prepends a prefix (such as a host name) is combined with mounted sub-apps.\n- Confirm whether auth or authorization middleware is registered on a sub-path inside a mount prefix.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["standard-getpath","no-mount","no-path-scoped-middleware","versions-outside-4.13.16-4.13.17"],"who_is_affected":"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.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000851,"input_tokens":5299,"output_tokens":643,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-288':38B '-9':333C,345C '/admin':220C '/admin/secret':194C,209C,230C '/mount':340C,342C '/public/admin/secret':205C,215C '/secret':200C '0':332C,344C '2p75':25A,30A '4.13.16':106C,412C '4.13.17':414C '400':284C '41':360C '4m76':102C '7975':104C 'add':12A,60B,132C,426C 'affect':409C 'alway':255C 'apart':368C 'app':66B,74B,86B 'app.mount':3A,51B,110C,419C 'applic':168C,179C,198C,212C,227C,254C,299C,382C,386C,395C,410C 'authent':444C 'author':307C,446C 'back':272C 'base':43B,147C 'becom':362C 'bun':33B 'bypass':15A 'c.req.path':242C 'chang':278C 'check':268C 'client':78B,374C 'cloudflar':35B 'cloudflare-work':34B 'contain':308C 'count':121C 'custom':10A,58B,130C,398C,423C 'cwe':37B 'decod':265C 'deno':39B 'detail':183C 'differ':69B,172C 'dot':287C 'encod':286C,350C 'escap':312C 'exampl':140C,359C 'express':327C 'fals':294C 'fix':98C 'forward':4A,52B,233C,353C 'getpath':11A,59B,131C,185C,365C,399C,424C 'ghsa':23A,28A,101C 'ghsa-4m76-xfj5':100C 'ghsa-h25j-2p75-qj33':22A,27A 'h25j':24A,29A 'hono':32A,40B,47B,298C 'host':42B,142C,146C 'host-bas':145C 'host-based-rout':41B 'id':331C,343C 'impact':371C 'insid':18A,439C 'issu':408C 'made':107C 'mani':163C 'match':245C 'mean':280C 'meant':93B 'middlewar':16A,91B,217C,267C,392C,432C 'mount':1A,20A,49B,65B,81B,108C,113C,167C,189C,197C,226C,253C,297C,321C,381C,417C,441C 'name':143C 'node':45B 'one':160C,176C 'option':325C 'origin':348C 'otherwis':285C 'outer':73B,85B,178C,211C,250C,385C 'packag':46B 'paramet':328C 'pars':319C 'path':7A,55B,70B,89B,119C,127C,138C,151C,158C,173C,234C,241C,259C,263C,322C,354C,390C,406C,438C 'path-scop':88B,389C 'percent':311C,349C 'prefix':14A,21A,62B,114C,134C,246C,403C,428C,442C 'prepend':401C 'preserv':357C 'protect':95B,182C,387C 'qj33':26A,31A 'raw':117C,157C 're':318C 're-pars':317C 'reach':80B,195C,206C,376C 'receiv':170C 'regist':218C,339C,433C 'regular':326C 'reli':430C 'remov':111C,165C,247C 'repeat':289C 'request':118C,192C,203C,304C 'respond':282C 'return':186C 'rout':44B,75B,82B,126C,137C,148C,150C,180C,213C,231C,240C,262C,378C 'run':223C 'scope':17A,90B,391C 'see':67B,256C 'segment':123C,154C,161C,288C 'separ':346C 'serv':228C 'slash':291C 'standard':364C 'strict':293C 'strip':301C 'sub':437C 'sub-path':436C 'summari':96C 'support':336C 'surviv':316C 'taken':237C 'throw':338C 'togeth':420C 'trail':290C 'turn':270C 'unaffect':367C 'unauthent':77B,373C 'url':275C,305C 'use':396C,416C 'whose':306C 'worker':36B 'would':300C 'wrong':6A,54B 'xfj5':103C","nicknames":[],"mitigations":[],"who_affected":"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.","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","hostbasedrouting","medium","node","npm","package"],"campaign_type":null,"search_a":"'2p75':25A,30A 'add':12A 'app.mount':3A 'bypass':15A 'custom':10A 'forward':4A 'getpath':11A 'ghsa':23A,28A 'ghsa-h25j-2p75-qj33':22A,27A 'h25j':24A,29A 'hono':32A 'insid':18A 'middlewar':16A 'mount':1A,20A 'path':7A 'prefix':14A,21A 'qj33':26A,31A 'scope':17A 'wrong':6A","search_b":"'-288':38B 'add':60B 'app':66B,74B,86B 'app.mount':51B 'base':43B 'bun':33B 'client':78B 'cloudflar':35B 'cloudflare-work':34B 'custom':58B 'cwe':37B 'deno':39B 'differ':69B 'forward':52B 'getpath':59B 'hono':40B,47B 'host':42B 'host-based-rout':41B 'meant':93B 'middlewar':91B 'mount':49B,65B,81B 'node':45B 'outer':73B,85B 'packag':46B 'path':55B,70B,89B 'path-scop':88B 'prefix':62B 'protect':95B 'reach':80B 'rout':44B,75B,82B 'scope':90B 'see':67B 'unauthent':77B 'worker':36B 'wrong':54B","search_c":"'-9':333C,345C '/admin':220C '/admin/secret':194C,209C,230C '/mount':340C,342C '/public/admin/secret':205C,215C '/secret':200C '0':332C,344C '4.13.16':106C,412C '4.13.17':414C '400':284C '41':360C '4m76':102C '7975':104C 'add':132C,426C 'affect':409C 'alway':255C 'apart':368C 'app.mount':110C,419C 'applic':168C,179C,198C,212C,227C,254C,299C,382C,386C,395C,410C 'authent':444C 'author':307C,446C 'back':272C 'base':147C 'becom':362C 'c.req.path':242C 'chang':278C 'check':268C 'client':374C 'contain':308C 'count':121C 'custom':130C,398C,423C 'decod':265C 'detail':183C 'differ':172C 'dot':287C 'encod':286C,350C 'escap':312C 'exampl':140C,359C 'express':327C 'fals':294C 'fix':98C 'forward':233C,353C 'getpath':131C,185C,365C,399C,424C 'ghsa':101C 'ghsa-4m76-xfj5':100C 'hono':298C 'host':142C,146C 'host-bas':145C 'id':331C,343C 'impact':371C 'insid':439C 'issu':408C 'made':107C 'mani':163C 'match':245C 'mean':280C 'middlewar':217C,267C,392C,432C 'mount':108C,113C,167C,189C,197C,226C,253C,297C,321C,381C,417C,441C 'name':143C 'one':160C,176C 'option':325C 'origin':348C 'otherwis':285C 'outer':178C,211C,250C,385C 'paramet':328C 'pars':319C 'path':119C,127C,138C,151C,158C,173C,234C,241C,259C,263C,322C,354C,390C,406C,438C 'path-scop':389C 'percent':311C,349C 'prefix':114C,134C,246C,403C,428C,442C 'prepend':401C 'preserv':357C 'protect':182C,387C 'raw':117C,157C 're':318C 're-pars':317C 'reach':195C,206C,376C 'receiv':170C 'regist':218C,339C,433C 'regular':326C 'reli':430C 'remov':111C,165C,247C 'repeat':289C 'request':118C,192C,203C,304C 'respond':282C 'return':186C 'rout':126C,137C,148C,150C,180C,213C,231C,240C,262C,378C 'run':223C 'scope':391C 'see':256C 'segment':123C,154C,161C,288C 'separ':346C 'serv':228C 'slash':291C 'standard':364C 'strict':293C 'strip':301C 'sub':437C 'sub-path':436C 'summari':96C 'support':336C 'surviv':316C 'taken':237C 'throw':338C 'togeth':420C 'trail':290C 'turn':270C 'unaffect':367C 'unauthent':373C 'url':275C,305C 'use':396C,416C 'whose':306C 'would':300C 'xfj5':103C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-11T08:55:11+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-h25j-2p75-qj33","url":"https://github.com/honojs/hono/security/advisories/GHSA-h25j-2p75-qj33","severity":"medium","published_at":"2026-11-11T08:55:11+00:00","modified_at":"2026-11-11T08:55:12+00:00","first_seen_at":"2026-11-11T08:59:08+00:00","fetched_at":"2026-11-11T09:44:33+00:00","note":null}],"documents":[{"id":124178,"url":"https://github.com/honojs/hono/security/advisories/GHSA-h25j-2p75-qj33","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"}