Add domain allowlist to block SSRF via first-party proxy redirects#510
Add domain allowlist to block SSRF via first-party proxy redirects#510
Conversation
The first-party proxy followed up to 4 redirects with no restriction on redirect destinations. A signed URL pointing to an attacker-controlled origin could redirect to an internal service, enabling SSRF. Add `proxy.allowed_domains` — an opt-in list of permitted redirect target hostnames. Supports exact match and `*.`-wildcard prefix with dot-boundary enforcement. When the list is empty (default) behavior is unchanged for backward compatibility. Closes #414
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Nice hardening update overall — the redirect allowlist behavior and wildcard boundary checks look solid.
I found two follow-ups worth addressing:
-
Medium:
proxy.allowed_domainsentries are currently used as-is, so empty/whitespace patterns can make the allowlist non-empty but non-matchable, unexpectedly blocking redirects.- Evidence:
crates/common/src/proxy.rs:587,crates/common/src/proxy.rs:470,crates/common/src/settings.rs:292 - Recommendation: normalize at config load time (trim/lowercase/drop empties), and optionally validate pattern shape (
example.comor*.example.com).
- Evidence:
-
Low: tests cover
is_host_allowedlogic well, but don’t yet exercise full redirect follow enforcement end-to-end inproxy_with_redirects.- Evidence:
crates/common/src/proxy.rs:1907,crates/common/src/proxy.rs:484 - Recommendation: add one allowed + one blocked redirect-chain test through
proxy_request/redirect flow.
- Evidence:
Everything else looked good, and CI is green.
There was a problem hiding this comment.
LGTM — core SSRF hardening looks correct and CI is green.
One suggestion for follow-up: the new proxy.allowed_domains setting should be documented in the proxy and configuration guides (docs/guide/first-party-proxy.md and docs/guide/configuration.md) so operators are aware of this security control. Specifically, it would be helpful to add a [proxy] section documenting:
allowed_domainssemantics and wildcard matching rules- The default-open behavior when the setting is omitted
- A production recommendation to explicitly set the allowlist
Summary
proxy.allowed_domains— an opt-in list of permitted redirect-target hostnames supporting exact match ("example.com") and subdomain wildcard ("*.example.com") with dot-boundary enforcement to preventevil-example.combypass.Changes
crates/common/src/proxy.rsis_host_allowedhelper; enforce allowlist on each redirect hop inproxy_with_redirects; 13 unit testscrates/common/src/settings.rsallowed_domains: Vec<String>field toProxystruct with serde defaulttrusted-server.toml[proxy]section; addallowed_domainskey with commented vendor examples.env.devTRUSTED_SERVER__PROXY__ALLOWED_DOMAINSenv var overrideCloses
Closes #414
Test plan
cargo test --workspacecargo clippy --all-targets --all-features -- -D warningscargo fmt --all -- --checkcd crates/js/lib && npx vitest runcd crates/js/lib && npm run formatcargo build --bin trusted-server-fastly --release --target wasm32-wasip1fastly compute serveChecklist
unwrap()in production code — useexpect("should ...")logmacros (notprintln!)