A preview or import feature may fetch a URL supplied by its user. Server-side request forgery, or SSRF, happens when untrusted input causes the server to make an unintended request. The browser supplies the address, but the server uses its own network access and permissions to fetch it.
An internal service may be reachable from that server even when the user's browser cannot reach it. An allowlist states which destinations are permitted. In this model the allowed destination has scheme http, host 127.0.0.1 and port 8000. Treat that as a fictional fetch policy; no URL here should be requested.
Before you begin
- Recommended first
- Notes: scope, command, result, time, HTTP methods, headers, status codes, cookies, How a web app is put together, Same-origin policy, Race conditions
- Estimated time
- 16 min reading, 12 min activity. Setup and optional practice may take longer.
- Where you work
- Read the original fictional requests, source fragments and state tables in a current desktop or mobile browser. The required activity needs no server, database, account or installed security tool. Do not send the printed requests to any service.
- Without a lab
- Use the complete printed evidence to trace the data or state on paper. Write the decision, the fact supporting it and one limit of the model, then compare with the activity rubric. This does not establish live service behavior. Reading works without JavaScript. Checking requires JavaScript and a secure browser context; saving also requires usable browser storage.
After this lesson you can:
- Point to the component that would download the worked destination.
- Classify the two activity destinations against the allowlist.
- Keep every name unrequested.
01Example
This fictional flow shows who would perform a destination request. Do not contact the example internal name.
Caller supplies: http://desk-metadata.internal/label
Application receives the submitted URL.
Backend fetcher would request that destination.
Policy decision must happen before the backend request.
No request was sent.02Who fetches
Follow the components rather than the appearance of the form. The caller chooses a URL, the application receives it, and the backend fetcher would contact the destination. That boundary can expose internal responses or trigger unintended actions if the fetcher trusts arbitrary destinations.
Prefer fixed destinations or a narrow allowlist, compare parsed scheme/host/port, and limit outbound network access. Redirects and DNS resolution need checks too because they may change the eventual destination. The card omits those operations. A browser's same-origin reading rule does not constrain requests made by a backend process.
See that the caller supplies an address and the backend would be the component that fetches it.Model. A teaching model drawn by hand. It shows the idea, not real tool output.
Read the full explanation below.
Playback is optional. Step through at your own pace.
The caller supplies a destination URL.
Follow the explanation
- The caller supplies a destination URL.
- A backend fetch would use the server-side requester.
Read every state and value
1. The caller supplies a destination URL.
- Messages shown
- Submitted URL
- Current message
- Submitted URL
- Policy decisions
- Status: pending
- Participant roles
- Actor: caller; Text: Supplies data; does not fetch in this model. · Actor: Application; Text: Receives the submitted URL. · Actor: Backend fetcher; Text: Would make the server-side destination request after policy. · Actor: Submitted destination; Text: Submitted destination only; no request was sent.
2. A backend fetch would use the server-side requester.
- Messages shown
- Submitted URL · Would request a fetch
- Current message
- Would request a fetch
- Policy decisions
- Status: not-established
- Participant roles
- Actor: caller; Text: Supplies http://desk-metadata.internal/label as data. · Actor: Application; Text: Receives the submitted URL. · Actor: Backend fetcher; Text: Policy must happen before any destination request. · Actor: Submitted destination; Text: No fetch message is released; no destination contacted.
03Classify the activity destinations
Read the evidence before comparing your reasoning with the activity rubric. Send nothing.
Original flow. No request was sent.
Browser shows a form.
The form field contains a destination written by the caller.
The backend is the component that would download that destination.
The browser supplied the address. The backend would perform the fetch.
Fictional destination on the worked card: http://desk-metadata.internal/label
That name is not a host to contact. It stands for a service the browser cannot see
and the backend might reach if it fetched caller-supplied addresses.
Activity destinations, also not to be requested:
http://127.0.0.1:8000/note.txt is on the allowlist card
http://files.club.internal/note is not on the allowlist card
Outbound policy for the backend fetcher.
Allowlist: http://127.0.0.1:8000/ and paths under it.
Anything else is not fetched.
A prefix of the text is not enough: the card compares the scheme, host, and port
as separate parts. This lesson does not send either URL.
Browser page loads that the browser makes for itself are outside this allowlist.
Those loads are the browser's own requests.
- Write which component would perform the download.
- Mark the activity URL that matches scheme, host, and port 8000 on the loopback name. Mark the other URL.
- Check: the note.txt URL is on the allowlist. The files.club.internal URL is not. The worked metadata name is not on the list either.
- Stop. Do not send any of these names.
04Optional challenge
Explain why a browser rule against reading another origin does not stop the backend fetch. The rubric is: the browser rule binds the browser, and the fetcher is the backend. About ten minutes.
05Fresh cases for the checks
Use these fictional cases for the checks below. They have different inputs from the worked examples. Read them here or make notes; no installation or external service is needed.
Fetcher case A: new fictional flowOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
1. A browser submits a destination string to a notes application.
2. The application passes an approved destination to its backend downloader.
3. The downloader would request the content and return it to the application.
This is a flow model only; do not request any destination.
Fetcher case B: independent parsed-destination ruleOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
Allow only scheme http, host 127.0.0.1, port 8000. Paths under / are allowed.
P: http://127.0.0.1:8000/notice
Q: https://127.0.0.1:8000/notice
R: http://127.0.0.1:9000/notice
No redirects or DNS changes are modeled; a real policy must account for eventual destinations too.
06Explain your evidence
Optional written self-check: explain one decision using the supplied case. No tool run is required.
Check your explanation: separate who supplies the URL from who fetches it; compare parsed scheme/host/port; place enforcement before the backend request; name redirects and resolution as real-policy limits without sending anything.
07Common mistakes
If you treat the form as the fetch, you stopped at the component that supplied the address.
If you allow files.club.internal because it contains the word note, you used a text prefix. The card compares scheme, host, and port.
If you request the metadata name, you left the lesson. It is not a host to contact.
References
- RFC 6454: The Web Origin Concept
Sections 3.2 and 5. Reading another origin is generally forbidden in the browser, and sending is a separate allowance. This lesson uses that limit only to say a browser rule does not bind the backend fetcher.
- PortSwigger: SSRF
Explains the failure mechanism and prevention. Use it for further reading after reasoning from this page's original model; a topic page is not evidence that a lab was launched.