Skip to content

Permissions as Sets

Permissions as sets is a way to model authorisation as bounded membership: a user, origin, action, and resource are either inside or outside the allowed set. In browser security, that boundary is shaped by the same-origin policy, cookies, CORS, CSRF tokens, and SameSite rules.

The problem is ambient authority. A logged-in browser carries cookies automatically, so a request to a site may be authorised even when the page that caused it came from somewhere else. Without a crisp boundary, an attacker’s page can borrow the victim’s authenticated browser state and widen the blast radius from one malicious page to another account’s privileged actions.

The browser’s main boundary is origin: scheme, host, and port together. JavaScript from one origin can usually read responses from that same origin, but not from another unless CORS permits it. However, the same-origin policy is often misunderstood: it mostly blocks reading cross-origin responses, not every act of sending cross-origin traffic. Forms, images, and some requests can still be initiated.

CSRF exploits that distinction. An attacker cannot read the victim’s bank page, but can cause the victim’s browser to submit a state-changing request to it. If the browser attaches the victim’s session cookie and the server accepts only that cookie as proof, the request falls inside the server’s permission set even though the attacker’s page should not have that authority.

The trade-off is that tighter sets require extra protocol state and careful compatibility choices. CSRF tokens add server validation and form plumbing. SameSite cookies reduce accidental cross-site credential sending, but can break legitimate embedded or identity-provider flows. CORS is not a substitute, because it governs whether script may read a response, not whether a form submission reaches the server.

Engineers meet this in web frameworks, cookie settings, and authentication flows. Django and Rails validate CSRF tokens on unsafe methods and reject missing or invalid tokens. OAuth and OpenID Connect use a state value to bind a redirect response to the browser session that started it. The practical rule is simple: state-changing actions need proof stronger than the presence of a cookie.

Common questions

Is the same-origin policy the same as CSRF protection?
No. The same-origin policy stops a page from reading many cross-origin responses, but it does not by itself stop the browser from sending cross-origin requests. CSRF protection checks that a state-changing request was intentionally created by the legitimate site, usually with a token or equivalent session-bound value.
Why describe permissions as sets?
It forces precision. Instead of saying a user is authorised in general, you ask whether this user, from this origin, may perform this action on this resource. CSRF happens when the server checks only part of that set, such as the session cookie, and ignores where the request intention came from.
Does CORS prevent CSRF?
Usually not. CORS controls whether browser JavaScript is allowed to access a cross-origin response. A forged form submission can still be sent without the attacker reading the result. CSRF defences must be enforced by the target server, commonly with tokens, SameSite cookie policy, and avoiding state changes through safe methods.
When is SameSite enough?
It depends on the application’s flows and threat model. SameSite can greatly reduce ambient cookie sending on cross-site requests, but some legitimate login, payment, or embedded flows need cross-site cookies. For sensitive state changes, treat SameSite as a useful layer, not a complete replacement for request-bound CSRF validation.