

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Managing Secrets
incomplete
2: Injecting Secrets at Runtime
incomplete
3: Protecting Secrets
incomplete
4: Build Artifacts and Deployment Hygiene
incomplete
5: Limiting Build Context
incomplete
6: Source Code and Config Leaks
incomplete
7: Public File Leaks
incomplete
8: Server-Side Request Forgery
incomplete
9: Defending Against SSRF
incomplete
10: Open Redirects
incomplete
11: Risks of Dependencies
incomplete
12: Auditing Dependencies
incomplete
13: Dependency Maintenance
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
The safest SSRF defense is to avoid arbitrary destinations. If a travel app needs to fetch images from two providers, accept HTTPS URLs for those exact origins and reject everything else.
Or even better, accept image IDs and build the URLs within the server code.
For example, you can explicitly parse and validate the URL before any request is sent:
const ALLOWED_IMAGE_ORIGINS = new Set([
"https://images.example.com",
"https://cdn.example.com",
]);
function parseAllowedImageUrl(rawUrl: string): URL | undefined {
let url: URL;
try {
url = new URL(rawUrl);
} catch {
return undefined;
}
if (url.protocol !== "https:") return undefined;
if (url.username || url.password) return undefined;
if (!ALLOWED_IMAGE_ORIGINS.has(url.origin)) return undefined;
return url;
}
Compare parsed origins exactly. That will make sure you reject unexpected ports and lookalike hosts like images.example.com.attacker.test.
Also give outbound requests a deadline, so a slow approved host can't hold server resources indefinitely. You can pass AbortSignal.timeout() with a value in milliseconds as the fetch signal – e.g., AbortSignal.timeout(10_000) for a 10-second deadline.
Redirects need their own policy. fetch() follows redirects by default, which means an approved URL might redirect to an internal destination like 127.0.0.1. Disable automatic redirects with redirect: "manual" and reject redirect responses before reading or returning their bodies!
An exact-origin allowlist avoids most DNS ambiguity, but if you truly need arbitrary public hosts, blocking private addresses gets much harder: you have to validate every resolved IPv4 and IPv6 address and ensure the connection uses an address you checked. A separate DNS lookup followed by a normal fetch doesn't guarantee both operations use the same address, so it doesn't stop DNS rebinding by itself.
Bearly Secure's image-preview helper can fetch any destination the server can reach. Restrict remote image previews to exact, approved HTTPS origins.
http://127.0.0.1:3000/health
https://storage.googleapis.com
Use an HTTPS URL from an allowed image host.
Image URL redirects are not allowed.
Run and submit the CLI tests from the project root.