
Step 1 of 7
Trace an Unwanted Authenticated Request
Trace how an external site can induce an authenticated account update, and identify the server-side acceptance gap that turns an automatically attached session credential into a CSRF risk.
Learning path · Level 11 · Tutorial 6
Recognize requests vulnerable to cross-site request forgery and explain how a front end participates in server-enforced defenses without claiming that CORS or cookie settings alone solve the problem.
Trace an Unwanted Authenticated Request
Trace how an external site can induce an authenticated account update, and identify the server-side acceptance gap that turns an automatically attached session credential into a CSRF risk. 2 min
Separate Site Boundaries from Origin Boundaries
Classify Northstar URL pairs by the stricter origin boundary and the broader schemeful site boundary. 2 min
Predict the Effect of an Explicit SameSite Policy
Predict whether an explicit SameSite policy permits the Northstar Account session cookie in specific request contexts, while keeping cookie eligibility separate from guaranteed delivery or state change. 3 min
Distinguish Request Prevention from Response Blocking
Determine whether a browser observation prevented the unwanted request itself or only limited access to its response. 3 min
Participate in a Server-Validated Token Flow
Use a server-issued anti-CSRF token in the documented Northstar Account client contract, and distinguish client participation from server-side validation. 4 min
Validate the Request Source on the Server
Evaluate an Origin and Referer validation policy that uses exact server-side matching, a narrow fallback, and rejection for source-evidence gaps. 2 min
Review and Repair a CSRF Defense Proposal
Review a flawed Northstar Account design, identify gaps across every state-changing entry point, and produce a justified client-and-server mitigation plan. 3 min

Step 1 of 7
Trace how an external site can induce an authenticated account update, and identify the server-side acceptance gap that turns an automatically attached session credential into a CSRF risk.
Cross-site request forgery (CSRF) happens when Other site causes a user’s browser to perform an unwanted authenticated, state-changing request to Northstar Account.
In this illustrated scenario, the user already has a valid session. Other site triggers a request that changes the account email to learner@example.test. The Browser attaches the session credential automatically, and the Application server treats the request as authenticated.
The important point is the unwanted server-side action—not whether Other site can view the result.
Follow the request, not just the page that started it.

The Browser can send an authenticated request and the server can change state even when Other site cannot read the response.
Automatic credentials are a condition to investigate, not proof of CSRF by themselves. A successful forgery also needs:
The attacker does not need to know the value of the session cookie. They also do not need to read the response. Their goal is to cause the Browser to send a request that the server accepts.
This differs from XSS: CSRF induces a request from outside the application; XSS runs attacker-controlled code in the application’s own origin.
Vulnerable variant — illustrative endpoint contract. A form-compatible request is accepted without CSRF validation.
POST https://app.northstar.example/api/profile/email
Content-Type: application/x-www-form-urlencoded
Cookie: session=<opaque-session>
email=learner@example.testExample
The vulnerable POST variant accepts application/x-www-form-urlencoded and changes the email without an effective request-forgery check. The Application server therefore sees an authenticated request and performs the update.
The fact that Other site cannot inspect the response does not undo an update that has already happened.
A trace states that the Browser attached session to a state-changing request initiated by Other site. What additional fact is needed to conclude that the operation is susceptible to CSRF?
Put this CSRF trace in order, from the precondition to the unwanted account update.

Step 2 of 7
Classify Northstar URL pairs by the stricter origin boundary and the broader schemeful site boundary.
Two URL boundaries answer different questions.
An origin is the exact combination of scheme, host, and port. All three must match for two URLs to be same-origin.
A schemeful site uses the scheme and the shared registrable domain. It does not separate sibling subdomains or ports in the way an origin does. So two URLs may be same-site while still being different origins.

Same-origin requires every origin component to match. Same-site is broader: it groups URLs by scheme and registrable domain.
Use https://app.northstar.example as the reference. For origin comparison, an omitted HTTPS port is effectively 443.
First compare scheme, host, and port exactly. Then, if the origins differ, compare the scheme and registrable domain to determine whether the pair is still same-site.
These components let you derive both classifications without treating a site as a trust boundary.
| URL | Scheme | Host | Effective port | Schemeful site |
|---|---|---|---|---|
| https://app.northstar.example | https | app.northstar.example | 443 | https + northstar.example |
| https://promo.northstar.example | https | promo.northstar.example | 443 | https + northstar.example |
| https://app.northstar.example:8443 | https | app.northstar.example | 8443 | https + northstar.example |
| http://app.northstar.example | http | app.northstar.example | 80 | http + northstar.example |
| https://outside.example | https | outside.example | 443 | https + outside.example |
https://app.northstar.example and https://promo.northstar.example have different hosts, so they are not same-origin. Yet they share the https scheme and the northstar.example registrable domain, so they are same-site.
Likewise, changing only the port creates a different origin without changing the site. Changing https to http changes both the origin and the schemeful site.
Warning
Same-site is a browser classification, not a statement that every sibling is equally trusted. promo.northstar.example could be lower-trust, separately operated, or compromised. A CSRF threat model must therefore distinguish “same-site” from “trusted application origin.”
Match each URL pair to its classification and reason.
Tap an item and then its matching pair.

Step 3 of 7
Predict whether an explicit SameSite policy permits the Northstar Account session cookie in specific request contexts, while keeping cookie eligibility separate from guaranteed delivery or state change.
For a request that attempts to update the Northstar Account email to learner@example.test, SameSite answers one narrow question: is the session cookie eligible in this request context?
It does not prove that a request was sent, that a response is readable, or that application state changed. Those outcomes depend on additional browser and server behavior.
Assume a matching cookie host and path, an HTTPS target, any required request credentials, and no extra browser privacy blocking. Compare explicit policies only; do not rely on a browser default.

Cookie eligibility is one stage in the flow; it is separate from whether a request is sent or state is changed.
For the session cookie, Northstar Account uses an explicit attribute such as:
Set-Cookie: session=<opaque-session>; Path=/; Secure; HttpOnly; SameSite=Lax
The table compares explicit values at the SameSite layer. The sibling request originates at https://promo.northstar.example and targets https://app.northstar.example: it is same-site, even though it is cross-origin.
“Yes” means the policy does not exclude the cookie in that stated context. It does not guarantee that the cookie is ultimately delivered.
| Explicit policy | Cross-site top-level GET | Cross-site form POST | Cross-site embedded request | Same-site sibling request |
|---|---|---|---|---|
| SameSite=Strict | No | No | No | Yes |
| SameSite=Lax | Yes | No | No | Yes |
| SameSite=None; Secure | Yes | Yes | Yes | Yes |
Tip
SameSite=None requires Secure and permits cross-site use at the SameSite layer. It is not a delivery guarantee: other cookie rules and browser privacy protections can still prevent delivery.
Likewise, SameSite=Strict does not reject every cross-origin request. A request from the same-site sibling is cross-origin but is not cross-site.
Assume the stated conditions from this step. In this order—cross-site top-level GET, cross-site form POST, cross-site embedded request, same-site sibling request—which complete prediction is correct for the session cookie?

Step 4 of 7
Determine whether a browser observation prevented the unwanted request itself or only limited access to its response.
A state-changing request must not use GET. Consider the Unsafe GET variant:
GET /api/profile/email?email=learner@example.test
Assume the authenticated session was set with:
Set-Cookie: session=<opaque-session>; Path=/; Secure; HttpOnly; SameSite=Lax
From https://outside.example, a top-level navigation to that URL can be a cross-site safe-method navigation. At the SameSite layer, the Lax session cookie is eligible. If the server treats that GET as an email update, the navigation can change the account even though the user did not intend the update.
A navigation is not proof of user intent. Use GET for retrieval only; moving a write to POST fixes HTTP semantics, but POST alone is not a CSRF defense.

A cross-site top-level GET navigation can be sent with a Lax-eligible cookie. The unsafe part is the server allowing GET to change state.
Warning
Do not infer safety from a hidden control, a disabled button, or the absence of a visible link. Those are interface choices. A server must reject request methods and request shapes that its contract does not permit.
Response access and request delivery are separate questions. The Vulnerable variant accepts application/x-www-form-urlencoded without CSRF validation. A page at https://outside.example can submit a normal cross-origin form to it.
Assume this explicit cookie policy:
Set-Cookie: session=<opaque-session>; Path=/; Secure; HttpOnly; SameSite=None
At the SameSite layer, that cookie is eligible for the cross-site form submission. The other site's page does not need to read the response for the Application server to process the request and change state. A browser restriction on reading a cross-origin response does not undo a request already accepted by the server.
Vulnerable variant — the server accepts this form-compatible request without CSRF validation.
POST /api/profile/email HTTP/1.1
Host: app.northstar.example
Content-Type: application/x-www-form-urlencoded
Cookie: session=<opaque-session>
email=learner@example.testThe Protected variant uses the documented JSON-and-token contract. Requiring JSON or a custom header can cause a browser to preflight a scripted cross-origin request. A rejected preflight prevents that particular scripted request from being sent.
That is narrower than a complete defense: it does not protect an Unsafe GET variant or a separate form-compatible endpoint. The server must enforce its contract for every state-changing request; changing GET to POST, or observing one CORS error, is not enough.
Compare the browser observations by asking first whether the operation request reached the Application server.
| Observation | Operation request sent? | What it does not establish |
|---|---|---|
| Cross-site top-level GET with Lax cookie | Can be sent | That GET is safe to use for a write |
| Form-compatible cross-origin POST | Can be sent | Other site must be able to read the response |
| Rejected JSON preflight | Target POST is not sent | Other write paths are protected |
| POST used instead of GET | Depends on server acceptance | The POST cannot be forged |
Compare the three traces. For each one, state whether the state-changing operation request reaches the Application server. For trace C, distinguish the preflight from the target POST. Then explain why POST alone and a CORS error do not prove that the email update is safe from CSRF.
Trace A
https://outside.exampleGET /api/profile/email?email=learner@example.testSameSite=LaxTrace B
https://outside.exampleapplication/x-www-form-urlencodedSameSite=NoneTrace C
https://outside.exampleSameSite=NoneWrite at least 250 characters (0/250).

Step 5 of 7
Use a server-issued anti-CSRF token in the documented Northstar Account client contract, and distinguish client participation from server-side validation.
Northstar Account uses a synchronizer-token contract. The Application server creates an unpredictable anti-CSRF token associated with the authenticated session, then makes that token available to the legitimate same-origin client.
For the protected update, the client first requests GET /api/csrf-token. It then sends POST /api/profile/email with JSON and the token in X-CSRF-Token. The server must compare the submitted token with the authenticated session before it changes the email to learner@example.test.
A cookie can authenticate a request automatically; the anti-CSRF token is the additional value that an unrelated site should not be able to supply under this contract.

