Skip to content

fix: trust forwarded client IPs only behind configured proxies - #7614

Merged
masenf merged 2 commits into
reflex-dev:mainfrom
harsh21234i:fix/7601-trusted-proxy-client-ip
Oct 22, 2026
Merged

masenf merged 2 commits into
reflex-dev:mainfrom
harsh21234i:fix/7601-trusted-proxy-client-ip

Conversation

@harsh21234i

@harsh21234i harsh21234i commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #7601. router.session.client_ip previously trusted the leftmost X-Forwarded-For value, which clients can spoof.

The connection peer address is now used by default. Applications behind trusted reverse proxies can set trusted_proxy_hops to select the client address from the forwarded chain.

Changes

  • Add trusted_proxy_hops, defaulting to 0; reject negative and non-integer values.
  • Use the configured hop count to read the address from the right side of X-Forwarded-For. Fall back to the connection peer if the header is missing or too short.
  • Document the setting and its proxy-trust requirements.
  • Add regression tests and changelog entries for reflex and reflex-base.

Testing

  • tests/units/test_app.py and tests/units/test_config.py: 350 passed, 2 skipped
  • Pyright, Ruff, and codespell passed

View guided diff

@harsh21234i
harsh21234i requested review from a team and Alek99 as code owners October 20, 2026 09:13

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 8 files

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread news/+7601-trusted-proxy-client-ip.breaking.md
Comment thread packages/reflex-base/news/+7601-trusted-proxy-client-ip.feature.md
Comment thread tests/units/test_config.py Outdated
@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with no outstanding findings.

Summary

The PR makes router.session.client_ip ignore forwarded headers by default. Apps behind trusted proxies can opt in with trusted_proxy_hops.

  • Client IPs come from the connection peer unless trusted proxy hops are configured.

No new actionable issues were found in the changes since the previous review.

Reviews (2) · Last reviewed commit: "fix: address trusted proxy review feedba..." · Reviewed by Greptile

Comment thread tests/units/test_config.py Outdated
@codspeed

codspeed Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 10 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 148 untouched benchmarks


Comparing harsh21234i:fix/7601-trusted-proxy-client-ip (5ca62ee) with main (d3f4ab1)

Open in CodSpeed

@masenf masenf added documentation Improvements or additions to documentation bug Something isn't working breaking Public API facing change considered for minor release bump pre-v1.0 labels Oct 21, 2026 — with ChatGPT Codex Connector
@masenf masenf added the on deck PRs lined up to review / merge next label Oct 21, 2026

@masenf masenf 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.

thanks for implementing this security enhancement

@masenf
masenf merged commit 8856d75 into reflex-dev:main Oct 22, 2026
180 of 181 checks passed
masenf added a commit that referenced this pull request Oct 23, 2026
#7646)

* Correct 0.10.1 news fragments and document REFLEX_BACKEND_START_METHOD

The 7258 fragment described the opposite of what #7304 does (it raises an
error for a missing __init__.py instead of loading the app), the repeated
headers fragment still claimed client_ip came from the first x-forwarded-for
hop after #7614 made that depend on trusted_proxy_hops, and the 7261 fragment
belonged to a docs-only change. Add the backend start method variables to the
self-hosting docs; they were only described in environment.py.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016T8wWv8bUUSzRHNGpKbSqW

* Keep the 7258 fragment and scope the start method docs to Granian

#7304 ended up passing Granian the configured module target, so the
original fragment was accurate. The start method variables are only read
on the Granian code paths.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016T8wWv8bUUSzRHNGpKbSqW

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Public API facing change considered for minor release bump pre-v1.0 bug Something isn't working documentation Improvements or additions to documentation on deck PRs lined up to review / merge next

Projects

None yet

Development

Successfully merging this pull request may close these issues.

client_ip trusts the client-controlled leftmost X-Forwarded-For entry

2 participants