{{ message }}
fix!: only trust x-forwarded-host from configured trusted proxies#26204
Merged
geokat merged 3 commits intoJun 11, 2026
Merged
Conversation
350bd43 to
3cf4d6c
Compare
Subdomain app routing derived the app identity from httpapi.RequestHost, which returned the client-supplied X-Forwarded-Host header verbatim. No middleware validated or stripped that header, so a request from an untrusted peer could forge it. Since the application_connect cookie is scoped to the wildcard apps domain, JavaScript in a share=authenticated app could fetch() with a forged X-Forwarded-Host pointing at a victim's owner-only app; coderd routed and authorized the request as the victim and returned the private app response same-origin to the attacker. Replace RequestHost with httpmw.EffectiveHost, which honors X-Forwarded-Host only when the original socket peer is a configured trusted origin, otherwise falling back to the received Host header. This ties host trust to the same RealIPConfig model already used for X-Forwarded-For and -Proto. Wire it into HandleSubdomain for both coderd and wsproxy, and log both the effective host and the raw received_host. Add coverage: EffectiveHost unit tests assert the trust decision uses the socket peer rather than the spoofable forwarded client IP, and a HandleSubdomain test confirms a forged X-Forwarded-Host from an untrusted peer never reaches token resolution. Refs: https://linear.app/codercom/issue/PLAT-259
3cf4d6c to
83fd965
Compare
geokat
commented
Jun 10, 2026
Comment on lines
+367
to
+369
| loggermw.Logger(s.Logger, func(r *http.Request) string { | ||
| return httpmw.EffectiveHost(s.Options.RealIPConfig, r) | ||
| }), |
Contributor
Author
There was a problem hiding this comment.
This callback is not ideal, but removing it cleanly would require a broader refactor to avoid the import cycle. I kept the callback here to avoid adding extra churn to a security fix.
Contributor
Documentation CheckUpdates Needed
Automated review via Coder Agents |
fa0a412 to
ed2a41c
Compare
johnstcn
approved these changes
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
Subdomain app routing resolved the app identity from
httpapi.RequestHost, whichreturns the client-supplied
X-Forwarded-Hostheader verbatim, and no middlewarevalidated or stripped it. Because the
application_connectcookie is scoped tothe wildcard apps domain, JavaScript running in a
share=authenticatedapp couldfetch()with a forgedX-Forwarded-Hostpointing at a victim's owner-only app.coderd would route and authorize the request as the victim and return the private
app's response same-origin to the attacker's page, allowing the attacker to read
the victim's private app output.
Fix
Remove
httpapi.RequestHostand resolve the host through a newhttpmw.EffectiveHost, which honorsX-Forwarded-Hostonly when the originalsocket peer is a configured trusted origin, otherwise falling back to the received
Hostheader. This ties host trust to the sameRealIPConfigmodel already usedfor
X-Forwarded-ForandX-Forwarded-Proto.EffectiveHostis wired intoHandleSubdomainfor both coderd and wsproxy. Request logs now record both theeffective
hostand the rawreceived_host.The trust check uses the original socket peer rather than the post-
ExtractRealIP(spoofable) forwarded client IP, with unit tests pinning that behavior, plus a
HandleSubdomainregression test confirming a forgedX-Forwarded-Hostfrom anuntrusted peer never reaches token resolution.
Compatibility note
Deployments that rely on reverse proxies rewriting
Hostand forwarding theoriginal host in
X-Forwarded-Hostnow needCODER_PROXY_TRUSTED_ORIGINSconfigured for those proxies. Otherwise subdomain app routing will ignore
X-Forwarded-Host.Refs: https://linear.app/codercom/issue/PLAT-259