Guard UnifiedPush endpoints against SSRF#25
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b9a7574a8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ); | ||
|
|
||
| let response = self.client.post(device_token).json(&payload).send().await?; | ||
| let response = self.client.post(endpoint_url).json(&payload).send().await?; |
There was a problem hiding this comment.
Revalidate or disable UnifiedPush redirects
When a registered public HTTPS endpoint returns a redirect, this request uses reqwest's default redirect policy, which follows redirects automatically, but only the original endpoint_url was validated. In that scenario a valid distributor can redirect the server to an unvalidated scheme or host (for example outside UNIFIEDPUSH_ALLOWED_HOSTS_REGEX, or a private IP literal that does not require DNS resolution), bypassing the SSRF/TLS policy this change is adding. Disable redirects for UnifiedPush or install a redirect policy that validates every Location before following it.
Useful? React with 👍 / 👎.
AndreaDiazCorreia
left a comment
There was a problem hiding this comment.
Thanks for tackling this. A few things need to change before merge:
Blocking
- Redirects bypass the SSRF guard. The shared reqwest::Client uses the default redirect policy, so a distributor can respond 302 Location: https://10.0.0.1/... (literal IP skips PublicDnsResolver) or redirect to a public host outside
- UNIFIEDPUSH_ALLOWED_HOSTS_REGEX. Same concern Codex raised. Please disable redirects on the UnifiedPush dispatch path or install a policy that re-runs validate_endpoint_url on every Location. Note http_client is shared with FCM — a separate client for UnifiedPush is probably cleaner.
- New direct deps. regex and hyper are added to Cargo.toml. Per CLAUDE.md constraint 6, that needs explicit maintainer sign-off. hyper is unavoidable for reqwest::dns::Resolve; regex could be swapped for suffix matching if we want to avoid it.
- /api/register fixture regression. URL-shaped Android tokens that previously got 200 OK now return 400 Invalid UnifiedPush endpoint URL, breaking the byte-identity invariant in CLAUDE.md constraint 3. Either document a new exception in CLAUDE.md (like the whitelist 403) or move the rejection to dispatch-only.
The IPv4 classifier, double-validation pattern, fail-fast on bad regex, and test coverage on the acceptance criteria all look great. Once these three are addressed I think this is good to merge.
Summary
Fixes #4.
Also covers the registration-side validation requested in #13.
Validation
Note: cargo test --doc reports no library targets for this binary crate.