Cross-site Request Forgery
Concept
A vulnerability where an attacker borrows a user's existing logged-in state to make a service accept a request the user never intended to send.
Why it exists
Browsers have followed one rule for a very long time: when sending a request to an address, attach whatever cookies are stored for that address. A cookie is the short marker a server leaves with the browser after login, and a request carrying that marker is treated by the server as coming from the logged-in person.
Without the rule you would have to log in again on every screen, so it exists for convenience. The catch is that when the browser attaches the marker it looks only at where the request is going, never at who composed it. A request the user created by clicking a button and a request quietly composed by some unrelated site both get the same marker as long as the destination matches.
The way this surfaced as a real incident survives as an old message-board story. Someone embeds an invisible image in a community post, and the image's address is actually a bank's money-transfer request. Anyone who opened the post while happening to be logged into that bank had a transfer executed — they had only read a page. From the bank's side, it was a normal request from an authenticated customer.
Cross-site request forgery (CSRF) is the name for that maneuver. It doesn't steal a password or break into a server; it pushes a door that was already unlocked, using someone else's hand.
How it works
The attacker gets the victim's browser to send the request, and the browser attaches the login marker on its own. Five steps.
- The user logs into Pagedeck. A marker is stored in the browser and usually survives closing the tab, from a few hours to a few days.
- The user opens another site, in another tab or after clicking a link in an email. It might belong to the attacker, or it might be an ordinary forum where anyone can post something that other people load.
- Hidden inside that page is a request addressed to Pagedeck. The most common form is an invisible form that submits itself the moment the page loads.
- The browser sends that request and attaches the marker from step 1, because the destination is Pagedeck and that's what the rule says to do.
- Pagedeck's server sees a valid marker, concludes the logged-in user sent it, and carries it out. A document is deleted, external sharing is switched on, a teammate's permissions change.
One detail decides the character of this attack: the attacker can cause the request but cannot read the response, because a browser won't hand a cross-site response back to the page's code. That makes it useless for extracting data and useful only for requests that change, delete, or send something. Turned around, that means only state-changing requests need protecting.
Defenses aim at the same point: require one thing the browser will not attach by itself. If the server embeds an unpredictable string when it serves the screen and checks that the request carries it back, a page on another site has no way to know the value and the request gets rejected. Marking cookies so they aren't attached to requests initiated from other sites is used alongside that, and for the few operations where the damage would be hard to undo — changing a password, transferring money — asking for the password again at the moment of the action adds a step no forged request can supply.
Where it shows up
The name comes up in three places.
- While building features. Every time a state-changing request is added, someone checks that the protection is in place. Read-only screens don't need it; deletes, permission changes, payments, and saved settings do. Most current web frameworks turn the defense on by default, and incidents usually trace back to a setting somebody disabled because it was inconvenient during development and never re-enabled.
- In code review and security checks. It occupies a line on published checklists like the OWASP Top 10, so the name gets read aloud often. Security questionnaires that enterprise customers send before signing almost always ask about it.
- When choosing how authentication works. Carrying login state in cookies brings this problem along, while a setup where the front-end code attaches the token to each request as a header gives the browser nothing to attach automatically, so the attack has no footing. That's why the term shows up whenever authentication design is on the table.
It's worth separating this from authorization, which sits on a different layer. Authorization asks whether this person may do this thing — and here the request borrows the hand of someone who legitimately may, so authorization alone never filters it out.
How it sounds at work
"This request changes state and the token check is missing."
A request pushed in from another site would go straight through.
"That setting was turned off for local development and it shipped that way."
The protection is disabled in the deployed build.
"If we send the token in a header instead of a cookie, this stops being a concern."
Nothing gets attached automatically, so the attack doesn't work.
At Pagedeck, the place this actually bit was document sharing settings. The request that flips a document to public was open to anyone who knew the address. Reviewing it, Theo found the protection missing on that one request — it had been built in a hurry ahead of the surrounding screens and had bypassed the framework default.
Anyone who planted a request on the internal message board could have quietly flipped a reader's documents to public. It never happened, but had it happened nobody would have noticed, because the change is recorded as the user's own.
What people get wrong
The most common belief is that rigorous login checks prevent it. It's easy to picture someone breaking into an account. This attack doesn't break the login check, though — it borrows a session that already passed. To the server the marker is genuine and the permissions are correct. Tighten authentication as much as you like and the hole stays exactly where it was, and if it's exploited the logs record the user doing it to themselves.
Assuming an encrypted connection covers it is the other one. The padlock in the address bar reads as safety. Encryption stops someone in the middle from reading traffic, and what happens here is a real user's browser sending a request over a normal path. There is nobody in the middle for encryption to stop. Firewalls and location restrictions miss it for the same reason: the request always originates from the user's own device.
Easily confused with
| Term | What happens | How it differs from CSRF |
|---|---|---|
| Cross-site scripting (XSS) | An attacker's script runs inside your own page | Because the code runs within your page, it can read responses, which is why it extends to stealing data. CSRF only causes a request and never sees the result. The defenses differ too — that one centers on filtering the values you print into a page |
Where to go next
- Application security
see where this vulnerability sits in the wider security landscape
- XSS
the similarly named vulnerability with a different shape
Last updated 2026-09-16