Skip to content

fix(api/auth): gate X-Forwarded-Proto on trusted_proxies for session cookie Secure flag#5581

Merged
houko merged 1 commit into
mainfrom
fix/xforwarded-proto-trusted-proxy-gate
May 22, 2026
Merged

fix(api/auth): gate X-Forwarded-Proto on trusted_proxies for session cookie Secure flag#5581
houko merged 1 commit into
mainfrom
fix/xforwarded-proto-trusted-proxy-gate

Conversation

@houko

@houko houko commented May 22, 2026

Copy link
Copy Markdown
Contributor

Closes #5580

Summary

request_is_https in crates/librefang-api/src/server.rs previously read X-Forwarded-Proto unconditionally. session_cookie_attrs used that decision to attach Secure to session cookies. The trusted_proxies config existed (and was already consulted by client_ip.rs for the real-client-IP decision) but was not consulted here.

Two failure modes closed:

  1. Forgery (low): attacker against plain-HTTP bind sets X-Forwarded-Proto: https → daemon forces Secure on the cookie. Operator now controls when this is honored.
  2. Naive nginx without proto-forwarding (critical): real HTTPS sessions emitted cookies WITHOUT Secure. A single accidental HTTP redirect could leak the cookie on the wire. Now fails-closed at deploy time — operator notices the missing Secure flag during testing.

The gate mirrors client_ip.rs:

  • Peer in trusted_proxies AND X-Forwarded-Proto: https → honour.
  • Peer NOT in trusted_proxies → ignore the header regardless.
  • Empty trusted_proxies → never honour X-Forwarded-Proto.

Multi-value X-Forwarded-Proto: https, http uses the leftmost value (origin scheme), matching the convention.

Files changed

  • crates/librefang-api/src/server.rs (+137 / -19 — single file; pre-existing main drift NOT swept)

Tests added (5 pass)

  • xfp_honored_when_peer_is_trusted
  • xfp_ignored_when_peer_is_untrusted
  • trusted_peer_without_xfp_is_plain_http
  • empty_trusted_proxies_ignores_xfp_unconditionally
  • xfp_multi_value_uses_leftmost_when_peer_trusted

Verification

  • cargo fmt -p librefang-api -- --check — clean (only server.rs)
  • cargo check -p librefang-api --lib — clean
  • cargo test -p librefang-api --lib xfp_ — 5 passed

Refs docs/issues/x-forwarded-proto-trusted-proxies.md.

…cookie Secure flag

`request_is_https` read `X-Forwarded-Proto` unconditionally, and
`session_cookie_attrs` used that decision to attach `Secure` to the
session cookie. The `trusted_proxies` config already existed (and is
already consulted by `client_ip.rs` for the real-client-IP decision)
but was not consulted here.

Two consequences:

1. An attacker against a plain-HTTP bind could set
   `X-Forwarded-Proto: https` to force `Secure` on their own session
   cookie — low impact, but the operator should be in control of
   transport posture.

2. (Critical case) A naive nginx setup that does NOT forward
   `X-Forwarded-Proto` made real HTTPS sessions emit cookies WITHOUT
   `Secure`. A single accidental HTTP redirect on that host would leak
   the cookie on the wire — and the operator had no signal that it was
   missing.

Fix: gate `X-Forwarded-Proto` interpretation behind the existing
`trusted_proxies` allowlist, mirroring the pattern in `client_ip.rs`.
Untrusted peers can no longer forge the header. The naive-nginx case
now fails closed at deploy time — the operator notices the absent
`Secure` flag while testing and fixes the proxy config, instead of
discovering the gap post-leak.

`dashboard_login` extracts the TCP peer via `ConnectInfo<SocketAddr>`
(already wired by `into_make_service_with_connect_info` at the
listener) and passes it through alongside the existing `AppState.
trusted_proxies` allowlist.

Refs `docs/issues/x-forwarded-proto-trusted-proxies.md`.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions github-actions Bot added the size/M 50-249 lines changed label May 22, 2026
@houko
houko merged commit 394a763 into main May 22, 2026
25 of 27 checks passed
@houko
houko deleted the fix/xforwarded-proto-trusted-proxy-gate branch May 22, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Medium] X-Forwarded-Proto honored without trusted-proxy check → Secure cookie downgrade

1 participant