October 27, 2026
CSRF and XSS: How a Valid Login Can Be Misused
A practical explanation of forged requests, injected scripts, and the defenses each needs.

By Vansh Baghel
5 min read
Imagine you are logged in to an online bookstore. You open a discount link, and your delivery address changes without your permission. Your password was never stolen. Your session is still valid.
Now imagine a different incident: you open a product page, and a malicious review causes JavaScript to run inside the bookstore's website. That script can interact with the page and make requests using your existing login.
The first scenario illustrates cross-site request forgery, or CSRF. The second illustrates cross-site scripting, or XSS. Both can misuse an authenticated browser, but they exploit different weaknesses and need different defenses.
CSRF takes advantage of credentials the browser sends automatically. When you sign in, a website may set a cookie containing a session ID or an access token. The browser can attach that cookie to later requests, subject to its domain, path, SameSite, and other delivery rules.
That is useful when you deliberately update your address. But a valid credential identifies the account associated with a request; it does not establish that you intended the action.
In our hypothetical bookstore, an attacker creates a page that causes a browser to submit an address-change request. They then persuade a signed-in user to visit it. If the browser permits the authentication cookie to accompany the request, and the bookstore has no effective CSRF protection, the server may accept the change.
The attacker needs to construct a request the endpoint will accept, including the required inputs. A separate unpredictable value that the attacker cannot obtain can prevent that. This is why not every form or authenticated endpoint is vulnerable.
A malicious page might submit a hidden form when it loads, or a misleading button might trigger the submission. If a website incorrectly changes data through a GET request, a crafted link may be enough to trigger the action. None of these techniques needs the victim's browser to hand its cookie to the attacker's website.
The cookie can remain genuine and private throughout the attack. The browser sends it to the real bookstore. The attacker's goal is to cause an authenticated request, and they may never see its response.
This explains why browser restrictions on reading another site's data are not a complete CSRF defense. Ordinary cross-origin form submissions can be sent even when the initiating page cannot read the response. CORS can block some kinds of cross-origin requests, including requests that require a preflight check, but a restrictive CORS policy alone does not stop every form submission.
Modern SameSite cookie rules block many traditional attack patterns. The scenario depends on the browser actually sending the required credential and the server accepting the request. Simply visiting another website does not automatically expose every logged-in account.
A JWT inside the cookie does not change this mechanism. The server may verify the JWT's signature, issuer, audience, and expiry correctly. Those checks succeed because the browser sent a legitimate token. The attacker did not need to alter its claims or forge a signature.
A JWT signature protects the signed contents against undetected modification. CSRF protection addresses how an unwanted request is induced. Replacing a session ID with a JWT inside the same automatically sent cookie does not remove that concern.
A token explicitly attached by application code to an Authorization header behaves differently: the browser does not automatically add that header when another site submits an ordinary form. This changes the CSRF attack path. The application still needs to protect its token and any other endpoints that authenticate through cookies.
XSS starts when untrusted content becomes executable inside the trusted application. Return to the bookstore's product reviews. A review should be treated as user content. If the application inserts it into the page unsafely, attacker-supplied content may be interpreted as executable JavaScript.
The application is not intentionally attacking its visitors. Its rendering logic has allowed an attacker to introduce instructions where only content should have been allowed.
Browsers normally isolate websites using origins, which are defined by the scheme, host, and port. JavaScript running on an unrelated site cannot simply read your bookstore's private pages or localStorage.
With XSS, malicious JavaScript runs within the bookstore's own page context. The browser does not automatically distinguish the developer's intended code from injected instructions. The injected code generally has the access available to that page, subject to browser and application protections.
It may read visible account information, change the page, access credentials stored in localStorage, or call the application's APIs using the victim's login. It does not gain unrestricted access to every website or the user's entire computer.
You will encounter three common labels for XSS:
- Stored XSS: malicious content is saved, for example in a review, and later delivered to people who view it.
- Reflected XSS: attacker-controlled input, often carried in a crafted URL, is included unsafely in the immediate response.
- DOM-based XSS: JavaScript in the page handles untrusted data unsafely and causes execution in the browser. The DOM is the browser's representation of the page.
These labels can overlap. Stored and reflected describe how malicious input reaches a page; DOM-based describes where unsafe processing occurs. The shared failure is allowing untrusted data to become executable content.
HttpOnly limits cookie theft, but it does not prevent every action an injected script can perform. An HttpOnly cookie cannot be read directly by page JavaScript. However, the browser can still attach it to requests made from that page. Malicious code may be able to change account settings without learning the cookie's value.
Putting a token in localStorage makes it available to JavaScript in that origin, including injected code. Keeping a credential in an HttpOnly cookie reduces that direct exposure, but still requires XSS prevention and appropriate CSRF defenses. The storage choice changes which protections you need.
For CSRF, a common defense is an unpredictable token associated with the user's session. The legitimate application includes it in a form or request, and the server validates it. An unrelated attacker page normally cannot read it because of browser origin restrictions. The server should reject requests with missing or invalid tokens, even if their authentication cookie is valid.
Use the framework's supported CSRF mechanism rather than inventing a token scheme. Configure SameSite cookies appropriately, check expected request origins where applicable, and consider browser-provided Fetch Metadata to reject unwanted request contexts. These mechanisms need a policy that matches legitimate application traffic.
SameSite is useful as an additional layer. Lax cookies can still accompany some top-level navigations using safe methods such as GET, so GET endpoints should not perform state-changing actions. Also, sibling subdomains can be same-site while remaining different origins; the two boundaries are not identical.
For XSS, the main work is keeping untrusted data out of executable contexts:
- Render text as text. Use safe rendering APIs and the protections provided by your framework. Review places where those protections are deliberately bypassed.
- Encode for the context. HTML text, attributes, URLs, and JavaScript have different rules. A transformation that is safe in one context can be unsafe in another.
- Sanitize intentionally permitted HTML. If users can submit rich content, use a maintained HTML sanitizer with an appropriate policy. Removing only script tags is insufficient.
- Add a carefully configured Content Security Policy. CSP can restrict which scripts execute and reduce the impact of some injection mistakes. It supplements safe rendering.
Both defenses matter because XSS can often undermine CSRF protection. A script already executing inside the application may be able to read the legitimate CSRF token and make requests that pass validation. A CSRF token is not proof that the person deliberately clicked a button.
When reviewing an application, trace two paths: how a state-changing request is authorized and protected against cross-site initiation, and how user-controlled content reaches a rendered page. Then check what an injected script could access. Those paths reveal the risks that a valid login, a JWT signature, or a cookie flag cannot resolve on its own.
Sources and further reading