Webhook-url-http-3a-2f-2f169.254.169.254-2fmetadata-2fidentity-2foauth2-2ftoken
If your system accepts webhook URLs from users, you are vulnerable. Here is the fix:
1. Implement an Allowlist
Do not allow arbitrary IPs. Only allow outbound requests to known SaaS vendor IPs (e.g., slack.com, github.com). Never allow 169.254.0.0/16.
2. Filter Private IPs (The Code Fix) Before making any webhook request, validate the URL:
# Dangerous: Do not do this.
# requests.get(user_provided_webhook_url)
If you are developing a feature:
Ensure that your application treats 169.254.169.254 as a protected internal IP. Do not forward responses from this endpoint to external users, as this would leak sensitive identity tokens.
If you found this in logs:
If you see strings like this in your ingress logs (incoming webhook requests), you are likely being actively scanned or attacked.
Here is how to lock it down:
1. Patch SSRF Vulnerabilities
2. Harden the Metadata Service
3. Network Controls
The attacker is counting on a common developer mistake: Blindly fetching a URL from an untrusted webhook.
If you need an OAuth2 token from Azure Managed Identity inside a VM or Azure Function, you do not use a webhook. You use the standard IMDS endpoint like this:
# From inside an Azure VM with Managed Identity enabled
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -H 'Metadata: true'
That returns a JSON response with an access_token. Metadata service hardening
You never put this URL into a third-party webhook configuration field.
If you spend any time in cloud security or penetration testing, you will eventually memorize one IP address: 169.254.169.254.
This is the link-local address (RFC 3927) reserved for cloud metadata services. When an attacker sends you a webhook URL that looks like http://169.254.169.254/metadata/identity/oauth2/token, they aren't trying to send you a friendly notification. They are trying to trick your server into stealing its own cloud identity tokens.
The input string is URL-encoded. Decoding the hexadecimal sequences reveals the actual target: Application-level controls