← Back to PRs

#16197: feat(ssrf): enhance protection with comprehensive cloud metadata blocking

by bianbiandashen open 2026-02-14 13:04 View on GitHub →
stale size: S
## Summary Expand SSRF protection to comprehensively block cloud metadata service endpoints across major providers. ## Problem The current implementation only blocks `localhost` and `metadata.google.internal`. However, cloud metadata services exist on multiple providers and can be accessed via: 1. Provider-specific hostnames 2. Direct IP addresses (e.g., 169.254.169.254) 3. DNS rebinding attacks that resolve to metadata IPs Successful SSRF attacks against metadata services can leak: - Instance credentials (IAM roles, service account tokens) - Cloud provider configuration - Sensitive environment variables - Network topology information ## Solution ### Blocked Hostnames | Provider | Hostname | |----------|----------| | GCP | `metadata.google.internal`, `metadata.goog` | | AWS | `instance-data` | | Azure | `metadata.azure.com` | | Alibaba | `100.100.100.200` | | DigitalOcean | `metadata.digitalocean.com` | | Oracle Cloud | `metadata.oraclecloud.com` | | Kubernetes | `kubernetes.default`, `kubernetes.default.svc` | ### Blocked IP Addresses | IP | Provider/Purpose | |----|------------------| | `169.254.169.254` | AWS, GCP, Azure, DigitalOcean (link-local) | | `fd00:ec2::254` | AWS IMDSv2 IPv6 endpoint | | `100.100.100.200` | Alibaba Cloud | ### New Function Added `isBlockedMetadataIp()` to detect direct IP access: ```typescript export function isBlockedMetadataIp(address: string): boolean ``` This function: - Normalizes the input (strips brackets, handles case) - Handles IPv4-mapped IPv6 addresses (`::ffff:169.254.169.254`) - Checks against the `BLOCKED_METADATA_IPS` set ### Integration Points The metadata IP check is called in `resolvePinnedHostnameWithPolicy()`: 1. Before DNS resolution (direct IP access) 2. After DNS resolution (DNS rebinding attacks) ## Security References - [AWS IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html) - [GCP Metadata Server](https://cloud.google.com/compute/docs/metadata/overview) - [Azure IMDS](https://docs.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service) - [OWASP SSRF Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html) ## Test Plan - [x] Verify existing localhost/metadata.google.internal blocking still works - [x] Verify new cloud hostnames are blocked - [x] Verify 169.254.169.254 is blocked when accessed directly - [x] Verify DNS resolution to metadata IPs is blocked - [x] Verify IPv4-mapped IPv6 handling works <!-- greptile_comment --> <h3>Greptile Summary</h3> Expands SSRF protection to block cloud metadata service endpoints across major providers (AWS, GCP, Azure, Alibaba, DigitalOcean, Oracle Cloud, Kubernetes). Adds a new `isBlockedMetadataIp()` function for direct IP-based metadata blocking, integrated at both pre-DNS and post-DNS resolution points. - The new blocked hostnames (`metadata.goog`, `instance-data`, `metadata.azure.com`, `metadata.digitalocean.com`, `metadata.oraclecloud.com`, `kubernetes.default`, `kubernetes.default.svc`) are genuine additions not previously covered. - The three IPs in `BLOCKED_METADATA_IPS` (`169.254.169.254`, `fd00:ec2::254`, `100.100.100.200`) are all already caught by the existing `isPrivateIpAddress()` function (link-local, private IPv6, and CGNAT ranges respectively), so `isBlockedMetadataIp()` serves as defense-in-depth rather than closing a gap. - No unit tests were added for the new `isBlockedMetadataIp` function or the expanded hostname list. Given this is security-critical code, test coverage for `isBlockedMetadataIp` (including edge cases like bracket-wrapped IPs and mapped IPv6) would strengthen confidence in the implementation. <h3>Confidence Score: 4/5</h3> - This PR is safe to merge — it adds additional SSRF protections without modifying existing behavior. - The changes are additive and security-hardening. All new blocked IPs are already caught by the existing `isPrivateIpAddress` check, so the new `isBlockedMetadataIp` function provides defense-in-depth. The new blocked hostnames are genuine additions. No existing behavior is modified. The main gap is the absence of unit tests for the new function, which would be expected for security-critical code. Score is 4 rather than 5 due to missing test coverage. - No files require special attention beyond the minor style issue flagged in `src/infra/net/ssrf.ts`. <sub>Last reviewed commit: f7e055d</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs