Guide 111 pillar

How to review SSRF in a cloud application

Review cloud SSRF through URL construction, redirects, proxy behavior, destination access, and provider-specific evidence without overstating what source proves.

To review server-side request forgery (SSRF), trace who chooses a request destination, what the application actually connects to, and what that server can reach. A URL-shaped input is a lead, not a verdict. The claim becomes serious when an untrusted actor can direct a server-side client to a destination outside the intended set and that client has useful network reach, authority, or a response channel. If the application selects the destination from a fixed server-owned mapping, the same URL parsing concern may not apply. If the network path or deployed configuration is unknown, say so before describing a production impact.

This is the core of CWE-918: the server retrieves a URL or similar resource without adequately constraining the destination. In a cloud application, the review must include the worker's egress policy, internal services, identity-bearing environment, and metadata configuration. OWASP's SSRF guidance separates the simpler case of a known set of trusted destinations from the harder case of deliberately supporting arbitrary external URLs. Start by deciding which case the feature actually needs.

Draw the request that matters

Illustrative case; names and facts are invented. A SaaS application, Northstar Notes, lets a workspace member submit an image URL for a document preview. An API route places the URL in a job. A separate worker downloads the image and stores a thumbnail. A scanner flags http_client.get(job.image_url) and calls it SSRF. The flag identifies a potentially sensitive operation, but it has not established whether the worker accepts an arbitrary URL, whether it applies destination policy, which network it runs on, or whether returned data reaches the member.

The first review artifact is a flow, not a payload:

Illustrative flow; no network request was made for this example.

workspace member -> preview API -> job record -> preview worker
                                       |                |
                             URL or image ID?    URL parser + DNS?
                                                        |
                                             redirect and proxy policy?
                                                        |
                                             actual outbound connection
                                                        |
                                          response handling + storage

Mark each arrow as observed, inferred, or unknown. The job boundary matters: the API might validate the original text, while the worker uses a different parser or follows a redirect. The worker might also receive a server-generated image ID rather than the user's URL, defeating the proposed path. A grep result at the HTTP call cannot answer either question.

Write a claim you could disprove: “A workspace member can supply a URL that the deployed preview worker contacts outside the intended image-provider set, and the response may influence a member-visible preview.” The falsifier is equally useful: “The worker constructs a fixed provider URL from a validated image ID, disallows redirects, and has no other caller carrying user-chosen destinations.” If the falsifier is found, record it; do not keep the scanner label by habit.

Separate destination choice from destination enforcement

Ask which of these designs Northstar intends:

Product need Review question Usually stronger design
Fetch from one known image service Can the user choose a host at all? Accept an image ID; construct the URL on the server.
Fetch from a small partner list Is the allowed host and port fixed after parsing? Exact, maintained destination allowlist plus network restriction.
Fetch arbitrary public images Can the application prove the connection stays on an allowed public route? Dedicated fetcher with constrained egress, redirect and DNS handling, limits, and isolation.

The first row removes most destination ambiguity. The second requires the reviewers to inspect exact host matching: a substring check or a suffix check without domain-label boundaries does not establish that a destination belongs to a partner. The third is a larger product decision because there is no small host allowlist. OWASP recommends combining application-level controls with network-layer restrictions, and discusses the different constraints for known destinations and arbitrary external requests.

Do not reduce this to “block private IPs.” That rule has to survive parsing, name resolution, redirects, proxy behavior, multiple resolved addresses, later re-resolution, and the address actually used by the client. A validator may approve one DNS result while the connector later uses another. A redirect can turn an initially approved URL into a different request. An environment proxy can alter where the request goes. A robust design controls the final outbound connection and repeats destination checks for every permitted redirect; a restrictive network path is a second boundary. This is an engineering review of the client and deployment, not a regex review.

Review the cloud boundary without assuming a cloud outcome

Cloud context changes what a server-side request might reach, but it does not prove exposure. Record the worker's actual runtime: container task, VM, function, managed fetch service, or another environment; its network placement; egress firewall or proxy; and the service identity available to it. Then identify internal destinations or metadata interfaces that are genuinely reachable from that runtime. If you cannot inspect the deployed network and runtime, mark the potential effect conditional.

For workloads on EC2, check the instance metadata setting. AWS documents a configuration in which IMDSv2 tokens are required. That is a relevant defense-in-depth fact, not proof that SSRF is impossible: an application may have other internal destinations, another cloud runtime, or a different path to sensitive data. Conversely, an EC2 address in an alert is not evidence that the flagged worker runs on EC2. Do not turn a generic cloud risk into a claim about a deployment you have not examined.

Practical business impact also depends on the response path. Can a user read fetched content in an error, generated preview, cache entry, support log, or API response? Can the worker merely cause an outbound request without disclosing the reply? Does an internal service accept the method, headers, and credentials the fetcher sends? These differences affect impact and practical exploitation difficulty. Record what is known separately from hypothetical consequences.

Compare the application trace with the connection trace

Northstar supplies a fictional evidence packet for the preview worker. It contains no real network observation:

