CS 161, Lesson 37, in 50 slides. It covers the browser's core isolation boundary: why the same-origin policy exists, in section 19; what an origin is, namely the scheme, host, and port, in section 19.1; and what the policy restricts against what it allows, which is the difference between reading and embedding, in section 19.2. That same section also gives the exam-critical rules for assigning an origin to scripts, images, and frames, and covers controlled cross-origin communication through postMessage. It is anchored to textbook sections 19.1 to 19.2.
Subject: Computer Security · 81 slides · applied lesson
Open the interactive version of this deck · Homework for this lesson
Title
CS 161 · Lesson 37 of 45
The browser's core isolation boundary — why it exists · what an origin is · read vs embed · the script/image/frame origin rules · postMessage
Objectives
src).<script> runs with the INCLUDING page's origin; an <img>/<iframe> get the origin they come FROM.Warm-up
Discussion prompt
Before we open L37 · The Same-Origin Policy: without looking back, what was the main idea of L36 · Web Basics: URLs, HTTP, HTML, the DOM & JavaScript, and what could you do by the end of it that you could not do before?
Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.
Answer:
CS 161, Lesson 36, in 57 slides. It covers the browser and protocol model that sits behind every web attack: the parts of a URL in section 18.1, the HTTP request and response model with GET against POST in sections 18.2 to 18.5, the webpage as a distributed application together with HTML and frame isolation in sections 18.6 and 18.7, and CSS, JavaScript, the DOM, and the JavaScript sandbox in sections 18.8 and 18.9. It is anchored to textbook sections 18.1 to 18.9.
Concept
Concrete scenario: in one tab you have www.gmail.com open and logged in. In another tab you have www.evil.com, a malicious site. Both are running JavaScript in the same browser at the same time.
What you absolutely do NOT want: evil.com's JavaScript reaching over and reading your emails, or sending mail as you. The browser has to keep the two pages apart.
Counterexample
Discussion prompt
Concrete scenario: in one tab you have www.gmail.com open and logged in. In another tab you have www.evil.com, a malicious site. Both are running JavaScript in the same browser at the same time.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
What you absolutely do NOT want: evil.com's JavaScript reaching over and reading your emails, or sending mail as you. The browser has to keep the two pages apart.
Concept
Browsers enforce the same-origin policy (SOP): every webpage is isolated from every other page — EXCEPT when two pages share the same origin. Isolation is the default; sharing is the narrow exception.
Same-Origin Policy (SOP) — A browser rule that isolates each webpage from every other page, so one page's JavaScript cannot read another page's data — unless the two pages have the SAME ORIGIN. Same-origin pages may access each other freely; cross-origin pages are walled off.
Concept
The flip side of isolation: two pages that DO share an origin get full mutual access. Same-origin JavaScript can read and modify the other page's DOM, see its responses, and use its cookies.
So the SOP is binary at the origin boundary: same origin ⇒ full trust; different origin ⇒ walled off. There is no 'partial' access between two origins by default.
Analogy
Discussion prompt
Explain §19 Same-origin pages trust each other fully by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
The flip side of isolation: two pages that DO share an origin get full mutual access. Same-origin JavaScript can read and modify the other page's DOM, see its responses, and use its cookies.
Intuition
Think of the browser as an apartment building. Each origin is a locked apartment. Two pages in the SAME apartment (same origin) can freely walk between rooms and read each other's things.
But your evil.com tab is in a DIFFERENT apartment from your Gmail tab. It cannot walk through the wall to read Gmail's mail. The wall between apartments is the same-origin policy.
Ask yourself: just because two pages are open at once, can one read the other? (No — being open side by side doesn't grant access; only sharing an origin does.)
Explain it
Discussion prompt
Explain §19 Each origin is its own walled apartment to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Think of the browser as an apartment building. Each origin is a locked apartment. Two pages in the SAME apartment (same origin) can freely walk between rooms and read each other's things.
Pattern
Predict first
The table runs: Read the Gmail tab's DOM (your inbox) | BLOCKED | your emails stolen · Read gmail.com's cookies | BLOCKED | your session hijacked
In §19 Trace the threat the SOP defeats, given the rows so far: what is the next one — the row where evil.com's JS attempts is fetch gmail.com and read the reply?
Correct: fetch gmail.com and read the reply | BLOCKED | mail read as you
| evil.com's JS attempts | with the SOP | without the SOP |
|---|---|---|
| Read the Gmail tab's DOM (your inbox) | BLOCKED | your emails stolen |
| Read gmail.com's cookies | BLOCKED | your session hijacked |
| fetch gmail.com and read the reply | BLOCKED | mail read as you |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. Both pages run JavaScript in the same browser process model — the danger is one reaching the other.
Worked example
evil.com loads in tab 1; gmail.com (logged in) loads in tab 2
Why: Both pages run JavaScript in the same browser process model — the danger is one reaching the other.
| evil.com's JS attempts | with the SOP | without the SOP |
|---|---|---|
| Read the Gmail tab's DOM (your inbox) | BLOCKED | your emails stolen |
| Read gmail.com's cookies | BLOCKED | your session hijacked |
| fetch gmail.com and read the reply | BLOCKED | mail read as you |
Verify: every dangerous read is a CROSS-ORIGIN read, which the SOP blocks
Why: §19: the SOP's job is exactly to block one origin's JS from reading another origin's data. evil.com ≠ gmail.com, so all three attacks are stopped at the origin boundary.
Comparison
Comparison matrix
From §19 Trace the threat the SOP defeats: refill the with the SOP column from what you know. The rest of the table is as it appeared.
| evil.com's JS attempts | with the SOP | without the SOP |
|---|---|---|
| Read the Gmail tab's DOM (your inbox) | BLOCKED | your emails stolen |
| Read gmail.com's cookies | BLOCKED | your session hijacked |
| fetch gmail.com and read the reply | BLOCKED | mail read as you |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'evil.com and Gmail are both open in my browser, so evil.com's JavaScript can just read what's in the Gmail tab.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: The same-origin policy ISOLATES them.
A student: when can one page actually read another page's data?
Why: The same-origin policy ISOLATES them. Being open at the same time grants nothing — evil.com (a different origin) cannot read the Gmail tab's DOM, responses, or cookies.
Trap
A student: 'evil.com and Gmail are both open in my browser, so evil.com's JavaScript can just read what's in the Gmail tab.'
Assume co-resident tabs share access to each other's data
Why: Wrong. The same-origin policy ISOLATES them. Being open at the same time grants nothing — evil.com (a different origin) cannot read the Gmail tab's DOM, responses, or cookies.
A student: when can one page actually read another page's data?
Only when the two pages share the SAME origin
Why: §19: the SOP isolates every page from every other page by default. Cross-origin reads are blocked; the sole exception is two pages with an identical origin. evil.com ≠ gmail.com, so no access.
Intuition
Notice the design choice: the browser doesn't start with 'everything can talk' and bolt on restrictions. It starts FULLY isolated and carves out one narrow exception — same origin.
That's secure-by-default thinking (L2/L3): deny first, permit deliberately. Every cross-origin interaction has to be explicitly allowed (embedding, postMessage, CORS) rather than assumed.
Ask yourself: if a new browser feature exposes data, what's the safe default? (Cross-origin DENIED — same as the SOP — and let sites opt in if they truly need sharing.)
Socratic
Discussion prompt
Notice the design choice: the browser doesn't start with 'everything can talk' and bolt on restrictions. It starts FULLY isolated and carves out one narrow exception — same origin.
Suppose that were not true. What is the first thing in L37 · The Same-Origin Policy that would stop working?
Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.
Answer:
Ask yourself: if a new browser feature exposes data, what's the safe default? (Cross-origin DENIED — same as the SOP — and let sites opt in if they truly need sharing.)
Section
Part 1 · §19.1 protocol + domain + port
Concept
The SOP is defined over origins, so we need an exact definition. An origin is built from three pieces of a URL — and only these three.
Origin — The triple (PROTOCOL, DOMAIN, PORT). Two pages have the same origin only if ALL THREE match exactly (as strings). The path, query, and fragment are NOT part of the origin.
Definition probe
Sort into buckets
Every line below is part of the definition of Same-Origin Policy (SOP) or of Origin — one or the other, never both. Put each where it belongs.
Concept
Take the URL http://wikipedia.org:80/wiki/Cat. Its origin is everything that names WHERE the resource lives — protocol, domain, and port — and nothing about WHICH resource.
http :// wikipedia.org : 80 / wiki/Cat
\__/ \___________/ \_/ \_______/
PROTOCOL DOMAIN PORT path
\_________ origin ________/ (NOT origin)Same-origin test: line up two URLs and compare protocol, domain, and port. If all three are character-for-character identical, same origin. If any differs, different origin.
Concept
If a URL omits the port, the browser fills in the protocol's default port: 80 for HTTP, 443 for HTTPS. So http://wikipedia.org is treated as http://wikipedia.org:80.
| URL | effective port |
|---|---|
| http://wikipedia.org | 80 (HTTP default) |
| http://wikipedia.org:80 | 80 (explicit) |
| https://wikipedia.org | 443 (HTTPS default) |
| http://wikipedia.org:81 | 81 (explicit, NOT default) |
So http://wikipedia.org ≡ http://wikipedia.org:80 (same origin), but http://wikipedia.org ≠ http://wikipedia.org:81 — the port differs.
Trade off
Comparison matrix
From §19.1 Default ports: every row here is a choice with a cost. Fill the effective port column, then say which row you would actually pick and what you give up for it.
| URL | effective port |
|---|---|
| http://wikipedia.org | 80 (HTTP default) |
| http://wikipedia.org:80 | 80 (explicit) |
| https://wikipedia.org | 443 (HTTPS default) |
| http://wikipedia.org:81 | 81 (explicit, NOT default) |
Concept
wikipedia.org and www.wikipedia.org look like 'the same site,' but as origin DOMAIN strings they are not equal — www. makes a different string, hence a different origin.
| domain string | compared to wikipedia.org |
|---|---|
| wikipedia.org | same |
| www.wikipedia.org | DIFFERENT (subdomain prefix) |
| en.wikipedia.org | DIFFERENT (subdomain prefix) |
| wikipedia.com | DIFFERENT (different TLD) |
The same-origin comparison is a literal string match on the host — there is no 'these belong to the same company so they're the same origin' rule.
Discrimination
Sort into buckets
Sort these by compared to wikipedia.org, from memory, without looking back at §19.1 A subdomain is a different domain. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Intuition
An origin is like a full street address: house number AND street AND city. Match the street but not the city and it's a different place. Match domain but not protocol or port, and it's a different origin.
The path is which ROOM you visit once you're at the address — it doesn't change the address. That's why /a/ and /b/ on the same site are the same origin.
Ask yourself: is www.wikipedia.org the same place as wikipedia.org? (No — a different subdomain is a different domain string, so a different origin.)
Worked example
For each pair, compare PROTOCOL, then DOMAIN, then PORT — all three must match
Why: These are the textbook's canonical examples. We only look at protocol/domain/port; we ignore the path entirely.
| URL A | URL B | same origin? | why |
|---|---|---|---|
| http://wikipedia.org/a/ | http://wikipedia.org/b/ | SAME | path is NOT part of the origin |
| http://wikipedia.org | http://www.wikipedia.org | DIFFERENT | domain differs (subdomain) |
| http://wikipedia.org | https://wikipedia.org | DIFFERENT | protocol differs (http vs https) |
| http://wikipedia.org:81 | http://wikipedia.org:82 | DIFFERENT | port differs (81 vs 82) |
Verify the tricky one: http://wikipedia.org vs http://wikipedia.org:80
Why: §19.1: HTTP's default port is 80, so the first URL's effective port IS 80 — all three parts match, SAME origin. But http://wikipedia.org vs http://wikipedia.org:81 differ in port → DIFFERENT.
Blank canvas
Draw it
Draw what §19.1 Same origin? Decide each pair just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Trap
A student: 'Both URLs are wikipedia.org, so they're obviously the same origin.'
http://wikipedia.org vs https://wikipedia.org <- protocol differs
http://wikipedia.org vs http://www.wikipedia.org <- domain differs
http://wikipedia.org:81 vs http://wikipedia.org:82 <- port differsJudge same-origin by the domain alone
Why: Wrong. The origin is (protocol, domain, port) — matching the domain is NOT enough. http vs https differ, a different subdomain (www.) is a different domain string, and different ports differ. Any one mismatch ⇒ different origin.
A student: what do I actually have to compare?
Compare all THREE: protocol AND domain AND port
Why: §19.1: two pages share an origin only if protocol, domain, and port all match exactly as strings. Same domain with a different scheme, subdomain, or port is a DIFFERENT origin.
Error analysis
Annotate
Walk the callouts on Trap: 'same domain = same origin'. Each one is a place this is easy to get subtly wrong.
Worked example
Compare https://app.bank.com/login and https://app.bank.com/transfer
Why: Two URLs on the same host — reduce each to its (protocol, domain, port) triple and ignore everything else.
| URL | protocol | domain | port |
|---|---|---|---|
| https://app.bank.com/login | https | app.bank.com | 443 (default) |
| https://app.bank.com/transfer | https | app.bank.com | 443 (default) |
Verify: all three parts match ⇒ SAME origin (the differing path is ignored)
Why: §19.1: protocol https = https, domain app.bank.com = app.bank.com, port 443 = 443. Identical triples, so same origin — /login and /transfer pages can access each other freely.
Comparison
Comparison matrix
From §19.1 Build the origin, then compare: refill the domain column from what you know. The rest of the table is as it appeared.
| URL | protocol | domain | port |
|---|---|---|---|
| https://app.bank.com/login | https | app.bank.com | 443 (default) |
| https://app.bank.com/transfer | https | app.bank.com | 443 (default) |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'http://wikipedia.org/a/ and http://wikipedia.org/b/ have different paths, so they're different origins.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: The path is NOT part of the origin.
A student: which URL parts count for the origin?
Why: The path is NOT part of the origin. Both URLs share the same protocol, domain, and port — so they are the SAME origin and their pages can freely access each other.
Trap
A student: 'http://wikipedia.org/a/ and http://wikipedia.org/b/ have different paths, so they're different origins.'
Treat /a/ and /b/ as different origins
Why: Wrong. The path is NOT part of the origin. Both URLs share the same protocol, domain, and port — so they are the SAME origin and their pages can freely access each other.
A student: which URL parts count for the origin?
Only protocol + domain + port — never the path, query, or fragment
Why: §19.1: the origin is read off just three parts. Everything after the host/port (the path and beyond) is ignored when comparing origins. /a/ and /b/ are same-origin.
Section
Part 2 · §19.2 read is blocked, embed is allowed
Concept
Concrete rule: the SOP stops one origin's JavaScript from reading another origin's data — its DOM, the responses to its fetch/XHR requests, and its cookies. evil.com's JS simply cannot read gmail.com's anything.
Concept
Crucially, the SOP does NOT stop you from LOADING cross-origin resources. A page may embed images, scripts, and frames from other origins via src. The whole web depends on this — CDNs, ad scripts, embedded videos.
<!-- all allowed on any origin -->
<img src="https://other.com/logo.jpg">
<script src="https://cdn.com/lib.js"></script>
<iframe src="https://other.com/widget"></iframe>The line is embed vs read: you may EMBED a cross-origin resource, you just can't READ its contents across the origin boundary.
Intuition
Embedding a cross-origin image is like hanging a borrowed painting on your wall: you can display it, frame it, size it. That's fine — display is allowed.
Reading across origins is like opening the lender's safe in their house. The SOP locks that. You can show their stuff; you can't reach in and read their private contents.
Ask yourself: does embedding a cross-origin image let your JS read that image's pixels? (No — you can display it, but reading its contents is across the origin boundary, so it's blocked.)
Concept
When we say the SOP blocks 'reading another origin's data,' that bundles three concrete capabilities an attacker would love — and the SOP denies all three across origins.
| cross-origin read | what it would expose | SOP |
|---|---|---|
| another origin's DOM | its page contents / form fields | BLOCKED |
| its fetch/XHR response body | data its requests return | BLOCKED |
| its cookies | its session / login credentials | BLOCKED |
Socratic
Discussion prompt
When we say the SOP blocks 'reading another origin's data,' that bundles three concrete capabilities an attacker would love — and the SOP denies all three across origins.
Suppose that were not true. What is the first thing in L37 · The Same-Origin Policy that would stop working?
Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.
Pattern
Predict first
The table runs: Embed google's logo via <img src> | yes | embedding cross-origin is allowed · Display/size that logo on the page | yes | embedding includes layout · JS reads the fetch() response body | NO | reading cross-origin data is blocked
In §19.2 Embed (allowed) vs read response (blocked), given the rows so far: what is the next one — the row where operation is JS reads the embedded image's pixels?
Correct: JS reads the embedded image's pixels | NO | that's reading across origins
| operation | allowed? | why |
|---|---|---|
| Embed google's logo via <img src> | yes | embedding cross-origin is allowed |
| Display/size that logo on the page | yes | embedding includes layout |
| JS reads the fetch() response body | NO | reading cross-origin data is blocked |
| JS reads the embedded image's pixels | NO | that's reading across origins |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. Two cross-origin operations against google.com — one is embedding, one is reading.
Worked example
Your page is on http://cs161.org. You want google.com's logo, and you want google.com's homepage HTML
Why: Two cross-origin operations against google.com — one is embedding, one is reading. The SOP treats them very differently.
<!-- on http://cs161.org -->
<img src="http://google.com/logo.jpg"> <!-- embed: OK -->
<script>
fetch('http://google.com/').then(r => r.text())
</script> <!-- read: BLOCKED -->| operation | allowed? | why |
|---|---|---|
| Embed google's logo via <img src> | yes | embedding cross-origin is allowed |
| Display/size that logo on the page | yes | embedding includes layout |
| JS reads the fetch() response body | NO | reading cross-origin data is blocked |
| JS reads the embedded image's pixels | NO | that's reading across origins |
Verify the dividing line: did the resource get LOADED, or did your JS READ its contents?
Why: §19.2: loading/embedding cross-origin is fine; only reading the contents across the origin boundary is blocked. The image renders, but its bytes and the fetch response are off-limits to cs161.org's JS.
Discrimination
Sort into buckets
Sort these by allowed?, from memory, without looking back at §19.2 Embed (allowed) vs read response (blocked). Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'The SOP isolates origins, so my page can't even load an image or script from another site.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: The SOP blocks READING cross-origin data, not EMBEDDING cross-origin resources.
A student: what exactly does the SOP forbid?
Why: The SOP blocks READING cross-origin data, not EMBEDDING cross-origin resources. Pages load cross-origin images, scripts, fonts, and frames constantly — that's how CDNs and ads work.
Trap
A student: 'The SOP isolates origins, so my page can't even load an image or script from another site.'
Assume the SOP forbids all cross-origin loads
Why: Wrong. The SOP blocks READING cross-origin data, not EMBEDDING cross-origin resources. Pages load cross-origin images, scripts, fonts, and frames constantly — that's how CDNs and ads work.
A student: what exactly does the SOP forbid?
It blocks READING cross-origin contents; EMBEDDING is allowed
Why: §19.2: you may embed cross-origin resources via src; you just can't read their contents (DOM, responses, cookies) across the boundary. Embed vs read is the whole distinction.
Concept
If the SOP blocked all cross-origin loads, there would be no CDNs, no embedded maps, no ad networks, no shared font/script libraries. The web only works because EMBEDDING cross-origin is allowed.
The SOP's design splits the difference: maximize useful sharing (anyone can embed anyone) while denying the one dangerous capability (reading another origin's private contents). Embed freely; read never.
Section
Part 3 · §19.2 scripts, images & frames
Concept
Here's the subtle, exam-critical part. A resource does NOT always get the origin of the URL it was fetched from. Which origin a resource gets depends on the KIND of resource — and the rules differ for scripts, images, and frames.
Getting this wrong is the single most common SOP mistake — and the script rule is exactly what makes XSS (L40) devastating. We'll take the three resource types one at a time.
Concept
Rule 1: JavaScript runs with the origin of the page that LOADS it — not the origin it was downloaded from. A <script src=…> from anywhere runs as if it were part of YOUR page.
<!-- page is on http://cs161.org -->
<script src="http://google.com/tracking.js"></script>
<!-- tracking.js runs with origin cs161.org,
NOT google.com -->So that included script has the SAME origin as your page — full access to your DOM, your data, everything. This is why pulling in third-party scripts is dangerous: you're giving their code your origin.
Concept
Rule 2: an image has the origin of where it comes from. An <img src="http://google.com/logo.jpg"> on cs161.org has origin google.com — not cs161.org.
<!-- page is on http://cs161.org -->
<img src="http://google.com/logo.jpg">
<!-- image origin = google.com; cs161.org
learns only its DIMENSIONS, not pixels -->Because the image is a different origin, the loading page learns only the image's dimensions (so it can lay out the page) — it cannot read the image's actual pixels.
Sorting
Sort into buckets
These are the pieces of L37 · The Same-Origin Policy, out of order. Put each one back under the part of the lesson it belongs to.
Concept
Rule 3: a frame has the origin of the URL the frame is retrieved from. An <iframe src="http://google.com"> on cs161.org has origin google.com — the frame's own URL, not the embedding page's.
<!-- page is on http://cs161.org -->
<iframe src="http://google.com"></iframe>
<!-- frame origin = google.com,
NOT the embedding page cs161.org -->So the embedding page (cs161.org) and the framed page (google.com) are DIFFERENT origins, and the SOP walls them off from reading each other — exactly the frame isolation from L36.
Intuition
Including a <script> is like HIRING a contractor into your house: they walk around with your keys (your origin) and can touch everything. That's why a third-party script is a big trust decision.
Embedding an <img> or <iframe> is like DISPLAYING a borrowed object behind glass: it keeps its own owner (its source origin), and you only see it — you can't reach inside it.
Ask yourself: which of the three resource types gives YOUR page's powers to someone else's code? (The script — it runs with your origin. Images and frames keep theirs.)
Socratic
Discussion prompt
Including a <script> is like HIRING a contractor into your house: they walk around with your keys (your origin) and can touch everything. That's why a third-party script is a big trust decision.
Suppose that were not true. What is the first thing in L37 · The Same-Origin Policy that would stop working?
Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.
Answer:
Embedding an <img> or <iframe> is like DISPLAYING a borrowed object behind glass: it keeps its own owner (its source origin), and you only see it — you can't reach inside it.
Worked example
Your page is on http://cs161.org and embeds a script, an image, and an iframe — all from google.com
Why: Same source URL host (google.com) in all three cases. The origin each resource GETS still differs by type.
<!-- all on http://cs161.org -->
<script src="http://google.com/track.js"></script>
<img src="http://google.com/logo.jpg">
<iframe src="http://google.com"></iframe>| resource | origin it gets | who can access what |
|---|---|---|
| <script src=google> | cs161.org (the INCLUDING page) | runs AS your page — full access to your DOM/data |
| <img src=google> | google.com (where it came from) | your page learns only its dimensions, not pixels |
| <iframe src=google> | google.com (the frame's URL) | framed page is cross-origin; SOP blocks mutual reads |
Verify the danger: the included <script> got YOUR origin, so it can read your whole page
Why: §19.2: scripts run with the including page's origin (cs161.org), images and frames keep google.com. That a script you include runs as YOU is precisely why injecting a <script> (XSS, L40) is so powerful.
Trade off
Comparison matrix
From §19.2 Three resources, three origins: every row here is a choice with a cost. Fill the origin it gets column, then say which row you would actually pick and what you give up for it.
| resource | origin it gets | who can access what |
|---|---|---|
| <script src=google> | cs161.org (the INCLUDING page) | runs AS your page — full access to your DOM/data |
| <img src=google> | google.com (where it came from) | your page learns only its dimensions, not pixels |
| <iframe src=google> | google.com (the frame's URL) | framed page is cross-origin; SOP blocks mutual reads |
Trap
A student: '<script src="http://google.com/track.js"> is from google.com, so it runs with origin google.com and is isolated from my cs161.org page.'
Give the included script the source URL's origin (google.com)
Why: Wrong. JavaScript runs with the origin of the PAGE THAT INCLUDES it, not where it was downloaded from. track.js runs with origin cs161.org and has FULL access to your page — the opposite of isolated.
A student: whose origin does an included script actually run with?
The INCLUDING page's origin — your origin
Why: §19.2: an included <script> runs as part of your page with YOUR origin and full access to your DOM and data. This is exactly the mechanism that makes XSS (L40) devastating: injected script runs in the victim page's origin.
Intuition
When cs161.org embeds a google.com image, the browser has to lay out the page, so it must tell cs161.org how big the image is. But size is all it tells — the image's actual pixels belong to google.com's origin.
Think of a wrapped package: you can see its dimensions to fit it on a shelf, but you can't see what's inside. Dimensions leak; contents don't.
Ask yourself: could cs161.org's JS read the colors of an embedded cross-origin photo? (No — that's reading the image's contents across origins, which the SOP blocks; only its dimensions are exposed.)
Explain it
Discussion prompt
Explain §19.2 The image leaks shape, not content to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Think of a wrapped package: you can see its dimensions to fit it on a shelf, but you can't see what's inside. Dimensions leak; contents don't.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'http://bank.com and https://bank.com are the same site, so same origin.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: The protocol is part of the origin.
A student: does switching http→https change the origin?
Why: The protocol is part of the origin. http vs https are DIFFERENT protocols, so http://bank.com and https://bank.com are DIFFERENT origins — even though the domain and (well, ports differ too: 80 vs 443) everything 'looks' like the same site.
Trap
A student: 'http://bank.com and https://bank.com are the same site, so same origin.'
Ignore the protocol when comparing origins
Why: Wrong. The protocol is part of the origin. http vs https are DIFFERENT protocols, so http://bank.com and https://bank.com are DIFFERENT origins — even though the domain and (well, ports differ too: 80 vs 443) everything 'looks' like the same site.
A student: does switching http→https change the origin?
Yes — different protocol ⇒ different origin
Why: §19.1: the origin is (protocol, domain, port). http and https differ in protocol (and in default port, 80 vs 443), so they are distinct origins and the SOP isolates them from each other.
Section
Part 4 · §19.2 postMessage (and ⊕ the rest)
Concept
Sometimes two different-origin pages genuinely need to talk — say an embedded widget and its host. JavaScript's postMessage lets pages of different origins communicate, but with very limited functionality.
postMessage — A JavaScript API that lets two pages of DIFFERENT origins exchange messages in a controlled, limited way. It is not a hole in the SOP: the channel is narrow, and the RECEIVER must validate the sender's origin before trusting a message.
Concept
postMessage does not let any origin freely read another's page. It only passes discrete MESSAGES, and the side receiving a message is responsible for verifying who sent it before acting on it.
window.addEventListener('message', (e) => {
if (e.origin !== 'https://trusted.com') return; // validate!
handle(e.data);
});If the receiver skips the e.origin check, any page can send it messages — a real bug. The SOP gives you the sender's origin precisely so you can check it.
Analogy
Discussion prompt
Explain §19.2 The receiver must check the origin by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
If the receiver skips the e.origin check, any page can send it messages — a real bug. The SOP gives you the sender's origin precisely so you can check it.
Worked example
A host page receives messages from an embedded widget at https://trusted.com
Why: Cross-origin by design — the host and widget are different origins, so postMessage is the channel. The question is whether the host trusts blindly.
window.addEventListener('message', (e) => {
// UNSAFE: no origin check — any page can send this
handle(e.data);
});| receiver code | who can drive handle() | verdict |
|---|---|---|
| no e.origin check | ANY origin that sends a message | unsafe |
| if (e.origin !== 'https://trusted.com') return; | only trusted.com | safe |
Verify: the fix is one line — validate e.origin before acting
Why: §19.2: postMessage hands the receiver the sender's origin precisely so it can check it. Skipping the check turns a controlled channel into an open door for any page.
Comparison
Comparison matrix
From §19.2 A safe vs unsafe postMessage receiver: refill the who can drive handle() column from what you know. The rest of the table is as it appeared.
| receiver code | who can drive handle() | verdict |
|---|---|---|
| no e.origin check | ANY origin that sends a message | unsafe |
| if (e.origin !== 'https://trusted.com') return; | only trusted.com | safe |
Concept
⊕ Supplemental — beyond §19.1–19.2. Several other mechanisms relax or attack the SOP; you'll meet them later or in practice, but they're outside this textbook section.
Access-Control-Allow-Origin response header; complex requests trigger a preflight, simple ones don't.document.domain — a legacy mechanism that let two pages relax to a shared parent domain (now deprecated).<script> cross-origin-embed rule to fetch data as executable JS, sidestepping the read restriction.Intuition
postMessage is like a mail slot between two locked apartments: you can slide a NOTE through, but you can't walk in and rummage through the other apartment. The wall (the SOP) still stands.
And the note is stamped with the sender's address (e.origin). A careful receiver reads the stamp and ignores notes from addresses it doesn't trust.
Ask yourself: does receiving a postMessage let you read the sender's DOM? (No — you only get the message data, plus the sender's origin to validate. The pages stay isolated.)
Counterexample
Discussion prompt
Ask yourself: does receiving a postMessage let you read the sender's DOM? (No — you only get the message data, plus the sender's origin to validate. The pages stay isolated.)
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'postMessage is a way around the SOP — once I use it, I can read the other page's whole DOM.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: postMessage only passes limited MESSAGES between origins — it does not expose the other page's DOM.
A student: what does postMessage actually give you?
Why: postMessage only passes limited MESSAGES between origins — it does not expose the other page's DOM. And the receiver must validate the sender's origin; it isn't an automatic trust channel.
Trap
A student: 'postMessage is a way around the SOP — once I use it, I can read the other page's whole DOM.'
Treat postMessage as full cross-origin read access
Why: Wrong. postMessage only passes limited MESSAGES between origins — it does not expose the other page's DOM. And the receiver must validate the sender's origin; it isn't an automatic trust channel.
A student: what does postMessage actually give you?
A narrow, opt-in message channel — with origin checks required
Why: §19.2: postMessage enables limited cross-origin communication, not arbitrary reads. Each side sends discrete messages, and the receiver is responsible for checking e.origin before trusting the data.
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
Pattern
src).<script> runs with the INCLUDING page's origin (yours!); an <img> keeps the origin it came from (you get dimensions, not pixels); an <iframe> keeps the origin of the URL it was retrieved from.postMessage for limited, opt-in messaging — and ALWAYS validate e.origin on the receiving side.Edge cases
Discussion prompt
The same-origin playbook works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".
Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.
Answer:
<script> runs with the INCLUDING page's origin (yours!); an <img> keeps the origin it came from (you get dimensions…postMessage for limited, opt-in messaging — and ALWAYS validate e.origin on the receiving side.Check
A page served from http://cs161.org includes <script src="http://google.com/tracking.js">. Separately, consider whether http://wikipedia.org and https://wikipedia.org are the same origin. Think before choosing.
Check your understanding
Which statement is TRUE?
Answer: A
Why: §19.2: JavaScript runs with the origin of the page that INCLUDES it, not the origin it was downloaded from. So <script src="http://google.com/tracking.js"> on cs161.org runs with origin cs161.org and has full access to that page's DOM and data — which is exactly why including third-party scripts is dangerous and why XSS (L40) is so powerful. The other claims fail the origin definition (protocol, domain, port; path excluded): http vs https differ in protocol, so they are different origins; and /a/ vs /b/ share protocol+domain+port, so they are the SAME origin.
Concept
src are allowed.Concept
<script> runs in the victim page's origin with full DOM power.Concept
Access-Control-Allow-Origin (beyond §19).Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — What Is an Origin? · What the SOP Restricts vs Allows · The Origin-Assignment Rules · Controlled Cross-Origin Communication. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
You can now say why the SOP exists (keep evil.com out of your Gmail), compute an origin as (protocol, domain, port) and decide same-origin by exact match of all three, separate what the SOP restricts (reading cross-origin data) from what it allows (embedding), apply the script/image/frame origin rules — especially that an included script runs with YOUR origin — and describe postMessage as the controlled cross-origin channel.
| Idea | § | The one-line version |
|---|---|---|
| Why the SOP | 19 | isolate every page; evil.com must not read Gmail |
| Origin | 19.1 | (protocol, domain, port) — all three must match exactly |
| Default ports | 19.1 | 80 for http, 443 for https; path is NOT in the origin |
| Restrict | 19.2 | blocks reading cross-origin DOM / responses / cookies |
| Allow | 19.2 | embedding cross-origin img/script/iframe via src is fine |
| Script origin | 19.2 | runs with the INCLUDING page's origin (→ XSS, L40) |
| Image/frame origin | 19.2 | keep the origin they came from (dimensions, not pixels) |
| postMessage | 19.2 | limited cross-origin messaging; receiver checks origin |
| Bridge | — | send-but-can't-read ⇒ CSRF (L39); CORS = opt-in exception |
Want this taught 1-on-1? Alexander tutors Computer Security — $55/session, free consultation.