Any API that accepts a URL and then fetches it is asking its own server to make requests on behalf of an untrusted caller, from inside your network and with your cloud identity. OWASP lists this as API7:2023 Server Side Request Forgery in the OWASP API Security Top 10 2023. This guide treats API7 as a requirement set for API teams: where URL-consuming features hide in API designs (webhooks, imports, previews, custom SSO, GraphQL mutations), how to turn each OWASP prevention item into a concrete control and test, how to design API contracts that avoid accepting URLs at all, and what evidence an assessor should collect. It is written for API developers, platform teams and AppSec assessors. The underlying techniques (URL validation, DNS rebinding defence, metadata service hardening, egress filtering) are covered in depth in the SSRF Prevention Guide; this page applies them to APIs. For the whole list see Top 10 API Security Risks.
Key takeaways
- Find every URL-consuming field first: webhooks, "import from URL", link previews, avatar URLs, OIDC discovery and JWKS URLs, PDF and image renderers. You cannot protect what the API inventory does not list.
- Prefer identifiers over URLs in the contract: an API that accepts
integration_idand builds the URL server-side removes most of the attack surface before any validation is written. - Validate at registration and at every delivery: webhook destinations must be checked when stored and again at connection time, against the resolved IP, with redirects disabled.
- Never return raw fetched responses: OWASP's own webhook scenario leaks cloud credentials because a "test request" echoed the response back to the caller.
- Assume validation will fail somewhere: isolate fetchers on their own network path with deny-by-default egress and a minimal cloud role, so a bypass reaches nothing valuable.
What API7 covers
OWASP defines SSRF flaws as occurring when an API fetches a remote resource without validating the user-supplied URL, so that an attacker can coerce the application to send a crafted request to an unexpected destination, even when that destination is protected by a firewall or VPN. OWASP gives two reasons the risk is growing: modern features encourage fetching resources from user input (webhooks, file fetching from URLs, custom SSO, URL previews), and cloud providers, Kubernetes and Docker expose management and control channels over HTTP on predictable, well-known paths. OWASP also states plainly that SSRF risk cannot always be completely eliminated, so protection must be chosen against business need.
| OWASP rating factor | API7:2023 value | What it means for API teams |
|---|---|---|
| Exploitability | Easy | Only an endpoint that accepts a client-provided URI is needed |
| Prevalence | Common | Missing or improper URI validation is a common issue |
| Detectability | Easy | Basic SSRF is easy to find; blind SSRF (no response returned) needs more effort |
| Technical impact | Moderate | Internal service enumeration, information disclosure, firewall bypass, denial of service, or use of the server as a proxy; much higher where cloud credentials are reachable |
The weakness is CWE-918 Server-Side Request Forgery, and the corresponding attack pattern is CAPEC-664 Server Side Request Forgery. Note that OWASP's official risk name is written "Server Side Request Forgery" without a hyphen; the common spelling "server-side" refers to the same risk.
Where SSRF hides in API designs
| API feature | Typical field or operation | Why it is risky | Design control |
|---|---|---|---|
| Webhooks and notification channels | callback_url, webhook.url, "send test event" | Arbitrary destination by design; test calls often return the response | Registration-time and delivery-time validation, dedicated egress, status code only in the test result |
| Import from URL | file_url, picture_url, CSV or feed import | Fetcher runs inside the network; timing reveals open ports (OWASP scenario 1) | Allow list of origins and media types, or direct upload instead |
| Link previews and unfurling | Message body URLs, og:image fetch | Triggered without an explicit URL field, so often missed in reviews | Separate preview service with public-only egress |
| Custom SSO and federation | OIDC issuer discovery, jwks_uri, SAML metadata URL | Server fetches metadata and keys from a tenant-supplied URL | Admin-only configuration, HTTPS only, public addresses only, fetched once and cached |
| Document and image rendering | HTML-to-PDF, SVG, office conversion | Embedded resources (<img>, <link>, XML entities) are fetched by the renderer | Renderer in a sandbox with no network or a strict allow list |
| GraphQL mutations | Mutations that create integrations (OWASP scenario 2) | URL arguments buried in nested input types escape REST-centric scanners | Schema review for URL-typed arguments, same validation library |
| Integration connectors and AI tools | "Connect your instance" base URL, agent fetch tools | Destinations controlled by tenants or by model output | Allow-listed connector catalogue; agent fetch tools through a filtered proxy |
Third-party responses fetched this way also need safe handling on the way back in. See the OWASP API Top 10 API10 Unsafe Consumption of APIs Guide.
From OWASP prevention items to testable requirements
| OWASP prevention item | Concrete control | Evidence an assessor can check |
|---|---|---|
| Isolate the resource fetching mechanism in your network | Fetchers run as a separate service or workload with its own subnet, security group and egress proxy; no route to internal ranges or metadata endpoints | Network policy or security group rules; proxy configuration; a test request to an internal address that fails at the network layer |
| Use allow lists of remote origins, URL schemes and ports, and accepted media types | Per feature: exact host allow list where destinations are known; https only, port 443; content type check on the response before processing | Configuration file or code with the lists; unit tests for rejected schemes (file:, gopher:, ftp:) and ports |
| Disable HTTP redirections | HTTP client created with redirect following off; any needed redirect re-validated as a new request | Client construction code; test with a redirect to an internal address |
| Use a well-tested and maintained URL parser | One shared parser for validation and request building, so both see the same host | Single fetch library used across services; tests with parser-confusion inputs |
| Validate and sanitise all client-supplied input | Schema validation at the gateway (format, length, scheme) plus server-side validation of the resolved IP at connection time | OpenAPI or GraphQL schema; validator tests including IPv6 and alternative IP encodings |
| Do not send raw responses to clients | Return only a status (success, failed, timed out) or a processed, type-checked result | API response samples for test and import endpoints |
OWASP ASVS 5.0 states the same expectations in verifiable form: V1.3.6 (Level 2) requires validating untrusted data against an allow list of protocols, domains, paths and ports before calling another service; V15.3.2 (Level 2) requires backend calls to external URLs not to follow redirects unless intended; and V1.5.3 (Level 3) requires different parsers for the same data type to parse consistently.
Designing API contracts that resist SSRF
- Accept references, not locations: for known integrations, let the caller choose an
integration_idor a tenant subdomain from a validated list, and build the full URL server-side with a fixed scheme, host pattern and path. The OWASP SSRF Prevention Cheat Sheet recommends exactly this for known destinations. - Offer upload instead of fetch: where a URL import is a convenience, a direct upload (with its own file validation) removes server-side fetching entirely.
- Type URL fields in the schema: mark URL parameters with
format: uriin OpenAPI and a dedicated scalar in GraphQL, and add a pattern requiringhttps://. This makes URL fields discoverable by inventory tools and enforceable at the gateway, though schema checks alone do not stop SSRF. - Restrict who can set destinations: SSO metadata URLs and connector base URLs should be admin-only operations with audit logging, not available to every tenant user. See the OWASP API Top 10 API5 Broken Function Level Authorization Guide.
- Bound the work: timeouts, maximum response size and rate limits on fetch endpoints prevent the server being used for denial of service or scanning. See the OWASP API Top 10 API4 Unrestricted Resource Consumption Guide.
A safe webhook pattern
- At registration: parse the URL with the shared library, require
httpsand port 443, resolve the host and reject any private, loopback, link-local, multicast or metadata address (IPv4 and IPv6, including::1/128,fe80::/10,fc00::/7), and record the owner. - Verify ownership: require the endpoint to echo a challenge or return a token before activation, which also proves the receiver intends to receive events.
- At every delivery: resolve again, validate every resolved address, connect to the validated IP while keeping the hostname for the Host header, SNI and certificate check (the OWASP cheat sheet's defence against DNS rebinding), and do not follow redirects.
- Send through a dedicated egress path: deliveries leave from a webhook worker pool behind a proxy that only allows public destinations and logs every call with the tenant ID.
- Report status, not content: the "send test event" response and delivery logs shown to users contain the HTTP status and timing, never the response body.
- Sign what you send: sign payloads (for example with an HMAC per subscription) so receivers can verify origin; the signing secret is a credential to rotate.
Where identity fits
The damage from API SSRF is usually decided by identity, not by the request itself. The prize is the workload's cloud credential, available from the instance metadata service (ATT&CK T1552.005 Cloud Instance Metadata API). On AWS, IMDSv2 requires a session token obtained through a PUT request to /latest/api/token and sent in the X-aws-ec2-metadata-token header; with tokens set to required, calls without a valid token get a 401, PUT requests carrying X-Forwarded-For are rejected, and the default response hop limit is 1. These checks defeat most simple GET-based SSRF but are defence in depth: an SSRF that controls method and headers can still reach the service. Give fetcher workloads their own role with no data access, so a stolen credential is nearly worthless. See the Cloud Instance Metadata Services Compared Guide and the EC2 Instance Metadata Service Hardening Guide, and treat webhook signing secrets and connector tokens as non-human credentials under the API Key Management Guide.
Testing and evidence
- Inventory: query the API specification and gateway logs for parameters typed or named as URLs (
url,uri,callback,webhook,endpoint,image,feed) and for features that fetch implicitly (previews, renderers). Reconcile against the API inventory; undocumented endpoints are an API9 problem as well (see the OWASP API Top 10 API9 Improper Inventory Management Guide). - Unit tests for the validator: rejected schemes, private and metadata addresses in IPv4 and IPv6, alternative IP encodings, hostnames resolving to private addresses, and redirects to internal targets.
- Blind SSRF tests: in authorised testing, use an out-of-band callback host you control to confirm whether a field triggers server-side requests at all, including delayed ones from queues.
- Network proof: from the fetcher workload, confirm that connections to internal ranges and metadata endpoints are blocked by the network, independently of application validation.
- Response handling: confirm test and import endpoints never echo fetched bodies, headers or detailed connection errors that reveal internal topology.
For broader test planning see the Web Application Security Testing Guide.
Detection and measurement
Log every outbound fetch with tenant, API operation, requested host, resolved IP, status and bytes. Alert on validator rejections clustered by tenant (probing), fetches to newly seen hosts that resolve to non-public addresses, metadata access by application processes, and cloud credentials issued to a fetcher role being used from outside its expected network (ATT&CK T1552.005 followed by unusual API calls).
| Metric | Target |
|---|---|
| URL-consuming API operations with a documented owner, allow list or block list, and tests | 100% |
| Fetch operations routed through the shared fetch library and egress proxy | 100% |
| Compute instances with IMDSv2 required (or the cloud equivalent enforced) | 100% |
| Test or import endpoints returning raw fetched content | 0 |
| Validator rejections investigated when a tenant exceeds the alert threshold | 100% within SLA |
Decision guidance
- Known destinations (payment provider, CRM connector): strict allow list of hosts and paths, URL built server-side. This is OWASP cheat sheet case 1 and the strongest option.
- Arbitrary public destinations (webhooks, previews): block list of non-public addresses with connection-time validation, isolated workers and filtered egress. Accept that this is weaker and compensate with the network layer.
- Tenant-defined internal destinations (on-premises connectors): do not fetch from the shared platform; use an agent the customer runs in their own network that connects outbound to you.
- Non-essential feature: if a URL feature has little business value, remove it. OWASP notes the risk cannot always be eliminated, and removal is the only complete fix.
- Small teams: a single shared fetch function with the block list, redirects off, and an egress rule blocking metadata and private ranges covers most of API7 in a sprint. Large platforms: a central fetch service and proxy that every team must use, enforced by network policy.
Lessons from incidents
The Capital One breach in 2019 is the reference case for why API7 is rated by its cloud consequences. A misconfigured web application firewall was induced to request its own instance metadata endpoint, which returned temporary credentials for the firewall's IAM role. The role could read far more data than a firewall needs, and the attacker copied data on about 100 million people in the US and 6 million in Canada; the US Office of the Comptroller of the Currency later imposed an 80 million dollar civil money penalty. Every control in this guide would have broken the chain at a different point: no metadata route from the component, token-required metadata access, and a role scoped to its job.
Common failure patterns
- Validating the string, connecting to the name: the hostname passes a check, then resolves to an internal address at connection time (DNS rebinding).
- Redirects left on: the validated public URL answers with a redirect to an internal address that the client follows.
- Webhook test endpoints that echo responses: turning blind SSRF into full-read SSRF, exactly as in OWASP scenario 2.
- Only REST reviewed: URL arguments inside GraphQL input types or asynchronous job payloads never reach the validator.
- Different parsers for validation and request: the validator and the HTTP client disagree about which host a crafted URL names.
- Over-privileged fetcher roles: the fetch service runs with the same cloud role as the main application, so any bypass exposes production data.
Framework mapping
| Framework | Reference |
|---|---|
| OWASP API Security Top 10 2023 | API7:2023 Server Side Request Forgery; related API10:2023 Unsafe Consumption of APIs |
| OWASP ASVS 5.0 | V1.3.6; V15.3.2; V1.5.3 |
| CWE and CAPEC | CWE-918; CAPEC-664 Server Side Request Forgery |
| MITRE ATT&CK | T1190 Exploit Public-Facing Application; T1552.005 Cloud Instance Metadata API; T1046 Network Service Discovery |
| NIST SP 800-53 Rev. 5 | SI-10 Information Input Validation; SC-7 Boundary Protection and SC-7(5) Deny by Default, Allow by Exception; AC-4 Information Flow Enforcement |
| NIST CSF 2.0 | PR.IR-01 Networks and environments are protected from unauthorized logical access and usage |
| ISO/IEC 27001:2022 Annex A | A.8.28 Secure coding; A.8.22 Segregation of networks; A.8.20 Networks security |
Practitioner checklist
- Inventory every API operation that accepts or implicitly fetches a URL, including GraphQL arguments and async jobs.
- Replace URL inputs with identifiers or uploads wherever the business case allows.
- Use one shared fetch library: single parser, https and port allow list, redirects off, timeouts and size limits.
- Validate destinations at registration and at connection time against the resolved IP, IPv4 and IPv6.
- Return status only from test and import endpoints, never raw fetched content.
- Run fetchers in isolated workloads with deny-by-default egress through a logging proxy.
- Enforce token-required metadata access and give fetcher roles no data permissions.
- Restrict SSO metadata and connector URLs to admins, with audit logging.
- Add validator unit tests and authorised out-of-band tests to the release pipeline, and alert on clustered rejections.
Standards and references
- OWASP: API7:2023 Server Side Request Forgery
- OWASP: API Security Top 10 2023
- OWASP: Server-Side Request Forgery Prevention Cheat Sheet
- OWASP: Application Security Verification Standard 5.0
- MITRE CWE: CWE-918 Server-Side Request Forgery (SSRF)
- MITRE CAPEC: Server Side Request Forgery
- MITRE ATT&CK: Cloud Instance Metadata API
- AWS: Use the Instance Metadata Service to access instance metadata
Related NHI Mgmt Group resources: SSRF Prevention Guide · Top 10 API Security Risks · OWASP API Top 10 API10 Unsafe Consumption of APIs Guide · Capital One Breach 2019