ASVS 5.0 V3.2.1 requires security controls that stop browsers from rendering content or functionality in the wrong context, for example when an API response or a user uploaded file is opened directly. Suggested controls include checking Sec-Fetch headers, the CSP sandbox directive, and the attachment disposition in Content-Disposition. It is a Level 1 requirement.
Why it matters
If a browser can be sent straight to a URL that returns user controlled content, it may treat that content as a page. An uploaded HTML or SVG file then runs script on your origin, which gives an attacker the session of whoever opens the link. The same happens when a JSON endpoint is sniffed as HTML.
How to implement it
Set the content type correctly and add headers that remove the ambiguity.
For user uploads and downloads:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="report.pdf"
X-Content-Type-Options: nosniff
Content-Security-Policy: sandbox
For API responses, always send Content-Type: application/json and X-Content-Type-Options: nosniff. Serve user content from a separate domain, so a mistake cannot reach your session cookies.
For endpoints meant only for fetch calls, check the Fetch Metadata headers the browser adds, and refuse direct navigation:
@app.before_request
def only_from_our_app():
if request.path.startswith("/api/"):
dest = request.headers.get("Sec-Fetch-Dest")
if dest == "document":
abort(403)
Browsers that do not send these headers should still get the other controls, so treat the check as an extra layer.
How to test it
Upload an HTML file and an SVG containing a script, then open the returned URL directly. The browser should download it or show it inert, never run it. Request an API URL in the address bar and check the response headers. Confirm that nosniff is present.
A short checklist for user content
Serve uploads from a separate registrable domain, with random file names and no execution rights. Detect the type from the content, and store and send back a fixed safe Content-Type. Force download for anything that does not need to display inline. Keep a list of formats that can contain script, namely HTML, SVG, XML and some PDF features, and treat them as hostile.
For APIs, a JSON response should never contain a user supplied string that could be mistaken for HTML at the start of the body, and nosniff stops guessing anyway. Avoid JSONP, and reject requests whose Sec-Fetch-Mode is navigate for endpoints that only serve scripts and fetch calls.
Common mistakes
- Serving uploads inline from the main origin.
- Detecting the type by file extension and trusting the client supplied type.
- Missing
nosniff, which lets the browser guess a more dangerous type.
Quick check
Why does an SVG upload need special care?
SVG is XML that can contain script. Opened directly on your origin, it executes like a page.