What goes wrong in CSRF
In cross-site request forgery, another context causes the browser to make a request that the server treats as an action by the signed-in user. The triggering context need not be able to read the response. ‘Our CORS rule prevents the other website from reading’ therefore does not suffice as evidence.
A synthetic example of your own: account management accepts a notification-address change solely on the session cookie. Without checking whether the action comes from the intended application context, an unwanted request can use the same session. The specific risk depends on which requests the browser permits and which cookies it sends with them.
The OWASP CSRF guidance covers token-based safeguards and additional context checks. These are development recommendations, not a claim that every cookie-based API is vulnerable in the same way.
Same-origin and same-site are different boundaries
CORS works with origins: scheme, host and port. SameSite cookies refer to a site context, particularly scheme and registrable domain for ordinary web addresses. Two HTTPS subdomains can therefore be same-site but cross-origin.
On narrow screens, scroll the table sideways.
| Example pair | For the usual HTTPS case |
|---|---|
https://app.example.com and https://api.example.com | Different origins, same site |
https://app.example.com and https://app.example.com:8443 | Different origins, same site |
https://app.example.com and https://other.example.net | Different origins and sites |
This matters when other subdomains host third-party content or other tenants. SameSite=Strict does not make every neighbouring subdomain an untrusted cross-site context. Document who controls the entire affected site rather than considering only the API host. The MDN cookie description explains SameSite values.
Choose cookie attributes to suit the session
A synthetic header for a server-side session could look like this:
Set-Cookie: __Host-session=synthetic-session-value; Path=/; Secure; HttpOnly; SameSite=Lax
The value is an illustrative marker, not a usable session key. The example is not a complete session configuration. The attributes address different subtasks:
Securelimits transmission to the intended secure transport.HttpOnlyprevents JavaScript from reading the cookie directly. Browser code can still trigger requests that include it.SameSiterestricts certain cross-site sending contexts.LaxandStrictaffect legitimate navigation and login flows differently.- In supporting browsers, the
__Host-prefix requiresSecure,Path=/and noDomainattribute, among other conditions; this limits the cookie's scope to the host setting it.
For required cross-site cookies, SameSite=None additionally requires Secure. Browser policies may still restrict their use further. Do not choose None as a blanket login-error fix. First check whether the actual setup is cross-site at all. MDN: Set-Cookie gives the details and prefix boundaries.
Use a complete CSRF mechanism
First examine the existing framework feature: which routes does it protect, when does protection run, how does your client obtain the required value, and how does it handle errors? Do not adopt only the name of a CSRF header.
In a session-bound token mechanism, the server creates an unpredictable value and binds it to the intended session context. Your client sends it with protected actions, often in a request header. The server checks it in addition to the access cookie. A token arriving only in an automatically sent cookie does not itself provide this additional binding.
Signed double-submit mechanisms also exist, as does protection through a mandatory custom header with strict origin permission for narrowly defined AJAX APIs. Their prerequisites differ. Choose your framework's documented variant; a naïve comparison of two freely settable cookie/form values is no universal substitute. The OWASP sections on token patterns and API headers describe these differences.
In token-based CSRF protection, the value does not belong in a URL, where it may enter history or logs. If a custom header is used, a cross-origin frontend needs corresponding CORS permission for that header. This still permits only trusted frontends; arbitrary origin reflection would undermine the boundary.
Consider JSON, HTTP methods and context checks together
An endpoint accepting only a correctly labelled JSON body and requiring an appropriate custom header has different browser conditions from a form endpoint. But the word ‘JSON’ does not itself prevent CSRF. If the same handler also accepts text/plain or form data, the assumed boundary may disappear. Check the media type actually accepted and every compatible input path.
State changes do not belong in GET handlers. A cookie with SameSite=Lax may accompany certain navigations; a supposedly read-only link must therefore not change an account setting. The OWASP limitations of SameSite make this dependency clear.
Origin/Referer checks and Fetch Metadata can provide additional context. Define permitted cases and treatment of missing information. An exception for known non-browser integrations requires its own justified access model; ‘header missing, therefore trust’ is no general rule. Likewise, proxy headers can support comparison only when the proxy boundary and its sanitisation are established.
Explicit tokens and XSS change the assessment
If an access token is explicitly set in Authorization only by your JavaScript, another page normally does not automatically possess it. This reduces the classic CSRF path for these requests. Still examine login, refresh and other routes that may use cookies again.
Moving a token into JavaScript storage trades risks: injected code in your own origin may read tokens or trigger permitted actions, depending on storage. HttpOnly does not prevent every action by such code either. The CSP foundations help with part of this browser protection; input/output handling and dependencies remain other tasks. Choose the authentication architecture deliberately.
Prepare your own evidence using harmless actions
Use your own test application, test accounts and a reversible synthetic change. Check the normal flow, a missing or incorrect CSRF token, another origin you control for testing, a neighbouring subdomain in the planned model and missing context headers. Demonstrate not only the status but also that the rejected request did not change state.
Include login, session renewal, logout and expired sessions. Protection covering only the normal edit button may miss other state-changing paths. Introduce new rules in a controlled way and keep a secure previous configuration ready. For legitimate failures, investigate the affected flow; do not disable checking globally.
The API Security Check performs no cookie or CSRF checks with signed-in accounts. These require application configuration, code review and your own browser and integration tests. If a response is blocked despite the correct protection decision, CORS error diagnosis helps. Sources checked: 27 September 2026.
Sources and date
Sources checked: 27 September 2026. Links also appear alongside the statements they support.