Skip to content

[SSI-468] Improve error message for SSRF host validation#24285

Open
shiroginne wants to merge 4 commits into
devfrom
bug/ssi-468-nextcloud-anbindung-fehler-nextcloud-hostname-has-no-public-ip-addresses
Open

[SSI-468] Improve error message for SSRF host validation#24285
shiroginne wants to merge 4 commits into
devfrom
bug/ssi-468-nextcloud-anbindung-fehler-nextcloud-hostname-has-no-public-ip-addresses

Conversation

@shiroginne

Copy link
Copy Markdown
Contributor

Ticket

SSI-468

What are you trying to accomplish?

Self-titled.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@shiroginne shiroginne self-assigned this Jul 15, 2026
@shiroginne shiroginne changed the title Improve error message for SSRF host validation [SSI-468] Improve error message for SSRF host validation Jul 15, 2026
@shiroginne
shiroginne requested a review from a team July 15, 2026 13:28
@shiroginne
shiroginne marked this pull request as ready for review July 15, 2026 13:28
Comment thread lib/open_project/httpx_ssrf_filter.rb Outdated
if addrs.empty?
raise ServerSideRequestForgeryError,
"#{@origin.host} resolves only to private IP addresses, blocked to prevent SSRF. " \
"To allow this host, add its IP addresses to OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST."

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.

🔴 This whole class we are looking at here is intended to be deleted.

As I said, there is a new version of httpx that allows to directly allowlist ip addresses in the built-in SSRF filter. We intended to switch over to that.

This also means that we'll not be able to change the error that's raised directly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh ok, is there any date or release when we are planning to remove this class? We could have a temp solution as is, and then figure out the new httpx's things 🤔

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.

Sorry, I thought this was clear before.

tl;dr (most of this we discussed IRL today):

  • httpx 1.8.0 introduces new options to ssrf_filter that make this class obsolete
    • this version is already released, but hasn't yet been picked up by Dependabot
  • Any solution that works without touching this class here, should work after such an update as well
  • I would not pursue the solution proposed here, because it's essentially a throw-away solution that would only persist for a short moment (and for that, the issue doesn't seem critical enough to me, personally)

@shiroginne shiroginne Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, let's stay in this conversation even though the code has changed completely.

The new approach is to use httpx 1.8.0 with its new SSRF filter plugin.
As for the error message, we'll inject a "decorator", which catches and then re-raises the error with our message.
Fun fact: the creator of httpx suggested a similar approach 😅 (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Update: In recent httpx updates, the method refresh_token on OAuthSession became private.
To make it work again, the private method is called. Not a great solution. To cover the next updates, a spec was created.

@github-actions

Copy link
Copy Markdown

Caution

The provided work package version does not match the core version

Details:

Please make sure that:

  • The work package version OR your pull request target branch is correct

@shiroginne
shiroginne force-pushed the bug/ssi-468-nextcloud-anbindung-fehler-nextcloud-hostname-has-no-public-ip-addresses branch from 69c398f to e3deb43 Compare July 17, 2026 14:02
To make it work again, the private method shall be called. Not a great solution. To cover the next updates, a spec was created.

super
rescue HTTPX::ServerSideRequestForgeryError
raise OpenProject::ServerSideRequestForgeryError,

@NobodysNightmare NobodysNightmare Jul 17, 2026

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.

🔴 Did you try out whether this works as intended?

I am surprised, because HTTPX catches this error internally and then reacts on it, eventually resulting in returning an error response (instead of raising the error to the outside world).

I guess this is also the reason why you couldn't add a rescue statement outside of HTTPX. The reason of my question is that you replace HTTPX::ServerSideRequestForgeryError with a different error class. Thus HTTPX is not able to catch this anymore. I'd expect that the changed code (as opposed to the original code) would raise the OpenProject::ServerSideRequestForgeryError into the face of the caller of an httpx.get instead of returning it as an error response.

edit: I just noticed that the OpenProject error inherits from the other one... Why do we do this at all then? This will never be visible to the outside?

edit 2: Okay, apparently it's accessible as result.error... I still don't know why we do it xD

module AuthenticationStrategies
# httpx keeps refreshed tokens inside OAuthSession without public readers,
# so #update_token digs them out via #send. Pinned here so that an httpx
# upgrade that moves them fails this spec first.

@NobodysNightmare NobodysNightmare Jul 17, 2026

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.

💚

I am still convinced that we should not use the HTTPX implementation of OAuth at all, because it's not intended to be used the way that we use it.

(But that's wildly out of scope for your PR)

@github-actions

Copy link
Copy Markdown

Warning

Flaky specs

  • rspec ./modules/team_planner/spec/features/query_handling_spec.rb[1:3:1:1]
  • rspec ./spec/features/roles/report_spec.rb[1:1]
  • rspec ./spec/features/roles/report_spec.rb[1:2]
  • rspec ./spec/features/roles/report_spec.rb[1:3]
🤖 Ask Copilot to investigate

Copy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer.

@copilot The following spec(s) are flaky in CI (first seen on PR #24285, linked for reference only):

- `rspec ./modules/team_planner/spec/features/query_handling_spec.rb[1:3:1:1]`
- `rspec ./spec/features/roles/report_spec.rb[1:1]`
- `rspec ./spec/features/roles/report_spec.rb[1:2]`
- `rspec ./spec/features/roles/report_spec.rb[1:3]`

Treat this as a standalone task, unrelated to PR #24285. Create a new branch from origin/dev and open a new pull request targeting dev — do not stack it on PR #24285 or reuse that branch.

Follow the playbook in docs/development/testing/handling-flaky-tests/README.md to find the root cause and fix the underlying race — do not skip, delete, or weaken the spec to make it pass; disabling is a last resort per the playbook, and only with a bug ticket. Verify the fix by running the spec(s) repeatedly (e.g. `script/bulk_run_rspec --run-count 10`).

If you cannot reproduce the flake or are not confident in a fix after reasonable investigation, do not fabricate a change or skip the spec to force CI green. Instead, leave the pull request in draft and document what you tried, the suspected cause, and any leads in its description, then assign @shiroginne to take over.

Once the fix is verified, title the PR after the spec(s) it fixes, and use the PR description to explain the root cause, how the change resolves it, and the before/after results. Label the PR `flaky-spec`, assign @shiroginne, and request a review from @shiroginne.
On every commit, set @shiroginne as the sole co-author with a `Co-authored-by:` trailer (use their GitHub no-reply email so it links to their account), so it is traceable who dispatched the fix.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants