The Big Picture: Separate Apartments in One Building
You probably have several tabs open at the same time: your email, a bank, a news site and some random page. Your cookies make you logged in to some of them. Now imagine the random page could quietly ask your bank "show me my account" using your cookies, and read the answer. That would be a disaster.
The browser prevents this with one of the most important rules on the web: the Same-Origin Policy (SOP). Think of each website as a separate apartment. Visitors may ring the doorbell (send requests), but they may not walk in and read the papers on the table.
Section 1 showed the process walls (the operating system keeps renderers apart). The SOP is a different wall: a set of rules inside the browser about what web code may read.
6.1 Why It Exists (Security Isolation Between Sites)
What it is: A rule that stops code from one origin from reading data that belongs to another origin.
What is an origin? An origin is three things together:
https://www.example.com:443/some/page
└─┬─┘ └──────┬──────┘ └┬┘
scheme host port origin = scheme + host + port
Two URLs are the same origin only if all three match. The path does not matter.
Compare with https://example.com/a | Same origin? | Why |
|---|---|---|
https://example.com/b/c | Yes | Only the path differs |
http://example.com/a | No | Scheme differs (http vs https) |
https://www.example.com/a | No | Host differs (a sub-domain counts as different) |
https://example.com:8443/a | No | Port differs (443 is the default for https) |
https://example.org/a | No | Different host |
Why it is needed. The browser automatically attaches cookies to requests (Section 5.1). Without the SOP, any page you visit could use your logged-in cookies to read your private mail or bank pages. With it, a page may cause a request, but a page from evil.example cannot read the response from bank.example. Cookies plus SOP are the pair that keeps logged-in sessions safe.
evil.example page bank.example
┌────────────────────┐ request ┌───────────────┐
│ script: fetch( │ ──────────► │ (cookies sent │
│ "https://bank...")│ │ by browser) │
│ │ ◄────────── │ response │
│ SOP: "You may NOT │ BLOCKED └───────────────┘
│ read this reply." │ from reading
└────────────────────┘
6.2 What It Restricts (and What It Allows)
Blocked by default (cross-origin):
| Blocked | Example |
|---|---|
Reading responses to requests (fetch, XMLHttpRequest) to another origin | A script on a.example cannot read JSON from b.example. |
| Reading or changing the DOM of a page or frame from another origin | A page cannot reach into an embedded b.example frame and read its text. |
| Reading storage of another origin | localStorage, IndexedDB and cookies of b.example are not visible to a.example. |
Allowed by default (embedding, not reading): a page can display or run many things from other origins, as long as it cannot read their contents directly:
| Allowed | Example |
|---|---|
| Images | <img src="https://other.example/pic.png"> |
| Scripts | <script src="https://cdn.example/lib.js"> (the script runs with your page's powers, so only include sources you trust) |
| Stylesheets, fonts, media | CSS from a CDN, video, audio |
| Frames | <iframe src="..."> (shown, but not readable) |
| Links and form submits | Clicking a link, or a form that posts to another site |
This matters: the web would break if sites could not use pictures and libraries from elsewhere. The rule is "you may show it, you may not read it."
Process isolation backs this up. Because Chrome and Edge place different sites in different renderer processes (Section 1.2), even a bug in the browser's SOP checks is harder to exploit. Think of it as the SOP being the rule and site isolation being the lock.
6.3 Opening the Door on Purpose: CORS
Sometimes a site wants another site to read its data (for example a public data service used by many web apps). The server can allow it using CORS (Cross-Origin Resource Sharing): headers in its response.
Page at https://app.example runs: fetch("https://api.other.example/data")
Browser adds: Origin: https://app.example
Server answers: Access-Control-Allow-Origin: https://app.example
Browser checks: "Does the allowed origin match mine?"
yes -> JavaScript may read the response
no / missing header -> blocked, error in Console
| Header | Who sends it | Meaning |
|---|---|---|
Origin | Browser (request) | "This request comes from this origin." Page scripts cannot fake it. |
Access-Control-Allow-Origin | Server (response) | Which origin may read the answer (a specific origin, or * for anyone, only for non-private data). |
Access-Control-Allow-Methods, -Headers | Server | Which methods and extra headers are allowed. |
Access-Control-Allow-Credentials | Server | Whether cookies may be included. Cannot be combined with *. |
Preflight. For "risky" requests (for example a PUT/DELETE, or JSON with custom headers), the browser first sends a small question, an OPTIONS request, before the real one:
1. Browser ── OPTIONS /data Origin: https://app.example
Access-Control-Request-Method: PUT ──► server
2. Browser ◄── Access-Control-Allow-Origin: https://app.example
Access-Control-Allow-Methods: PUT ── server
3. Only if the answer says "yes" does the browser send the real PUT.
You will see these OPTIONS calls in DevTools' Network tab. Two points that surprise beginners:
- CORS is enforced by the browser, not by the server. A command-line tool is not stopped by CORS. CORS protects the user's browser session, not the server's data from all clients.
- A "CORS error" in the Console means the server did not give the right permission. You cannot fix it from the page; the server's owner must change its headers.
6.4 Why Cookies and SOP Matter Together
Cookies make requests to a site carry your identity. The SOP stops other sites from reading the replies. But the SOP does not stop another site from sending a request (a form post or image load) to your bank, and the browser may attach cookies. That gap is the opening for CSRF below, which is why the SameSite cookie flag (Section 5.1) exists. Defence comes in layers: SOP, CORS rules, cookie flags, process isolation.
6.5 Two Common Web Attacks, in Simple Words (Defence Only)
We describe these only so you can understand how browsers defend against them.
XSS (Cross-Site Scripting). If a website carelessly shows text that a user typed (for example a comment) without cleaning it, an attacker can type text that is really a script. When other visitors load the page, the script runs inside the trusted site's origin, so the SOP allows it to read that site's data, for example anything JavaScript can see. The attacker's code is now "inside the apartment". Defences: the site must escape (neutralise) user text when displaying it; use a Content Security Policy (a header listing which scripts may run); and mark session cookies HttpOnly so injected scripts cannot read them.
CSRF (Cross-Site Request Forgery). A malicious page tricks your browser into sending a request to another site where you are logged in (for example a hidden form that submits "change my email"). Your cookies go along, so the site may think you asked. The attacker cannot read the reply (SOP), but the action may still happen. Defences: SameSite cookies, secret anti-CSRF tokens in forms that other sites cannot know, and checking the Origin header on the server.
| Attack | Tricks the... | Main defence |
|---|---|---|
| XSS | Site into running attacker text as code | Escape output, CSP, HttpOnly cookies |
| CSRF | Browser into sending a request with your cookies | SameSite cookies, anti-CSRF tokens |
For you as a user: keep the browser updated (security fixes ship often), install few extensions, and do not paste text from strangers into the DevTools Console. Some sites show a warning about this because attackers use it to trick people into running harmful code.
Summary
| Term | Plain meaning |
|---|---|
| Origin | scheme + host + port |
| Same-Origin Policy | Code from one origin may not read another origin's data |
| Blocked | Reading cross-origin responses, DOM and storage |
| Allowed | Embedding images, scripts, styles, frames, links |
| CORS | Server headers that let chosen origins read its responses |
| Preflight | OPTIONS question before a risky cross-origin request |
Access-Control-Allow-Origin | Which origin may read the response |
| XSS | Attacker's script runs inside a trusted site |
| CSRF | Another site makes your browser send a logged-in request |
| SameSite / HttpOnly / CSP | Cookie flag / hide cookie from scripts / script allow-list |