Skip to content

fix(nginx): use X-Forwarded-Proto header for proper protocol forwarding#443

Open
myml wants to merge 1 commit into
iflytek:mainfrom
myml:fix-protocol
Open

fix(nginx): use X-Forwarded-Proto header for proper protocol forwarding#443
myml wants to merge 1 commit into
iflytek:mainfrom
myml:fix-protocol

Conversation

@myml

@myml myml commented May 15, 2026

Copy link
Copy Markdown
Contributor

Replace $scheme with $http_x_forwarded_proto in proxy headers to correctly
forward the original client protocol when behind a reverse proxy or load
balancer. This fixes OAuth2 authentication issues where redirects would use
the wrong protocol scheme.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Nginx configuration to use the $http_x_forwarded_proto variable for the X-Forwarded-Proto header across several location blocks. The review feedback highlights a security risk regarding header spoofing and potential functional regressions if the header is absent. It is recommended to implement a fallback to the $scheme variable. Furthermore, the reviewer identified missing X-Forwarded-For and X-Real-IP headers in several blocks, which should be added to ensure consistent upstream auditing and client identification.

Comment thread web/nginx.conf.template Outdated
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-Proto $http_x_forwarded_proto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Blindly trusting the X-Forwarded-Proto header from the client introduces a security risk (header spoofing) and can lead to functional issues if the header is missing.

  1. Security Risk: A client can spoof this header to trick the upstream into believing the connection is secure (HTTPS) when it is not. This is particularly dangerous for OAuth2 flows where protocol-sensitive redirects are generated.
  2. Functional Regression: If Nginx is accessed directly (e.g., in local development or a non-proxied environment), $http_x_forwarded_proto will be empty, resulting in an empty header being sent to the upstream. This may cause the backend to fail or default to an incorrect protocol.

A more robust approach is to use a map in the http block to fall back to $scheme if the header is empty. Since this is a template and the http block is not visible, the following inline logic provides a safer fallback.

        set $proxy_x_forwarded_proto $scheme;
        if ($http_x_forwarded_proto) {
            set $proxy_x_forwarded_proto $http_x_forwarded_proto;
        }
        proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

Comment thread web/nginx.conf.template Outdated
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

This location is missing the X-Forwarded-For header, which is inconsistent with the /api/ location and important for upstream auditing and rate limiting. Additionally, the X-Forwarded-Proto header should implement a fallback to $scheme to prevent spoofing and issues in non-proxied environments.

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        set $proxy_x_forwarded_proto $scheme;
        if ($http_x_forwarded_proto) {
            set $proxy_x_forwarded_proto $http_x_forwarded_proto;
        }
        proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

Comment thread web/nginx.conf.template Outdated
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

This location is missing the X-Forwarded-For header. It should also implement the X-Forwarded-Proto fallback logic to maintain consistency and security across all proxied endpoints, especially for authentication-related paths.

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        set $proxy_x_forwarded_proto $scheme;
        if ($http_x_forwarded_proto) {
            set $proxy_x_forwarded_proto $http_x_forwarded_proto;
        }
        proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

Comment thread web/nginx.conf.template Outdated
proxy_pass ${SKILLHUB_API_UPSTREAM};
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The /.well-known/ location is missing both X-Real-IP and X-Forwarded-For headers. It should also implement the X-Forwarded-Proto fallback logic to ensure proper client identification and security consistency.

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        set $proxy_x_forwarded_proto $scheme;
        if ($http_x_forwarded_proto) {
            set $proxy_x_forwarded_proto $http_x_forwarded_proto;
        }
        proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

Replace $scheme with $http_x_forwarded_proto in proxy headers to correctly
forward the original client protocol when behind a reverse proxy or load
balancer. This fixes OAuth2 authentication issues where redirects would use
the wrong protocol scheme.

@dongmucat dongmucat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当前改动会修复外层 TLS 终止代理后 OAuth {baseUrl} 被算成 http 的问题,方向是对的;但这里不能在默认模板里无条件信任客户端传入的 X-Forwarded-Proto

web/nginx.conf.template 现在先用 $http_x_forwarded_proto 覆盖 $scheme,再把结果转发给 /api//oauth2//login/oauth2//.well-known/ 后端请求。release compose 默认会把 web 容器作为公网入口暴露,而后端又启用了 server.forward-headers-strategy: framework,部分下载/cookie 安全判断也直接依赖 X-Forwarded-Proto。这样直连客户端只要伪造 X-Forwarded-Proto: https,就能改写后端对请求协议安全性的判断。

建议把“信任上游 forwarded proto”做成显式部署选择,或只在可信外层代理已经清洗/覆盖该 header 的场景启用;默认直连模式应继续使用 $scheme。同时最好补一条部署级/模板级验证:直连 web 时客户端自带的 X-Forwarded-Proto 不会改变传给后端的 proto,可信代理场景才允许转发 https

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants