Fix SSRF allow-list bypass via URL parser differential - #365
Merged
Pino de Candia (pinodeca) merged 2 commits intoAug 29, 2026
Merged
Conversation
Parse each request URL once and use the canonical value for scheme validation, endpoint checks, and transport. This prevents backslash authority parsing differences from approving a host other than the request target. Apply the same validation path to regular and multipart requests, with unit and end-to-end coverage for exact domains, suffixes, and IP literals.
There was a problem hiding this comment.
Pull request overview
This PR hardens df.http() SSRF protections by eliminating URL-parser differentials: it parses request URLs once using the same WHATWG-based parser that reqwest uses, validates that canonical Url (scheme + allow-list), and then sends that exact value. It also applies the same validation path to multipart requests and documents the updated security model.
Changes:
- Introduce canonical URL parsing (
parse_request_url) and refactor SSRF validation to operate onUrl(not raw strings) for scheme + allow-list enforcement. - Update HTTP and multipart activities to validate and send the same parsed URL; disable proxy discovery in restricted builds.
- Add unit + E2E regressions for backslash authority termination, percent-decoding/canonicalization, exact/suffix domains, and IP literal bypass attempts; update docs and changelog.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/sql/06_http_and_ssrf.sql | Adds E2E regression covering backslash authority-termination SSRF bypass vectors. |
| src/ssrf.rs | Refactors SSRF scheme/allow-list validation to consume a single canonical Url; removes hand-rolled host parsing. |
| src/dsl.rs | Switches DSL-time scheme validation to precheck_url_scheme (advisory precheck). |
| src/activities/execute_multipart.rs | Parses URL once, validates canonical URL, and uses it for the multipart request. |
| src/activities/execute_http.rs | Parses URL once, validates canonical URL, uses it for transport; disables proxies in restricted builds; adds proxy-hardening test. |
| docs/http-security.md | Documents “one parse, one URL” model and proxy disabling in restricted builds. |
| CHANGELOG.md | Notes SSRF hardening change in unreleased security section. |
| Cargo.toml | Adds direct url dependency to align parsing/types with reqwest URL handling. |
| Cargo.lock | Records url as a direct dependency of the crate. |
Suppressed comments (1)
src/activities/execute_http.rs:312
- Lock the new ENV_MUTEX for the duration of the test before setting/unsetting proxy environment variables. Without this, concurrent tests can observe partially-modified proxy env state and behave unpredictably.
let _http_proxy_upper = EnvGuard::set("HTTP_PROXY", &proxy_url);
let _http_proxy_lower = EnvGuard::set("http_proxy", &proxy_url);
let _no_proxy_upper = EnvGuard::remove("NO_PROXY");
let _no_proxy_lower = EnvGuard::remove("no_proxy");
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+269
to
+273
| use super::*; | ||
| use std::ffi::OsString; | ||
| use std::io::{Read, Write}; | ||
| use std::net::TcpListener; | ||
| use std::sync::mpsc; |
| .get("http://pg-durable-proxy-test.invalid/") | ||
| .send() | ||
| .await; | ||
| stop_tx.send(()).unwrap(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Security impact
The previous allow-list extracted a host with a hand-written parser, while reqwest interpreted the URL using WHATWG rules. A backslash could therefore terminate the authority for reqwest but remain part of the authority seen by the allow-list, allowing validation of a different host from the request target.
Validation
cargo fmt -p pg_durable -- --checkcargo check --features pg17,http-allow-test-domainscargo clippy --features pg17,http-allow-test-domains -- -D warningscargo test --features pg17,http-allow-test-domains ssrf::tests(61 passed)./scripts/test-e2e-local.sh --verbose 06_http_and_ssrf(passed)