cswork / libraryOpen practice workspace

Articles

CSRF vs XSS Interview Questions: Cookies, Origins, and Defense Boundaries

Compare CSRF and XSS in interviews through cookies, origins, CORS, token defenses, safe rendering, and browser tests that verify real state changes.

CSRF vs XSS interview questions are easiest to answer by tracing two things separately: which credentials the browser attaches to a request, and which origin's authority a script receives. CSRF abuses a browser's authenticated request context. XSS causes untrusted content to execute as script in a trusted application's context. Their defenses overlap, but they do not protect the same boundary.

A clear request trace will reveal more understanding than a list of security headers.

Start with the authority each bug borrows

Official facts: OWASP describes CSRF as causing a user's browser to perform an unwanted action on a trusted application. XSS prevention focuses on keeping untrusted data from executing as browser code through appropriate output handling and safe sinks. OWASP CSRF Prevention, OWASP XSS Prevention

For CSRF, imagine the user is signed in to a fictional preferences application. An unrelated page causes a state-changing request. If applicable cookies accompany the request and the server has no effective request-origin or token defense, the server may process it as the user. Reading the response is not necessary for the unwanted update to occur.

For XSS, imagine an untrusted profile label reaches an unsafe HTML rendering path. If script executes in the application's origin, it can interact with the page and make requests using the authority available there. The dangerous transition is from data to executable content.

Editorial inference: the scenarios and test matrices here are original, intended for controlled applications and synthetic accounts.

Trace one preference update in two scenarios

Use a fictional endpoint that changes a notification setting. The legitimate page sends the user's new setting, an appropriate anti-CSRF value, and the session cookie according to browser rules. The server verifies the session and its CSRF policy before committing the change.

In the CSRF scenario, the initiating document belongs to another origin. The question is whether that document can cause an accepted state-changing request with the user's ambient credentials. The same-origin policy may prevent the initiating script from reading the response while still permitting certain requests to be sent.

In the XSS scenario, the script is already executing within the trusted application. It may obtain a CSRF value exposed to that page and issue the same request the legitimate interface would issue. The presence of a token does not automatically distinguish malicious same-origin script from legitimate application code.

This is why an interview answer should avoid “CSRF tokens prevent both.” Tokens help bind requests to a legitimate interaction context under their threat model. They do not repair the browser's decision to execute untrusted content with application privileges.

The two scenarios can also coexist. Fixing the request-forgery path does not remove an unsafe DOM sink, and escaping a profile label does not prove every cookie-authenticated update route enforces CSRF protection.

Same-origin and same-site are different comparisons

An origin includes scheme, host, and port. A site comparison used for modern cookie behavior is broader and incorporates scheme and the registrable domain. Two sibling subdomains can therefore be cross-origin while still being same-site. Treating those terms as synonyms leads to incorrect defenses.

Official browser documentation: MDN explains CORS as a mechanism for controlled cross-origin access, and documents SameSite cookie behavior separately. A cookie's delivery rules also depend on attributes and request context. MDN CORS, MDN Set-Cookie

For an original deployment exercise, place the application at app.example.test and an independently managed service at uploads.example.test, both using HTTPS. Ask whether the upload service should be trusted with the application's security boundary. A same-site cookie rule does not by itself establish that every sibling host is equally trustworthy.

Now change only the port on a development server. Origin-sensitive behavior can change even when the hostname looks identical. Tests that run everything behind one local origin may miss the production boundary entirely.

Write the expected source origin, target origin, credential mode, and cookie attributes in the fixture. “It works in the browser” is not a sufficient description of which policy was exercised.

What do the cookie attributes actually do?

HttpOnly prevents JavaScript from reading the cookie through ordinary document-cookie access. It does not stop the browser from including that cookie in eligible requests. Consequently, an XSS flaw can still perform authenticated actions even when it cannot directly read the session cookie.

Secure limits cookie transmission to secure contexts under the browser's rules. It does not validate user intent or make unsafe HTML rendering safe. SameSite restricts cookie inclusion in certain cross-site contexts, but the exact behavior differs between Strict, Lax, and None.

Official facts: MDN documents these attributes, including the requirement for Secure with SameSite=None and the navigation-sensitive behavior of Lax. Explicitly configure the intended policy rather than treating browser defaults as a complete application design. MDN cookie attributes

