Skip to content

Cross-Site Scripting

Overview

The API server emitted an HTML response with containing unsanitized user input which may be executed by a web browser.

Since the script comes from a web page that was sent by the web server, the victim's web browser executes the malicious script in the context of the web server's domain. This effectively violates the intention of the web browser's same-origin policy, which states that scripts in one domain should not be able to access resources or run code in a different domain.

Recommendation

Ensure that user input is sanitized before including it in any HTML response.

Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does.

To help mitigate XSS attacks against the user's session cookie, set the session cookie to be HttpOnly. In browsers that support the HttpOnly feature (such as more recent versions of Internet Explorer and Firefox), this attribute can prevent the user's session cookie from being accessible to malicious client-side scripts that use document.cookie.

Examples

Here's a FastAPI example which is vulnerable to XSS:

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get("/items/{id:path}", response_class=HTMLResponse)
async def read_item(request: Request, id: str):
    return f"<html><body>You requested item {id}</body></html>"

We can see that this endpoint inserts unsanitized user input into an HTML response, e.g. visiting /items/<script>alert(1)</script> will cause the browser to execute the script.

References