{"id":"CVE-2026-125109","kind":"vulnerability","aliases":["CVE-2026-125109","GHSA-2j8w-xcrc-x985"],"related":[],"title":"`Rack::Request#host_with_port` and `#base_url` return an invalid `Host` verbatim, enabling URL and allowlist bypass.","description":"## Summary\n\n`Rack::Request#host_with_port`, and therefore `#base_url` and `#url`, return the raw authority string when it fails validation. An attacker-controlled `Host`, `X-Forwarded-Host`, or `Forwarded: host=` value containing characters that are not permitted in an authority is embedded verbatim in URLs generated by the application.\n\nThis completes the fix for CVE-2026-34835 (GHSA-g2pf-xv49-m2h5), which made `#host` and `#hostname` return `nil` for an invalid authority but left this path unchanged.\n\n## Details\n\n`Rack::Request#host_with_port` splits the authority with `split_authority`. When the `AUTHORITY` pattern does not match, no components are returned and `host_with_port` falls back to returning the unvalidated authority string. `base_url` is `\"#{scheme}://#{host_with_port}\"` and `url` appends the full path, so both inherit the raw value.\n\nFor a request with `Host: evil.com/@legit.com`, `host` returns `nil` while `host_with_port` returns `evil.com/@legit.com` and `base_url` returns `http://evil.com/@legit.com`. A valid `Host` together with an invalid `X-Forwarded-Host` produces the same result, because forwarded headers take priority by default.\n\n## Impact\n\nApplications that build absolute URLs, redirects, or origin-dependent checks from `req.url`, `req.base_url`, or `req.host_with_port`, and that do not enforce a host allowlist, may emit URLs containing attacker-chosen characters such as `@`, `/`, `?`, `#`, spaces, or angle brackets. Generated links and `Location` headers can be redirected through userinfo tricks, string-based URL checks can be bypassed, and markup is reflected where the application does not escape the value. For example, `redirect` in Sinatra behind a proxy that forwards `X-Forwarded-Host` emits the raw invalid authority in `Location`.\n\nRails overrides these methods in Action Dispatch and is not expected to be affected. Rack 3.1 and 3.2 are affected. Rack 2.2 did not receive the CVE-2026-34835 change and returns the raw value from every host method.\n\n## Mitigation\n\n* Update to a patched version of Rack, in which `host_with_port` returns `nil` for an invalid authority and `base_url` falls back to the server's own name.\n* Enforce a host allowlist with `Rack::Protection::HostAuthorization`, `config.hosts` in Rails, or at the reverse proxy, and configure the proxy to overwrite `X-Forwarded-Host` and `Forwarded`.\n* Pin the authority with the `rack.request.config` `:authority` key where available.","summary":"Rack's host_with_port, base_url and url methods return an invalid Host, X-Forwarded-Host or Forwarded value unchanged, so URLs the application builds can carry attacker-chosen characters. An attacker can use this to bypass URL or host allowlist checks and redirect generated links or Location headers.","severity":"medium","cvss":4.8,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"rack","fixed":["3.1.23"],"affected":">= 3.0, < 3.1.23","ecosystem":"rubygems"},{"name":"rack","fixed":["3.2.8"],"affected":">= 3.2, < 3.2.8","ecosystem":"rubygems"}],"ecosystems":["rubygems"],"tags":["cwe-1286","package","rack","ruby","self-hosted","sinatra"],"not_affected_if":["host-allowlist-enforced","proxy-overwrites-forwarded-host","rails"],"how_to_check":"- Check the rack version in the Gemfile.lock: `bundle exec gem list rack` should show a fixed version.\n- Look for code that builds absolute URLs, redirects or origin checks from `req.url`, `req.base_url` or `req.host_with_port` without a host allowlist.\n- Confirm whether `Rack::Protection::HostAuthorization` or `config.hosts` is enabled.","fix":"- rack 3.1 series: `3.1.23`\n- rack 3.2 series: `3.2.8`\n- Rack 2.2 is not patched by this advisory; the sources say it returns the raw value from every host method.","status":"open","published_at":"2026-10-30T02:18:58+00:00","first_seen_at":"2026-11-09T22:53:30+00:00","triaged_at":"2026-11-09T22:57:07+00:00","updated_at":"2026-11-09T22:57:07+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-09T22:57:07Z","model":"claude-haiku-5-5","output":{"fix":"- rack 3.1 series: `3.1.23`\n- rack 3.2 series: `3.2.8`\n- Rack 2.2 is not patched by this advisory; the sources say it returns the raw value from every host method.","reach":"internet","title":"Rack: invalid Host header returned verbatim in generated URLs","impact":"low","summary":"Rack's host_with_port, base_url and url methods return an invalid Host, X-Forwarded-Host or Forwarded value unchanged, so URLs the application builds can carry attacker-chosen characters. An attacker can use this to bypass URL or host allowlist checks and redirect generated links or Location headers.","audience":"developers","category":"package","nicknames":[],"who_cares":["rack","ruby","sinatra","self-hosted"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"attacker-chosen URLs appear in generated links and redirects","analyst_note":"Confirm whether Rack 2.2 has any fixed release, since the sources state it returns the raw value and name no fix for it.","how_to_check":"- Check the rack version in the Gemfile.lock: `bundle exec gem list rack` should show a fixed version.\n- Look for code that builds absolute URLs, redirects or origin checks from `req.url`, `req.base_url` or `req.host_with_port` without a host allowlist.\n- Confirm whether `Rack::Protection::HostAuthorization` or `config.hosts` is enabled.","plain_action":"","product_name":"","needs_analyst":true,"not_affected_if":["rails","host-allowlist-enforced","proxy-overwrites-forwarded-host"],"who_is_affected":"Applications on Rack 3.0 through 3.1.22 or 3.2 through 3.2.7 that build absolute URLs, redirects or origin-dependent checks from request host values and do not enforce a host allowlist. Rails overrides these methods and is not expected to be affected; Rack 2.2 is affected but has no fix in this advisory.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"unknown"},"cost_usd":0.000923,"input_tokens":5496,"output_tokens":747,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-125109':21A,29A '-1286':33B '-2026':20A,28A,151C,397C '-34835':152C,398C '/@legit.com':235C,246C,253C '2.2':391C '2j8w':24A '3.1':385C '3.2':387C 'absolut':280C 'action':375C 'affect':383C,389C 'allowlist':17A,84B,303C,442C 'angl':316C 'append':218C 'applic':66B,144C,277C,343C 'attack':71B,75B,116C,309C 'attacker-chosen':70B,308C 'attacker-control':115C 'author':108C,135C,168C,182C,185C,188C,207C,367C,427C,469C,473C 'avail':476C 'back':202C,432C 'base':7A,46B,101C,209C,248C,331C,429C 'behind':354C 'bracket':317C 'build':67B,279C 'bypass':18A,80B,336C 'carri':69B 'chang':399C 'charact':73B,128C,311C 'check':85B,287C,333C 'chosen':72B,310C 'complet':146C 'compon':194C 'config.hosts':447C 'configur':456C 'contain':127C,307C 'control':117C 'cve':19A,27A,150C,396C 'cwe':32B 'default':275C 'depend':286C 'detail':174C 'dispatch':376C 'embed':137C 'emit':305C,363C 'enabl':14A 'enforc':300C,439C 'escap':346C 'everi':406C 'evil.com':234C,245C,252C 'evil.com/@legit.com':233C,244C,251C 'exampl':350C 'expect':380C 'fail':112C 'fall':201C,431C 'fix':148C 'forward':57B,60B,121C,124C,263C,270C,358C,361C,463C,466C 'full':220C 'g2pf':155C 'generat':88B,141C,318C 'ghsa':23A,154C 'ghsa-2j8w-xcrc-x985':22A 'ghsa-g2pf-xv49-m2h5':153C 'header':92B,271C,322C 'host':3A,12A,39B,43B,54B,58B,83B,96C,118C,122C,125C,160C,177C,198C,213C,232C,236C,240C,256C,264C,302C,362C,407C,419C,441C,464C 'hostauthor':446C 'hostnam':162C 'impact':276C 'inherit':224C 'invalid':11A,53B,167C,260C,366C,426C 'key':474C 'left':170C 'link':89B,319C 'locat':91B,321C,369C 'm2h5':157C 'made':159C 'markup':338C 'match':192C 'may':304C 'method':50B,373C,408C 'mitig':409C 'name':438C 'nil':164C,238C,423C 'origin':285C 'origin-depend':284C 'overrid':371C 'overwrit':460C 'packag':34B 'patch':413C 'path':172C,221C 'pattern':189C 'permit':132C 'pin':467C 'port':5A,45B,98C,179C,200C,215C,242C,295C,421C 'prioriti':273C 'produc':265C 'protect':445C 'proxi':356C,454C,458C 'rack':1A,30A,31A,35B,41B,94C,175C,384C,390C,416C,444C 'rack.request.config':472C 'rail':370C,449C 'raw':107C,226C,365C,403C 'receiv':394C 'redirect':87B,282C,325C,351C 'reflect':340C 'req.base':290C 'req.host':293C 'req.url':289C 'request':2A,95C,176C,230C 'result':268C 'return':9A,51B,105C,163C,196C,204C,237C,243C,250C,401C,422C 'revers':453C 'rubi':36B 'scheme':212C 'self':38B 'self-host':37B 'server':435C 'sinatra':40B,353C 'space':314C 'split':180C,184C 'string':109C,208C,330C 'string-bas':329C 'summari':93C 'take':272C 'therefor':100C 'togeth':257C 'trick':328C 'unchang':62B,173C 'unvalid':206C 'updat':410C 'url':8A,15A,47B,49B,64B,81B,102C,104C,140C,210C,217C,249C,281C,291C,306C,332C,430C 'use':77B 'userinfo':327C 'valid':113C,255C 'valu':61B,126C,227C,348C,404C 'verbatim':13A,138C 'version':414C 'x':56B,120C,262C,360C,462C 'x-forwarded-host':55B,119C,261C,359C,461C 'x985':26A 'xcrc':25A 'xv49':156C","nicknames":[],"mitigations":[],"who_affected":"Applications on Rack 3.0 through 3.1.22 or 3.2 through 3.2.7 that build absolute URLs, redirects or origin-dependent checks from request host values and do not enforce a host allowlist. Rails overrides these methods and is not expected to be affected; Rack 2.2 is affected but has no fix in this advisory.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["rack"],"ptokens":["rack"],"labels":["cwe1286","medium","package","rack","ruby","rubygems","selfhosted","sinatra"],"campaign_type":null,"search_a":"'-125109':21A,29A '-2026':20A,28A '2j8w':24A 'allowlist':17A 'base':7A 'bypass':18A 'cve':19A,27A 'enabl':14A 'ghsa':23A 'ghsa-2j8w-xcrc-x985':22A 'host':3A,12A 'invalid':11A 'port':5A 'rack':1A,30A,31A 'request':2A 'return':9A 'url':8A,15A 'verbatim':13A 'x985':26A 'xcrc':25A","search_b":"'-1286':33B 'allowlist':84B 'applic':66B 'attack':71B,75B 'attacker-chosen':70B 'base':46B 'build':67B 'bypass':80B 'carri':69B 'charact':73B 'check':85B 'chosen':72B 'cwe':32B 'forward':57B,60B 'generat':88B 'header':92B 'host':39B,43B,54B,58B,83B 'invalid':53B 'link':89B 'locat':91B 'method':50B 'packag':34B 'port':45B 'rack':35B,41B 'redirect':87B 'return':51B 'rubi':36B 'self':38B 'self-host':37B 'sinatra':40B 'unchang':62B 'url':47B,49B,64B,81B 'use':77B 'valu':61B 'x':56B 'x-forwarded-host':55B","search_c":"'-2026':151C,397C '-34835':152C,398C '/@legit.com':235C,246C,253C '2.2':391C '3.1':385C '3.2':387C 'absolut':280C 'action':375C 'affect':383C,389C 'allowlist':303C,442C 'angl':316C 'append':218C 'applic':144C,277C,343C 'attack':116C,309C 'attacker-chosen':308C 'attacker-control':115C 'author':108C,135C,168C,182C,185C,188C,207C,367C,427C,469C,473C 'avail':476C 'back':202C,432C 'base':101C,209C,248C,331C,429C 'behind':354C 'bracket':317C 'build':279C 'bypass':336C 'chang':399C 'charact':128C,311C 'check':287C,333C 'chosen':310C 'complet':146C 'compon':194C 'config.hosts':447C 'configur':456C 'contain':127C,307C 'control':117C 'cve':150C,396C 'default':275C 'depend':286C 'detail':174C 'dispatch':376C 'embed':137C 'emit':305C,363C 'enforc':300C,439C 'escap':346C 'everi':406C 'evil.com':234C,245C,252C 'evil.com/@legit.com':233C,244C,251C 'exampl':350C 'expect':380C 'fail':112C 'fall':201C,431C 'fix':148C 'forward':121C,124C,263C,270C,358C,361C,463C,466C 'full':220C 'g2pf':155C 'generat':141C,318C 'ghsa':154C 'ghsa-g2pf-xv49-m2h5':153C 'header':271C,322C 'host':96C,118C,122C,125C,160C,177C,198C,213C,232C,236C,240C,256C,264C,302C,362C,407C,419C,441C,464C 'hostauthor':446C 'hostnam':162C 'impact':276C 'inherit':224C 'invalid':167C,260C,366C,426C 'key':474C 'left':170C 'link':319C 'locat':321C,369C 'm2h5':157C 'made':159C 'markup':338C 'match':192C 'may':304C 'method':373C,408C 'mitig':409C 'name':438C 'nil':164C,238C,423C 'origin':285C 'origin-depend':284C 'overrid':371C 'overwrit':460C 'patch':413C 'path':172C,221C 'pattern':189C 'permit':132C 'pin':467C 'port':98C,179C,200C,215C,242C,295C,421C 'prioriti':273C 'produc':265C 'protect':445C 'proxi':356C,454C,458C 'rack':94C,175C,384C,390C,416C,444C 'rack.request.config':472C 'rail':370C,449C 'raw':107C,226C,365C,403C 'receiv':394C 'redirect':282C,325C,351C 'reflect':340C 'req.base':290C 'req.host':293C 'req.url':289C 'request':95C,176C,230C 'result':268C 'return':105C,163C,196C,204C,237C,243C,250C,401C,422C 'revers':453C 'scheme':212C 'server':435C 'sinatra':353C 'space':314C 'split':180C,184C 'string':109C,208C,330C 'string-bas':329C 'summari':93C 'take':272C 'therefor':100C 'togeth':257C 'trick':328C 'unchang':173C 'unvalid':206C 'updat':410C 'url':102C,104C,140C,210C,217C,249C,281C,291C,306C,332C,430C 'userinfo':327C 'valid':113C,255C 'valu':126C,227C,348C,404C 'verbatim':138C 'version':414C 'x':120C,262C,360C,462C 'x-forwarded-host':119C,261C,359C,461C 'xv49':156C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-10-30T02:18:58+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-2j8w-xcrc-x985","url":"https://github.com/rack/rack/security/advisories/GHSA-2j8w-xcrc-x985","severity":"medium","published_at":"2026-10-30T02:18:58+00:00","modified_at":"2026-11-09T21:57:02+00:00","first_seen_at":"2026-11-09T22:53:30+00:00","fetched_at":"2026-11-09T22:53:30+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-125109","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125109","severity":null,"published_at":"2026-11-09T22:18:42+00:00","modified_at":"2026-11-09T22:18:42+00:00","first_seen_at":"2026-11-10T00:28:47+00:00","fetched_at":"2026-11-10T00:28:47+00:00","note":null}],"documents":[{"id":110685,"url":"https://github.com/rack/rack/security/advisories/GHSA-2j8w-xcrc-x985","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":"2026-10-30T02:18:58+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":112145,"url":"https://github.com/rack/rack/commit/4380381a56dc52556a436d6d794c8e18dc8b0565","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":112146,"url":"https://github.com/rack/rack/commit/49386f460286b7346c7003b69a839de782cc8a39","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":112142,"url":"https://github.com/rack/rack/releases/tag/v3.1.23","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":112143,"url":"https://github.com/rack/rack/releases/tag/v3.2.8","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: 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"}