An interview trap is a state-changing GET endpoint. If a navigation can trigger a mutation, assumptions about Lax cookies and safe methods become dangerous. Use appropriate request semantics and explicit protection for state changes; changing a cookie attribute should not be the only repair for a badly designed endpoint.

Also distinguish cookie scope from application authorization. A narrowly scoped cookie reduces some exposure, but the server still needs to decide whether the authenticated user may perform the requested action.

CORS is not a universal CSRF firewall

CORS controls browser-mediated access to cross-origin responses and governs preflight behavior for requests that require it. Some requests can be sent without a preflight. Denying the response to JavaScript does not reverse a server-side change that already happened.

For a JSON API that strictly requires a custom header and rejects simpler content types, a correctly configured preflight policy can form part of a CSRF defense. The details matter: accepting an alternative form submission path may reopen the boundary, and allowing an untrusted origin with credentials undermines the design.

Do not describe CORS as server authentication. Non-browser clients are not constrained by the browser's CORS enforcement, so the API still needs authentication and authorization independently. Similarly, an origin allowlist should compare parsed, exact origins rather than use a substring that accepts unrelated names.

A useful original debugging question is: “The console says CORS blocked the response, but the preference changed. Is that possible?” Yes: inspect whether the request was sent, whether credentials accompanied it, and whether the server committed a mutation. The console message alone is not the test oracle.

Match each control to its defense boundary

Use this table as an interview checklist, not as a claim that one row secures an entire application. Framework support and the actual deployment determine the complete implementation.

ControlMain contributionLimit you should explain
CSRF token validationRejects requests missing the expected request bindingSame-origin malicious script may access or use it
SameSite cookiesRestricts selected cross-site cookie deliverySame-site is broader than same-origin
Origin and Fetch Metadata policyFilters requests by browser contextNeeds explicit compatibility and missing-header handling
Context-aware output encodingKeeps untrusted values as data in the target contextOne encoder is not correct for every context
Safe DOM sinks and sanitizationAvoids unsafe interpretation or restricts allowed markupUnsafe post-sanitization mutation can undo the protection
CSPAdds constraints on script execution and resource useDoes not replace primary XSS prevention

Official guidance: OWASP's XSS prevention guidance distinguishes HTML, attribute, JavaScript, CSS, and URL contexts. Its CSRF guidance discusses framework protections, token patterns, origin verification, Fetch Metadata, and SameSite. Apply the relevant combination rather than treating their names as interchangeable. XSS prevention contexts, CSRF defense options

Why sanitization and encoding are not synonyms

If the product wants to display a user's label as plain text, a safe text-rendering path avoids interpreting it as markup. If the product intentionally permits rich HTML, it needs a suitable sanitization policy that allows selected structures while removing dangerous ones.

Encoding a string for HTML text does not automatically make it safe inside a script or a URL. A value can cross several interpreters before reaching its final use, so trace the actual sink. “We sanitize inputs” is too vague to establish what the browser will execute.

For the exercise, use an inert marker containing punctuation that would have structural meaning in HTML. Verify it appears as literal text in the label component. Separately verify the rich-text component accepts allowed formatting and rejects prohibited structures under its policy. These are different contracts and deserve different tests.

Framework escaping helps when data follows the safe default path. Review explicit escape hatches, raw HTML insertion, and third-party components that reinterpret strings. The fact that most of the application uses a modern framework does not establish the safety of every rendering boundary.

Design browser tests that isolate the failure

Create two controlled origins and a synthetic signed-in user. First verify the legitimate update succeeds. Then test a request from the second origin with a missing or invalid CSRF value. Confirm both the response decision and the persisted preference value.

Repeat with the application's supported content types and navigation patterns. Include an untrusted sibling host if the deployment has one. Record which browser and cookie configuration produced the result so the test does not accidentally depend on an unstated default.

For XSS prevention, test the actual component and sink used in production. A unit test of an unused escaping helper provides little evidence. Verify that untrusted content remains data, and use browser-level checks where DOM interpretation matters.

Test a protected action from trusted application code too. A defense that rejects every request is not a successful design. The positive case establishes that the test environment is functional; the negative cases establish the boundary.

Finally, separate observable failure from attribution. A missing token rejected at the server proves that check ran. It does not prove there are no alternative state-changing endpoints, no unsafe script sinks, or no permissive cross-origin route elsewhere.

Sources and Further Reading