What Is XSSI and How Do Tokens Protect APIs?
Cross-Site Script Inclusion (XSSI) is a web security vulnerability
that allows an attacker’s website to steal sensitive, authenticated data
from another application by abusing the way web browsers handle the
<script> tag. Because script tags are exempt from the
Same-Origin Policy (SOP), an external domain can include dynamic,
user-specific JavaScript or JSON resources and capture their contents.
Implementing unpredictable token mechanisms protects JavaScript data
APIs by requiring requests to carry cryptographically secure tokens or
custom headers, which malicious third-party <script>
tags cannot generate or supply.
Understanding Cross-Site Script Inclusion (XSSI)
The Same-Origin Policy typically prevents one website from reading
data hosted on another origin. However, the HTML
<script> tag is fundamentally designed to allow
cross-origin execution to load libraries, analytics, and frameworks.
XSSI occurs when an application exposes sensitive user data through endpoints that output executable JavaScript, JSONP, or improperly formatted JSON. When an authenticated user visits an attacker-controlled webpage, the malicious site includes a script tag pointing directly to the vulnerable data API:
<script src="https://example.com/api/user-profile.js"></script>When the victim’s browser requests this script, it automatically includes the victim’s session cookies. If the API responds with JavaScript containing sensitive data (such as global variables or executable functions), the attacker’s script can read that data directly from the browser’s execution context.
Variations of XSSI Exploitation
- Dynamic JavaScript Files: Endpoints returning
sensitive variables assigned directly to the global
windowscope. - JSONP Endpoints: Endpoints that wrap JSON data in a user-defined callback function, allowing attackers to intercept the payload by defining the callback function on their own page.
- Prototype Pollution and Object Override: Historical exploits where attackers manipulated array constructors or prototypes to capture naked JSON arrays evaluated by the browser.
How Token Mechanisms Protect JavaScript Data APIs
Because the browser’s default behavior sends cookies automatically
with cross-origin <script> requests, relying solely
on cookie-based authentication leaves dynamic JavaScript APIs
vulnerable. Token mechanisms effectively neutralize this threat.
1. Synchronizer Token Pattern (Anti-CSRF / Anti-XSSI Tokens)
Token-based defense involves issuing a unique, cryptographically random token tied to the user’s current session. When the client application requests sensitive data from an API:
- The server generates a dynamic token and embeds it in the initial authenticated page or sends it via a secure handshake.
- Every subsequent data request must explicitly include this token as a request parameter or within the payload.
- When a third-party site attempts to invoke the endpoint via a
<script>tag, it cannot guess or access the token because the Same-Origin Policy prevents it from reading the victim’s current token from the legitimate site. - The API rejects any request that lacks a valid, matching token, blocking the execution of the dynamic script.
2. Custom HTTP Headers and Bearer Tokens
Modern web APIs frequently use stateless authorization tokens (such
as JSON Web Tokens) transmitted through custom HTTP headers (e.g.,
Authorization: Bearer <token> or
X-Requested-With).
HTML <script> tags can only perform standard
GET requests and cannot set custom HTTP headers.
Consequently: * The cross-origin <script> tag cannot
attach custom headers automatically. * If an attacker attempts to use
fetch() or XMLHttpRequest to set custom
headers, the browser enforces Cross-Origin Resource Sharing (CORS)
rules. * Unless the API explicitly permits the attacker’s origin via
CORS headers, the browser blocks the request before any data can be
read.
Complementary Mitigations for API Protection
While token mechanisms provide strong protection, implementing defense-in-depth ensures complete immunity against XSSI:
- Use Pure JSON: Always return data as standard JSON
objects (
application/json) rather than executable JavaScript files or dynamic scripts. - Avoid JSONP: Deprecate JSONP callbacks entirely in favor of CORS-enabled REST or GraphQL APIs.
- Employ JSON Vulnerability Prefixes: Prepend data
responses with non-executable strings such as
)]}',\nor infinite loops likewhile(1);. Legitimate AJAX parsers strip this prefix before reading the JSON, while a browser attempting to execute the response via a<script>tag will throw a syntax error and halt execution. - Configure
SameSiteCookie Attributes: Set session cookies withSameSite=LaxorSameSite=Strictto prevent cookies from being sent automatically during cross-site resource inclusions.