source N42: member URL is copied into job J8
client config C4: HTTPS accepted; redirects followed
deployment D9: worker egress must traverse destination proxy P3
proxy P3: permits the image provider; denies other destinations
output: successful images become thumbnails; fetch errors become generic errors

The source suggests a redirect gap in the application. The deployed proxy might defeat the claimed off-policy connection. The reviewer must determine whether all worker connections pass through P3, including retries and proxy-bypass settings. A configuration file naming a proxy is weaker evidence than a selected runtime and enforced egress route.

An authorized owner could return one of these synthetic packets:

Packet What it establishes Result
Approved image fetched; redirect target denied at enforced proxy; no bypass route Positive control works and this off-policy connection is blocked Narrow the deployed claim; retain application redirect hardening
Both approved and rejected images fail because worker has no network Feature path was not successfully exercised Inconclusive; cannot credit destination policy
Redirect target receives request from worker; only generic error reaches member Off-policy connection supported in that environment Investigate reachable effect; do not claim readable response or stolen credentials
Response bytes return in a member-visible error body A response channel exists for that path Assess actual returned content and authority; still no automatic credential conclusion

Status codes from the public API cannot replace this packet. A generic error could mean an egress denial, a failed image parser after a successful fetch, or an internal exception. The connection and response paths answer different questions.

Use the product requirement to reduce the problem

The product owner clarifies that Northstar only needs its contracted image provider. Arbitrary URLs were convenient during prototyping, not a customer requirement. The selected design accepts an opaque provider image ID and constructs the destination in the worker:

request: {provider_image_id: "img_17"}
job J8:  tenant=Cedar, image_id=img_17, provider=approved-images
worker:  fixed scheme + fixed provider host + encoded ID path component
client:  redirects disabled; no incoming credentials forwarded

This is design pseudocode; the ID grammar, path construction and client behavior need implementation review. The ID must not become an alternate URL or an unrestricted path suffix. Resolve it under the requesting tenant's provider grant: a fixed host prevents arbitrary destinations but does not authorize every image that a shared integration credential can fetch. The worker should not recover from a provider error by retrying the original customer URL. A second queue producer must use the same job contract.

The remaining controls have a concrete purpose: a byte cap bounds downloaded input, a deadline bounds waiting, the image parser has its own resource limits, and tenant-bound output prevents one workspace from reading another's preview. The egress policy still constrains the component if destination construction fails. None of those facts establishes a universal safe-fetch service.

If arbitrary public images are an actual requirement, the decision changes. Keep the feature in a dedicated fetch component and require connection-time destination enforcement across DNS results, retries and every redirect, with a narrowly scoped network identity. OWASP's SSRF guidance discusses the application and network controls involved. The detailed parsed-destination problem belongs in the allowlist review.

Northstar's final design note therefore says what the team chose and gave up: provider IDs satisfy the image requirement; arbitrary URLs are removed; existing jobs carrying URLs require explicit rejection or controlled migration. It does not say “SSRF fixed” merely because one regex changed.

Validate safely and state what the result means

An authorized team can exercise the feature in a controlled test environment using synthetic destinations it owns. A useful validation harness presents an approved destination, an intentionally rejected destination, a redirect to a rejected destination, and a DNS result that changes between checks. Observe the outbound connection at the egress boundary as well as the API response. The goal is to verify that the connection policy holds, not to probe real internal services. Do not run a customer's repository code, install its dependencies, or use a live exploit as a substitute for source review.

When dynamic validation is unavailable, use source and configuration evidence and be precise: “The code path appears to permit an untrusted destination; production egress is unconfirmed.” This supports a review task, not a statement that credentials were obtained. A negative controlled test is limited to the tested client, configuration, destination class and revision. It cannot establish that every parser and future deployment is safe.

For Northstar, the initial source-only note, before the deployment packet and design decision above, might read:

Subject: preview-worker destination policy at illustrative revision N42. Observed: the member's image_url reaches the job and the worker's HTTP client. Counterevidence: the API restricts schemes, but the worker follows redirects and no second destination decision is visible in reviewed code. Unknown: production egress and response visibility. Decision: investigate deployment and redirect handling before assigning a confirmed production-impact claim. Next owner: preview-service and platform owners provide the selected worker configuration and egress policy.

If subsequent evidence shows an uncontrolled final connection to a sensitive destination, write the finding in plain language: what action the member can cause, what asset might be affected, which preconditions apply, and how hard the path appears in this deployment. Keep the exact technical trace below that summary. If egress policy demonstrably blocks the path, reject this specific claim and preserve the evidence; do not infer that all outbound fetches are safe.

Choose the next decision

For the next URL-taking feature, draw the five arrows from input to connection and answer whether the product really needs arbitrary destinations. Then ask the platform owner for one deployment fact: where the fetcher can send traffic. If the uncertainty is in URL allowlist behavior, continue with outbound URL allowlist review. For a general method to convert the alert into a falsifiable claim, use the scanner-alert review guide.