Skip to content

Account for hosts with/without ports in origin check #6166

Open

Description

@code-asher

Is there an existing issue for this?

  • I have searched the existing issues

OS/Web Information

N/A

Steps to Reproduce

You can simulate with this NGINX config:

proxy_set_header X-Forwarded-Host $host:$server_port;

Expected

If your origin is https://domain.tld and your host is domain.tld:443 the check should pass. Same for http://domain.tld and domain.tld:80.

Also I think NGINX's $host actually does not include ports so it will fail if your config only has $host and if you host on a port other than 443 and 80 since you would get an origin like https://domain.tld:8080 and the host would be domain.tld.

To fix the first we could just check the protocol on the origin and then add/remove 443 or 80.

For the second we could ignore the port altogether since I think the vulnerability does not happen across ports...

But I am not sure we should do anything; maybe the correct course of action is to edit the proxy config so the host and origin headers match. I have looked at other software but they all seem to do exact matches without messing around with the port. We could just edit the documentation to use $http_host.

Actual

The origin and domain are matched exactly so they do not match. Ends up causing the web sockets to fail with 1006.

Logs

No response

Screenshot/Video

No response

Does this issue happen in VS Code or GitHub Codespaces?

  • I cannot reproduce this in VS Code.
  • I cannot reproduce this in GitHub Codespaces.

Are you accessing code-server over HTTPS?

  • I am using HTTPS.

Notes

#6161

Might be causing issues reported in #6023 and #6064 as well.

And possibly #6014

Activity

  1. added
    bugSomething isn't working
    triageThis issue needs to be triaged by a maintainer
    on Apr 24, 2023
  2. changed the title [-]Account for hosts with 443 and 80 in origin check[/-] [+]Account for hosts with ports in origin check[/+] on Apr 24, 2023
  3. added and removed
    triageThis issue needs to be triaged by a maintainer
    on Apr 24, 2023
  4. changed the title [-]Account for hosts with ports in origin check[/-] [+]Account for hosts with/witohut ports in origin check[/+] on Apr 24, 2023
  5. changed the title [-]Account for hosts with/witohut ports in origin check[/-] [+]Account for hosts with/without ports in origin check[/+] on Apr 24, 2023
  6. smerschjohann commented on May 10, 2023

    @smerschjohann
    Contributor

    But I am not sure we should do anything; maybe the correct course of action is to edit the proxy config so the host and origin headers match. I have looked at other software but they all seem to do exact matches without messing around with the port. We could just edit the documentation to use $http_host.

    I just stumbled upon this issue. The X-Forwarded-Host describes the host domain, so it should not contain the port. If you want to give information about the protocol (http, https) there is another header for that: X-Forwarded-Proto. The port itself is typically irrelevant.

  7. code-asher commented on May 11, 2023

    @code-asher
    MemberAuthor

    Oh thanks! Interesting, I never noticed it explicitly excluded the port. Seems odd since Host itself does include the port.

    I believe the attack only occurs across sub-domains and not across ports since browsers would treat the latter as separate origins so with everything considered sounds like we can just ignore the port.

  8. harshbhx commented on Oct 14, 2026

    @harshbhx
    Contributor

    Hi @code-asher! I'd like to work on this, and I have a fix ready to send once my current PR (#8055) is through.

    One thing I wanted to check with you first. While implementing "ignore the port", I realised it would also let in requests from a different port on the same hostname. Browsers keep different ports as separate origins, but cookies aren't scoped by port, so a page on example.com:3000 could open a websocket to code-server and the session cookie would be sent with it. Today the exact match blocks that.

    So I went with a slightly stricter rule that still fixes both setups from the issue:

    • Hostnames must always match.
    • A forwarded host without a port is accepted, which covers nginx's $host.
    • Default ports count as no port, so example.com:443 matches https://example.com.
    • If both sides have a port, they must match, so localhost:8080 vs localhost:8081 is still rejected.
    Origin Forwarded host Today Proposed
    https://example.com example.com:443 ❌ ✅
    https://example.com:8080 example.com ❌ ✅
    http://localhost:8080 localhost:8081 ❌ ❌

    Does that sound good to you, or would you rather drop the port comparison entirely? Either way is a small change on my side.

  9. smerschjohann commented on Oct 14, 2026

    @smerschjohann
    Contributor

    I don't understand that table. The only thing that can be extended, if there really is the need is: https://domain.tld -> https://domain.tld:443 and http://domain.tld -> http://doman.tld:80

    Everything else IS NOT the same origin. So your table should never be right.

    just use the default forwarding configs and you won't have a problem, it is not a problem of code-server.

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port $server_port;
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions