What XSS Scripts Can Access
A script injected via XSS runs with the same browser permissions as any other script loaded by that page. The same-origin policy grants those permissions relative to the target origin, not the attacker's origin. This defines the impact.
Cookies
document.cookie returns all cookies set for the current origin that do not have the HttpOnly flag. Session tokens, tracking identifiers, and preference values stored in cookies without HttpOnly are readable from JavaScript and can be exfiltrated.
Cookies with HttpOnly are not accessible via document.cookie. The browser withholds them from JavaScript. They are still sent in HTTP requests, so XSS can use them indirectly by making authenticated requests, but cannot read their values.
Authentication Tokens in Storage
Applications using token-based authentication often store tokens in localStorage or sessionStorage. Both are accessible to JavaScript on the same origin via localStorage.getItem() and sessionStorage.getItem(). Unlike HttpOnly cookies, there is no browser flag that prevents script access to storage. If a session or API token is in storage, an injected script can read and exfiltrate it.
DOM Content
The injected script can read any content rendered in the current page via the DOM API. For an authenticated user, this includes rendered account data, transaction history, messages, or any other information the application displays. The script can also traverse to other pages within the same origin by navigating and reading the result, or by making fetch requests to same-origin URLs and reading the response bodies.
Authenticated Requests
Browsers automatically attach cookies and credentials to requests when the credentials option is set or when using older APIs like XMLHttpRequest. An injected script can use fetch() or XMLHttpRequest to call the application's own API endpoints with the victim's session credentials. This allows reading data from API responses and performing state-changing operations (submitting forms, updating settings, sending messages) as the victim.
CSRF tokens do not prevent this. A CSRF token is placed in the page or a cookie to verify that a form submission came from a legitimate page load. An injected script on the legitimate page can read the CSRF token from the DOM or from cookies (if the cookie lacks HttpOnly) and include it in forged requests.
Keylogging and Form Capture
JavaScript can attach event listeners to any element. An injected script can listen for input and keydown events on form fields and capture values as the user types, including passwords entered after the page loads.
Exfiltration
Collected data is typically exfiltrated by making a request to an attacker-controlled server. A fetch to an external URL, loading a 1x1 pixel image with query parameters, or using navigator.sendBeacon() are all mechanisms that carry data out. Content Security Policy can restrict which external destinations scripts may contact, which limits exfiltration paths but does not prevent all of them.