Skip to content

fixes #249: Do not trust client-provided forwarded headers for the IP address check - #260

Merged
Fishbowler merged 1 commit into
igniterealtime:mainfrom
guusdk:249_trust-forwarded-headers-only-from-trusted-proxies
Sep 25, 2026
Merged

Fishbowler merged 1 commit into
igniterealtime:mainfrom
guusdk:249_trust-forwarded-headers-only-from-trusted-proxies

Conversation

@guusdk

@guusdk guusdk commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

The IP address used to check against the list of allowed IP addresses was taken from the 'X-Forwarded-For' header (and some variants) when present. As any client can set that header, the check could easily be bypassed.

The address is now obtained from the request's remote address only. The REST API is served by the admin console's web server, which (when configured to do so) replaces that address with the value from forwarded headers. Since Openfire 5.1.0 (OF-3261), it can be configured to do so only for requests from trusted proxies. This plugin now requires Openfire 5.1.0 or later.

The admin console page of the REST API shows a warning when the IP address check is enabled, while the admin console uses forwarded headers without a list of trusted proxies.

Note that the only relevant commit in this PR is the last one. The others are from #258 on which this PR builds. This PR should be rebased after that one gets merged.

Summary by CodeRabbit

  • Security

    • IP allowlists now check the connection’s remote address rather than client-supplied forwarding headers.
    • The REST API settings page warns when forwarded-address settings could make IP checks spoofable and links to relevant access settings.
  • Documentation

    • Added guidance for IP allowlists and configuring trusted reverse proxies, including forwarding-header risks and restart requirements.
  • Compatibility

    • Openfire 5.1.0 or later is now required.

@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Warning

Review limit reached

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 2ba6aaa9-7d05-4b65-88a5-16b942821574

📥 Commits

Reviewing files that changed from the base of the PR and between dc7c536 and f005502.

⛔ Files ignored due to path filters (1)
  • src/web/images/warning-16x16.gif is excluded by !**/*.gif
📒 Files selected for processing (8)
  • changelog.html
  • plugin.xml
  • pom.xml
  • readme.md
  • src/java/org/jivesoftware/openfire/plugin/rest/AuthFilter.java
  • src/java/org/jivesoftware/openfire/plugin/rest/RESTServicePlugin.java
  • src/java/org/jivesoftware/openfire/plugin/rest/service/UserServiceLegacy.java
  • src/web/rest-api.jsp

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 4e042e27-ff92-4297-acdd-4517c64f597d

📥 Commits

Reviewing files that changed from the base of the PR and between 740c935 and dc7c536.

⛔ Files ignored due to path filters (1)
  • src/web/images/warning-16x16.gif is excluded by !**/*.gif
📒 Files selected for processing (8)
  • changelog.html
  • plugin.xml
  • pom.xml
  • readme.md
  • src/java/org/jivesoftware/openfire/plugin/rest/AuthFilter.java
  • src/java/org/jivesoftware/openfire/plugin/rest/RESTServicePlugin.java
  • src/java/org/jivesoftware/openfire/plugin/rest/service/UserServiceLegacy.java
  • src/web/rest-api.jsp

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The REST API plugin now checks request remote addresses against configured IP allowlists. It also detects a forwarded-header configuration that can make the check spoofable, displays a warning on the REST API page, and documents proxy configuration. The minimum Openfire version is now 5.1.0.

Changes

REST API allowlist and proxy trust

Layer / File(s) Summary
Server baseline and allowlist checks
plugin.xml, pom.xml, changelog.html, src/java/org/jivesoftware/openfire/plugin/rest/AuthFilter.java, src/java/org/jivesoftware/openfire/plugin/rest/service/UserServiceLegacy.java
The plugin and Maven parent now require Openfire 5.1.0. Both allowlist checks use the request remote address instead of forwarded-address headers.
Spoofability warning and proxy guidance
src/java/org/jivesoftware/openfire/plugin/rest/RESTServicePlugin.java, src/web/rest-api.jsp, readme.md, changelog.html
The plugin checks whether an allowlist is configured while forwarded-header handling is enabled and no trusted proxies are configured. The REST API page displays a warning when that check returns true. The README and changelog describe the related proxy behavior and configuration.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant RESTAPIJSP
  participant RESTServicePlugin
  participant AdminConsolePlugin
  Browser->>RESTAPIJSP: Request REST API page
  RESTAPIJSP->>RESTServicePlugin: Check whether allowlist check is spoofable
  RESTServicePlugin->>AdminConsolePlugin: Read forwarded-header and trusted-proxy settings
  AdminConsolePlugin-->>RESTServicePlugin: Return configured settings
  RESTServicePlugin-->>RESTAPIJSP: Return spoofability result
  RESTAPIJSP-->>Browser: Render warning when result is true
Loading

Merge Risk: ⚪ Minimal · up to dc7c5

The IP allowlist change is ready to merge after normal checks. Administrators must restart the admin console for proxy-setting changes to take effect, as documented.

Security Architecture Review

Security architecture risk: 🔵 Low · up to dc7c5

The change removes a direct way to spoof an allowed IP address. Protection still depends on the server and reverse proxies being configured to trust forwarded addresses only from the right proxies.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — If the web server accepts forwarded addresses from an untrusted peer, that peer can influence the address checked by both REST allowlists. Whether any deployed instance has that exposure is unknown.

Security Findings and Attack Paths

  • inferred — The changed checks remove the plugin’s direct forwarding-header spoofing path. A web-server configuration that still accepts such headers from untrusted peers remains a conditional attack path, not an exposure shown to have been introduced by this PR.

Trust Boundaries and Controls

  • observed — The enforcement boundary is the request remote address supplied to the plugin, followed by allowlist membership and, on the primary REST path, authorization checks. The warning is separate from those controls.

Resilience and Maintainability Implications

  • inferred — During a pending web-server restart, a configured-safe but active-unsafe state can leave the new warning absent. This limits the warning’s value as an indicator of current protection; it does not change the request check.

Hardening Proposals

  • proposed — Make the admin-page warning distinguish configured settings from active settings, or prominently indicate when a restart is pending; independently verify that trusted proxies replace untrusted client forwarding headers.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (5 skipped: 5… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing client-provided forwarded headers from bypassing the REST API IP address check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (5 skipped: 5 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@guusdk
guusdk force-pushed the 249_trust-forwarded-headers-only-from-trusted-proxies branch from 1e1171a to c4c2b66 Compare September 25, 2026 10:57
@guusdk
guusdk requested a review from Fishbowler September 25, 2026 10:57
…ers for the IP address check

The IP address used to check against the list of allowed IP addresses was taken from the 'X-Forwarded-For' header (and some variants) when present. As any client can set that header, the check could easily be bypassed.

The address is now obtained from the request's remote address only. The REST API is served by the admin console's web server, which (when configured to do so) replaces that address with the value from forwarded headers. Since Openfire 5.1.0 (OF-3261), it can be configured to do so only for requests from trusted proxies. This plugin now requires Openfire 5.1.0 or later.

The admin console page of the REST API shows a warning when the IP address check is enabled, while the admin console uses forwarded headers without a list of trusted proxies.
@Fishbowler
Fishbowler force-pushed the 249_trust-forwarded-headers-only-from-trusted-proxies branch from dc7c536 to f005502 Compare September 25, 2026 14:20
@Fishbowler
Fishbowler merged commit 6250f00 into igniterealtime:main Sep 25, 2026
6 checks passed
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