Cloud Metadata SSRF
Your app fetches user-supplied URLs without blocking cloud metadata endpoints like 169.254.169.254, letting attackers steal your cloud credentials via SSRF.
How It Works
Every cloud VM (AWS EC2, GCP, Azure) has an internal metadata service at a link-local address (169.254.169.254). This service returns the instance's IAM credentials, including temporary AWS access keys, with a simple HTTP GET — no authentication required from within the instance. If your app fetches any URL a user provides without validating it, an attacker supplies http://169.254.169.254/latest/meta-data/iam/security-credentials/ and steals your cloud credentials.
// BAD: fetching user-supplied URL with no validation
export async function POST(req: Request) {
const { url } = await req.json();
// Attacker sends: http://169.254.169.254/latest/meta-data/iam/security-credentials/
const response = await fetch(url);
return Response.json({ content: await response.text() });
}// GOOD: validate URL is external and not a private/metadata address
function isSafeUrl(url: string): boolean {
const parsed = new URL(url);
const blocklist = ['169.254.169.254', 'metadata.google.internal', '169.254.170.2'];
return parsed.protocol === 'https:' && !blocklist.includes(parsed.hostname);
}
export async function POST(req: Request) {
const { url } = await req.json();
if (!isSafeUrl(url)) return Response.json({ error: 'Invalid URL' }, { status: 400 });
const response = await fetch(url);
return Response.json({ content: await response.text() });
}Real-World Example
The 2019 Capital One breach was caused exactly by this: an SSRF vulnerability allowed the attacker to hit the EC2 metadata endpoint and retrieve IAM credentials, which were then used to download 100 million customer records from S3. It remains one of the most well-documented SSRF-to-cloud-takeover attacks.
How to Prevent It
- Block requests to 169.254.169.254, metadata.google.internal, 169.254.170.2, and fd00:ec2::254 (IPv6 equivalent)
- Also block private IP ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and localhost
- Use IMDSv2 on AWS EC2 which requires a PUT request with a session token — simple GET requests to the metadata endpoint fail
- Apply least-privilege IAM roles to your instances — even if credentials are stolen, their blast radius is limited
- Validate that user-supplied URLs use HTTPS and resolve to public IP addresses before fetching
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
S3 Bucket Public Access
criticalYour S3 bucket is publicly readable due to a public ACL, disabled Block Public Access settings, or a wildcard bucket policy — anyone on the internet can list and download your files.
AWS Credentials Hardcoded
criticalAWS access keys (starting with AKIA) or secret access keys are hardcoded in your source code, giving anyone who reads the code full access to your AWS account.
IAM Overly Permissive Policy
highYour IAM policy uses Action: '*' or Resource: '*', granting far more permissions than needed and turning any credential leak into a full account takeover.
Cloud Storage CORS Misconfiguration
mediumYour S3 or GCS bucket has CORS configured with origin: '*' or AllowedMethods: ['*'], letting any website read your storage responses and potentially access private data.