The server decides whether a state-changing request is accepted; it must validate the token against the authenticated session.
The client participates in the contract; it does not enforce it alone. It obtains the server-issued token, verifies the documented response shape, and attaches the token in the required header. credentials: "same-origin" allows the same-origin request to use the existing browser-managed session.
If token acquisition fails or its JSON shape is invalid, stop the update. If the update returns 403 Forbidden, surface that rejection. Do not retry the update without the anti-CSRF token.
The Application server must reject a missing, invalid, or session-mismatched token before changing state. A fixed client-generated value, a header whose value is never checked, or a check that only tests whether a header exists does not provide this defense.
The function stops if it cannot obtain a valid token and treats a 403 Forbidden update as a rejection rather than removing the protection.
type CsrfTokenResponse = {
csrfToken: string;
};
export async function updateEmail(email: string): Promise<void> {
const tokenResponse = await fetch("/api/csrf-token", {
credentials: "same-origin"
});
if (!tokenResponse.ok) {
throw new Error("Could not acquire an anti-CSRF token.");
}
const tokenBody: unknown = await tokenResponse.json();
if (
typeof tokenBody !== "object" ||
tokenBody === null ||
!("csrfToken" in tokenBody) ||
typeof tokenBody.csrfToken !== "string" ||
tokenBody.csrfToken.length === 0
) {
throw new Error("Invalid anti-CSRF token response.");
}
const csrfToken = tokenBody.csrfToken;
const updateResponse = await fetch("/api/profile/email", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({ email })
});
if (updateResponse.status === 403) {
throw new Error("Email update was rejected by CSRF validation.");
}
if (updateResponse.status !== 204) {
throw new Error("Email update failed.");
}
}Warning
Keep an anti-CSRF token in its documented request field or header, not in a URL. URLs can be retained in history, logs, and referrer data.
Do not expose tokens to untrusted origins. XSS remains dangerous because injected code running in the application’s context can read accessible tokens or issue authenticated requests. Token validation is important, but it does not make XSS harmless.
Assume csrfToken was obtained and validated. Complete this compact Northstar Account client contract.
const tokenResponse = await fetch("/api/csrf-token", {
credentials:
});
const updateResponse = await fetch("/api/profile/email", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
: csrfToken
},
body: JSON.stringify({ email })
});Put the server-side decisions in the required order for a protected email update.

Step 6 of 7
Evaluate an Origin and Referer validation policy that uses exact server-side matching, a narrow fallback, and rejection for source-evidence gaps.
Source validation is an additional server-enforced check for a state-changing request. For browser requests, the server examines the browser-reported Origin header. If Origin is absent, a documented policy may examine Referer instead.
This check answers where the browser says the request came from. It does not replace session authentication, authorization, or the anti-CSRF token check. The Application server must complete all required checks before it updates the account email.

A request can be sent without being allowed to change state. The Application server makes the acceptance decision.
Tip
Do not ask client code to create Origin or Referer. They are browser-managed headers. The front end follows the documented protected request contract; the server parses and evaluates the source evidence it receives.
Use an explicit allowlist containing parsed origins, not string fragments. In this policy, the only trusted source origin is https://app.northstar.example.
An origin includes scheme, host, and port. Therefore, a sibling origin is not trusted merely because it is same-site. Referer is a full URL, so the server parses it and compares its origin—not its complete page path—to the allowlist.
Apply this policy at the server before mutation. “Allow source condition” means only that source validation passed; the protected endpoint still needs its session, anti-CSRF token, and authorization checks.
| Request evidence | Server decision |
|---|---|
| Origin: https://app.northstar.example | Allow source condition |
| Origin: https://promo.northstar.example | Reject; sibling is not allowlisted |
| Origin: https://app.northstar.example.outside.example | Reject; hostname only looks similar |
| Origin: null | Reject; do not use Referer as rescue |
| Origin absent; Referer: https://app.northstar.example/profile | Parse Referer origin; allow source condition |
| Origin absent; Referer malformed or untrusted | Reject |
| Origin and Referer both absent | Reject |
Example
The fallback rule is deliberately narrow:
Origin is present, parse it and decide from that header alone.null, reject the state-changing request. Do not silently switch to Referer.Origin is absent may the server parse Referer and compare its origin with the allowlist.After source validation passes, the server still validates the anti-CSRF token associated with the authenticated session and performs authorization before changing the email.
Warning
CORS behavior and a hidden or disabled client control do not replace this endpoint policy. A response-access restriction is not evidence that the Application server rejected every unwanted state-changing request.
Likewise, an allowed source is not proof that a request is authorized or genuine. Source validation complements the Protected variant's server-validated anti-CSRF token, session handling, and authorization; it does not replace them.
Match each request evidence case to the server action required before POST /api/profile/email can update learner@example.test.
Tap an item and then its matching pair.

Step 7 of 7
Review a flawed Northstar Account design, identify gaps across every state-changing entry point, and produce a justified client-and-server mitigation plan.
Review a proposed defense as a chain, not as a single setting:
session automatically in that context?A CSRF finding needs both an attacker-triggerable state-changing request and server acceptance without an effective forgery check. Automatic credentials alone are not enough.

Response readability is separate from whether a state-changing request reached and was accepted by the server.
Tip
Do not treat a blocked response as proof that no change occurred. CORS governs particular browser request and response behaviors; it is not a server-side rule that makes every account-update route reject a forgery.
A repair must close every state-changing entry point and divide responsibilities correctly. The client follows the documented contract; the Application server enforces it. Cookie policy, CORS, and XSS controls contribute different protections.
Example
Northstar Account should remove or reject these alternatives and retain one server-enforced path:
GET /api/profile/email?email=learner@example.test changes state. Reject this design: GET must not update the account email.application/x-www-form-urlencoded and performs the update without CSRF validation. A cross-site form can target this shape.GET /api/csrf-token returns {"csrfToken":"<server-issued-token>"}. The client then sends POST /api/profile/email with JSON body {"email":"learner@example.test"} and X-CSRF-Token: <server-issued-token>. A valid update returns 204 No Content; failed CSRF validation returns 403 Forbidden.The protected session cookie is Set-Cookie: session=<opaque-session>; Path=/; Secure; HttpOnly; SameSite=Lax.
Each layer has a useful but limited job.
| Layer | Required contribution | Not a substitute for |
|---|---|---|
| Client | Get the server-issued anti-CSRF token; send it in X-CSRF-Token; surface token or 403 failures. | Server validation |
| Application server | Reject state-changing GET; enforce JSON contract; validate token and trusted request source before changing state. | A hidden control or client code |
| SameSite=Lax | Reduces some cross-site cookie contexts. | Protection for same-site sibling origins or unsafe GET designs |
| CORS | Can constrain a particular scripted cross-origin interaction. | Rejection of form-compatible or alternate routes |
| XSS prevention | Helps prevent hostile code in the application context. | Token validation; XSS can issue same-origin requests or access an available token |
Match each review concern to its appropriate repair responsibility.
Tap an item and then its matching pair.
Northstar Account has this proposed design:
GET /api/profile/email?email=learner@example.test updates the account email.POST /api/profile/email accepts application/x-www-form-urlencoded; its handler ignores X-CSRF-Token and performs no token validation.SameSite=Lax makes the session cookie safe, and CORS prevents any attack.Assume a signed-in user visits https://outside.example. That site causes a top-level HTTPS navigation using the Unsafe GET variant. The target cookie host and path match, no additional privacy blocking applies, and the session cookie explicitly uses SameSite=Lax.
Write a concise four-part mitigation review:
Use the terms state-changing request, same-site, anti-CSRF token, and server validation accurately.
Write at least 350 characters (0/350).
Summary
Use this sequence whenever you review an authenticated account update.
Congratulations! You completed: Recognize and Mitigate Cross-Site Request Forgery
You completed this level!
Up next: Testing Front-End Behavior
Test TypeScript Logic with VitestSet up Vitest in a local TypeScript project and write independent tests for application rules and runtime data parsers, including edge cases and expected failures.Thousands of online courses in video, ebooks and audiobooks.
To test your knowledge during online courses
Generated directly from your cell phone's photo gallery and sent to your email
Download our app via QR Code or the links below:.
+ 10 million
students
Free and Valid
Certificate
60 thousand free
exercises
4.8/5 rating in
app stores
Free courses in
video and ebooks