WEB / WEB-11.01
Origin and Same-Origin Policy
Atlas and a book-preview document can share a screen without being able to read each other’s DOM.
1. Core · Mechanism
Read every scenario without motion
Same origin
- Two documents ready
Both documents are already loaded; this scene is a browser-local DOM read gate, not network sending.
- Atlas document
- Read gate pending; atlas
- Preview document
- Loaded read-only preview; atlas-other-path
- Select identity
Atlas prepares the selected document-origin identities for comparison; a path or serialized null alone is not identity.
- Atlas document
- Identity comparison ready; atlas / atlas-other-path
- Preview document
- Loaded read-only preview; atlas-other-path
- Origin gate
Normal tuple or opaque identity equality was evaluated by the selected browser-local predicate; preview state is unchanged.
- Atlas document
- Same-origin gate allow
- Preview document
- Loaded read-only preview; atlas-other-path
- Read outcome
The selected read-only sample is available under the origin gate; this is not server authorization or an actual DOM test.
- Atlas document
- Declared sample: Atlas Notları
- Preview document
- Loaded read-only preview; atlas-other-path
Different host
- Two documents ready
Both documents are already loaded; this scene is a browser-local DOM read gate, not network sending.
- Atlas document
- Read gate pending; atlas
- Preview document
- Loaded read-only preview; preview
- Select identity
Atlas prepares the selected document-origin identities for comparison; a path or serialized null alone is not identity.
- Atlas document
- Identity comparison ready; atlas / preview
- Preview document
- Loaded read-only preview; preview
- Origin gate
Normal tuple or opaque identity equality was evaluated by the selected browser-local predicate; preview state is unchanged.
- Atlas document
- Same-origin gate deny
- Preview document
- Loaded read-only preview; preview
- Read outcome
The selected read-only sample is not exposed by the origin gate; this is not server authorization or an actual DOM test.
- Atlas document
- No DOM sample exposed; no network
- Preview document
- Loaded read-only preview; preview
Two opaque
- Two documents ready
Both documents are already loaded; this scene is a browser-local DOM read gate, not network sending.
- Atlas document
- Read gate pending; opaque-A
- Preview document
- Loaded read-only preview; opaque-B
- Select identity
Atlas prepares the selected document-origin identities for comparison; a path or serialized null alone is not identity.
- Atlas document
- Identity comparison ready; opaque-A / opaque-B
- Preview document
- Loaded read-only preview; opaque-B
- Origin gate
Normal tuple or opaque identity equality was evaluated by the selected browser-local predicate; preview state is unchanged.
- Atlas document
- Same-origin gate deny
- Preview document
- Loaded read-only preview; opaque-B
- Read outcome
The selected read-only sample is not exposed by the origin gate; this is not server authorization or an actual DOM test.
- Atlas document
- No DOM sample exposed; no network
- Preview document
- Loaded read-only preview; opaque-B
ACTORS · STATE · DATA FLOW
Which authority does the browser separate?
The browser does more than send HTTP to remote servers. It runs scripts, documents, storage and credential contexts for several applications in one user session, so it must limit one application directly reading another’s data. Origin is the basic identity for this client-side authority boundary. The browser decides DOM read access between Atlas and a preview document; the Notes API retains its server-side user/tenant decision. Two pages do not share authority merely because the same person opened both.
For ordinary HTTP(S), compare scheme, normalized host and port; path, query and fragment do not change that comparison. https://atlas.example.org:443/ and https://atlas.example.org/ have the same normalized origin. :8443 or preview.example.org is another origin. Sharing a registrable domain can establish a same-site relationship, not same-origin identity. HTML’s tuple also has a legacy domain field; this lesson uses no document.domain relaxation and teaches the ordinary same-origin gate. Sharing an IP address or backend operator likewise does not establish browser origin equality.
Not every origin is a URL string
An opaque origin carries an internal identity that cannot be reconstructed from a string. Distinct opaque-A and opaque-B both serialize as null, but are not the same origin; opaque-A equals itself. Thus null in a log or event.origin is not the name of one shared trusted origin. A sandboxed origin flag can make a document opaque even when its URL resembles Atlas. URL.origin alone does not determine every document-origin condition; creation and sandbox context matter too.
Contexts such as about:blank inheriting a creator origin show why the URL text is insufficient. data: documents can be opaque; file: origin behavior is implementation-dependent, so “the same directory means the same origin in every browser” is not valid. The artifact separates ordinary HTTP tuple examples from explicitly declared opaque identities. The scene shows a read-only DOM-sample gate between two already loaded documents, without running a real window, sandbox, network or browser exception.
Read, send and embed are separate decisions
SOP constrains cross-origin DOM and storage reads; it is not a firewall blocking all cross-origin networking. Links/navigation, some ordinary requests and embedding can proceed under their own rules. An image appearing beside an iframe does not open that document’s DOM; image/canvas readability has separate conditions too. A CORS-mode fetch can reach the server without exposing its response to script. A no-cors opaque response does not enable ordinary script body reading either. “Sent” and “readable” therefore require separate evidence.
Embedding also has conditions: response framing policy, MIME, CSP, sandbox or COEP/CORP can block it in the selected context. The categories explain general behavior, not unconditional success of every embed. A successful browser read gate does not authorize a server action; session and object policy still matter within one origin. The lesson table contains only ordinary read-only preview and catalog requests, with no server-side mutation or third-target request.
2. Red · Trust & Impact
Read every scenario without motion
Tuple boundary
- Path and default port were separated from origin
The atlas books URL and preview URL with uppercase host and explicit port 443 normalize to one origin. Path, query and fragment are excluded from the tuple. Raw URL equality is not origin comparison.
- Origin/operation facts
- Atlas default443 / paths differ / same origin
- Identity comparison
- Operation gate pending
- Data/permission boundary
- No verdict
- Nondefault ports and cross-hosts retained separate identities
Port 8443 yields origin https://atlas.example.org:8443 and preview.example.org has another host. Similar suffixes or ownership by one organization do not replace tuple equality. Default normalization does not equate every port.
- Origin/operation facts
- Atlas default443 / paths differ / same origin
- Identity comparison
- Nondefault8443 / preview host cross-origin
- Data/permission boundary
- No verdict
- Same-origin DOM reading was not a user grant
The same-origin readonly DOM sample has scriptReadable true and serverActionAuthorized not evaluated. A browser-local read gate does not calculate object permission or safe-output policy. The sample remains public declared text.
- Origin/operation facts
- Atlas default443 / paths differ / same origin
- Identity comparison
- Nondefault8443 / preview host cross-origin
- Data/permission boundary
- Origin read allowed / server policy not evaluated
- Cross-origin sending and reading became separate facts
The selected cross-origin readonly GET has sent true but scriptReadable false. Server receipt does not show a broken SOP. Sending a network request and exposing its response body to script are different operations.
- Origin/operation facts
- Cross-origin GET sent / script read false
- Identity comparison
- Nondefault8443 / preview host cross-origin
- Data/permission boundary
- Origin read allowed / server policy not evaluated
- Embedding did not replace direct DOM reading
A framing-allowed public preview has sent and embedded true while scriptReadable stays false. Visible framing does not permit direct reading of another origin’s DOM. Embedding policy and DOM isolation are separate gates.
- Origin/operation facts
- Cross-origin GET sent / script read false
- Identity comparison
- Embed true / direct script read false
- Data/permission boundary
- Origin read allowed / server policy not evaluated
- Control stayed within the operation-specific boundary
Trusted identity comparison uses the structured tuple; site or DNS addresses grant no extra DOM permission. Server-action policy is independent of SOP. This declarative matrix measures no actual network or browser enforcement.
- Origin/operation facts
- Cross-origin GET sent / script read false
- Identity comparison
- Embed true / direct script read false
- Data/permission boundary
- Separate send/embed/read/server-policy decisions
Opaque identity
- The same null display retained two identities
opaque-A and opaque-B serialize as null but have distinct identityAlias values. Equal display strings do not mean equal opaque internal identities. These teaching aliases are not actual browser origin handles.
- Origin/operation facts
- Both serialize null / distinct aliases A,B
- Identity comparison
- Operation gate pending
- Data/permission boundary
- No verdict
- Comparison was bounded by identity aliases
Opaque-A versus opaque-B expects false while opaque-A versus itself expects true. Treating null as one common origin incorrectly merges separated contexts. Opaque identity is not derived from a hostname like a tuple origin.
- Origin/operation facts
- Both serialize null / distinct aliases A,B
- Identity comparison
- A≠B / A=self / no null-based merge
- Data/permission boundary
- No verdict
- Unknown document context was not guessed from a URL
A sandboxed-origin flag can select opaque identity despite an HTTP URL. URL text alone is insufficient to determine actual Document origin. No DOM-read grant is inferred without creation and sandbox context.
- Origin/operation facts
- Both serialize null / distinct aliases A,B
- Identity comparison
- A≠B / A=self / no null-based merge
- Data/permission boundary
- HTTP URL alone insufficient for Document origin
- Creator-inherited context retained its own qualification
about:blank inherits the creator’s origin in the selected creation context. file URL behavior is implementation-dependent and not simulated. Ordinary HTTP URL parsing is not generalized to these contexts with one rule.
- Origin/operation facts
- Creation context matters / file not simulated
- Identity comparison
- A≠B / A=self / no null-based merge
- Data/permission boundary
- HTTP URL alone insufficient for Document origin
- The read gate was checked with its identity source
Identity kind remains explicitly tuple or opaque; missing creation facts receive no guessed tuple. Legacy document.domain relaxation is false in this profile. Narrow messaging is a separate control covered elsewhere.
- Origin/operation facts
- Creation context matters / file not simulated
- Identity comparison
- Identity kind/source retained / no guessed relaxation
- Data/permission boundary
- HTTP URL alone insufficient for Document origin
- Opaque review was not general browser proof
Normal aliases explain the incorrect equality assumption without running storage, canvas, sandbox runtime or actual DOM reads. Correct model identities do not verify browser compatibility or user authorization.
- Origin/operation facts
- Creation context matters / file not simulated
- Identity comparison
- Identity kind/source retained / no guessed relaxation
- Data/permission boundary
- Opaque model correct / browser enforcement unmeasured
ASSUMPTION · BOUNDARY · CONTROL
Which data could an incorrect equality expose?
Atlas and preview.example.org can share an operator but have different hosts to the browser. An application helper that opens a DOM sample because domain suffixes look similar creates a trust rule wider than the browser’s origin model. The relevant condition is data crossing from another origin without read permission; a shared screen or DNS IP does not justify it. Impact depends on the document or storage data involved. This lesson does not produce that behavior; it examines the mistaken equality in the policy table.
If serialized null equality replaces identity equality for opaque-A and opaque-B, separated contexts appear merged. The opaque branch preserves the opposite: identical display strings still lead to denial. Ignoring the port similarly merges :443 with :8443. The origin model is not a string-prefix check; it needs a normalized tuple or internal opaque identity. Placeholder identity aliases are not real browser origin handles, merely a way to expose the distinction.
What does request receipt prove?
An ordinary cross-origin GET reaching a server does not prove SOP is broken. The server can respond while script cannot access the body; an embed can be visible while direct DOM read is denied. Keep sent, embedded, script-readable and server-authorized fields separate to name control effects accurately. A design that treats read isolation as request authorization omits a server-side gate the browser does not supply. SOP alone is not positive evidence of CSRF protection or access control.
3. Blue · Secure development & defense
Read every scenario without motion
Operation matrix
- Normalized origins were paired with their source URLs
Scheme/host/port are kept separately for four HTTP URLs. This ledger represents a normalized default port as null; the native URL.port getter returns an empty string for a default port. Neither representation means HTTPS uses no port. Atlas other-path is same-origin and the preview host cross-origin.
- Origin matrix
- HTTP tuples normalized / ports retained
- Operation/coverage review
- Operation gate pending
- Evidence verdict
- No verdict
- Positive and negative read controls checked the same rule
Atlas other-path expects true while Atlas→preview expects false. Opaque-A/B false and self true are separate controls. Headers or DNS observations do not replace the declared identity comparisons.
- Origin matrix
- HTTP tuples normalized / ports retained
- Operation/coverage review
- Same tuple true / cross host and opaque pair false
- Evidence verdict
- No verdict
- Send/embed/read fields were retained side by side
The same-origin sample has sent false because it is already loaded. Cross-origin GET has sent true/read false; preview has embed true/read false. These describe different operations; sent false alone is not network refusal.
- Origin matrix
- Loaded sample / sent GET / embedded preview distinct
- Operation/coverage review
- Same tuple true / cross host and opaque pair false
- Evidence verdict
- No verdict
- Server-action policy remained with another owner
Public-read branches have selected public read only; the same-origin sample has server action not evaluated. Browser read isolation is neither server-request authorization nor proof of CSRF protection.
- Origin matrix
- Loaded sample / sent GET / embedded preview distinct
- Operation/coverage review
- Browser gate ≠ server action authorization
- Evidence verdict
- No verdict
- The policy matrix was not an actual network capture
profile actualBrowser and actualNetwork are false. Native URL parsing can calculate tuple examples without enforcing browser SOP, credential sending or embedding policy. Field source and model scope remain together.
- Origin matrix
- Loaded sample / sent GET / embedded preview distinct
- Operation/coverage review
- Browser gate ≠ server action authorization
- Evidence verdict
- Declared operation outcomes / network unmeasured
- Regression required comparison of the same operation
Regression rechecks current-document identity, operation kind and expected boundary within one scope. Cookie domain/path/site rules are not forced into a DOM-origin tuple. Minimal origin/operation evidence needs no private content.
- Origin matrix
- Loaded sample / sent GET / embedded preview distinct
- Operation/coverage review
- Browser gate ≠ server action authorization
- Evidence verdict
- Recheck identity kind + operation + boundary
Context gap
- URL source was separated from document-creation source
The origin matrix is a local URL/identity ledger. HTTP tuples, document-creation context and read operations are separate inputs; opaque aliases are not browser handles. In a real review, server receipt answers sending and a browser-local gate answers script reading. Here both are declared outcomes and the loaded preview creates no new request. The alternative review sees an HTTP URL string without creator or sandbox state. The ordinary URL-derived-tuple profile cannot automatically determine actual Document context. Opaque possibilities require coverage.
- Origin matrix
- URL known / creation-sandbox context missing
- Operation/coverage review
- Operation gate pending
- Evidence verdict
- No verdict
- Parser results were not Document-origin proof
The URL origin getter normalizes an HTTP URL without observing sandbox flags or inherited about:blank identity. Equating parser output with the actual document-read gate claims a check that was not performed.
- Origin matrix
- URL known / creation-sandbox context missing
- Operation/coverage review
- URL getter ≠ full Document-origin observation
- Evidence verdict
- No verdict
- A missing read observation was not labeled denial
No read-outcome observation exists either. The normal matrix’s scriptReadable values are not transferred into this incomplete context. An absent event and an observed browser exception are different evidence.
- Origin matrix
- Read outcome unobserved / no guessed deny
- Operation/coverage review
- URL getter ≠ full Document-origin observation
- Evidence verdict
- No verdict
- Required facts were separated into identity and operation
Review needs current-document origin kind, creation/sandbox context and operation. Server receipt may prove sending only; DOM reading needs another observation. One log row cannot close every gate.
- Origin matrix
- Read outcome unobserved / no guessed deny
- Operation/coverage review
- Need document identity source and read outcome
- Evidence verdict
- No verdict
- Actual-origin/read verdicts remained unknown
Document origin and script-read results remain UNKNOWN. Calculating an ordinary HTTP tuple does not fill unknown sandbox context. Missing evidence establishes neither browser compromise nor successful isolation.
- Origin matrix
- Read outcome unobserved / no guessed deny
- Operation/coverage review
- Need document identity source and read outcome
- Evidence verdict
- UNKNOWN: actual Document origin/read outcome
- New evidence scope was tied to the browser question
Further review needs controlled document-creation facts and scoped read observations, not full page data or credentials. Server-permission questions need separate server-side evidence rather than being merged into SOP review.
- Origin matrix
- Read outcome unobserved / no guessed deny
- Operation/coverage review
- Need document identity source and read outcome
- Evidence verdict
- Collect scoped creation/read facts; authz separately
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Record the boundary by document and operation
The origin matrix is a local URL/identity ledger. HTTP tuples, document-creation context and read operations are separate inputs; opaque aliases are not browser handles. In a real review, server receipt answers sending and a browser-local gate answers script reading. Here both are declared outcomes and the loaded preview creates no new request. Atlas records ordinary HTTP URLs with normalized scheme/host/port and keeps separate identity aliases for opaque contexts. Same-site information can inform cookie policy but does not enter the DOM read gate. Checks cover path changes preserving origin, default-port normalization and explicit nondefault ports changing it. Designing a narrow messaging contract instead of using the legacy document.domain setter keeps application trust boundaries visible for required cross-document work.
The review matrix includes more than allowed results. A same-origin read-only DOM sample is the positive control; cross-host and distinct opaque identities are negative controls. In every scene the preview’s own state remains unchanged, while Atlas’s browser-local read decision changes with no HTTP transfer. Same-origin permission does not resolve safe rendering or user authorization for the sample; it is only the selected origin gate’s outcome. A real browser harness would separately measure window/iframe origins, document creation and exceptions.
Network and exposure evidence
For network behavior, obtain request receipt and script exposure evidence from different owners: the server sees the normal request while the browser enforces the response gate. Do not force cookie scope and storage-origin relationships into one table; cookie domain/path/site rules differ from the DOM origin tuple. These distinctions are checked locally as source/path and predicate fixtures. Browser process isolation, real storage, canvas, credential sending and embedding-policy enforcement remain separate API/profile tests.
NOW APPLY IT TO THE CASE
How are origin identity, sending, embedding, script reading and server policy separated?
Atlas paths and its explicit default port normalize to one origin; preview host and port 8443 differ. Opaque-A and opaque-B both display null but retain distinct identities. Cross-origin sending or embedding does not imply script-readable body or DOM.
Which relationship does the case’s browser policy control? Explain exposure, destination or framing decisions separately from server object permission.
Open the related case file ↗READ THE EXAMPLE TOGETHER
Atlas origin and operation matrix
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"profile": {
"httpOnlyTupleExamples": true,
"legacyDocumentDomainRelaxation": false,
"actualBrowser": false,
"actualNetwork": false,
"domSample": "Atlas Notları · readonly declared text"
},
"httpOrigins": [
{
"url": "https://atlas.example.org/books?view=one#title",
"origin": "https://atlas.example.org",
"scheme": "https",
"host": "atlas.example.org",
"port": null
},
{
"url": "https://ATLAS.example.org:443/preview",
"origin": "https://atlas.example.org",
"scheme": "https",
"host": "atlas.example.org",
"port": null
},
{
"url": "https://atlas.example.org:8443/preview",
"origin": "https://atlas.example.org:8443",
"scheme": "https",
"host": "atlas.example.org",
"port": 8443
},
{
"url": "https://preview.example.org/books",
"origin": "https://preview.example.org",
"scheme": "https",
"host": "preview.example.org",
"port": null
}
],
"identities": {
"atlas": {
"kind": "tuple",
"scheme": "https",
"host": "atlas.example.org",
"port": null
},
"atlas-other-path": {
"kind": "tuple",
"scheme": "https",
"host": "atlas.example.org",
"port": null
},
"preview": {
"kind": "tuple",
"scheme": "https",
"host": "preview.example.org",
"port": null
},
"opaque-A": {
"kind": "opaque",
"identityAlias": "opaque-A",
"serialized": "null"
},
"opaque-B": {
"kind": "opaque",
"identityAlias": "opaque-B",
"serialized": "null"
}
},
"comparisons": [
{
"case": "normal",
"from": "atlas",
"to": "atlas-other-path",
"expected": true
},
{
"case": "cross-origin",
"from": "atlas",
"to": "preview",
"expected": false
},
{
"case": "opaque",
"from": "opaque-A",
"to": "opaque-B",
"expected": false
},
{
"case": "opaque-self",
"from": "opaque-A",
"to": "opaque-A",
"expected": true
}
],
"operations": [
{
"kind": "same-origin DOM sample",
"sent": false,
"embedded": "already loaded",
"scriptReadable": true,
"serverActionAuthorized": "not evaluated"
},
{
"kind": "selected cross-origin readonly GET, no CORS sharing",
"sent": true,
"embedded": false,
"scriptReadable": false,
"serverActionAuthorized": "selected public read only"
},
{
"kind": "selected cross-origin preview embed, framing allowed",
"sent": true,
"embedded": true,
"scriptReadable": false,
"serverActionAuthorized": "selected public read only"
}
],
"documentContexts": [
{
"context": "normal HTTP document",
"identity": "URL-derived tuple in selected profile"
},
{
"context": "creator-inherited about:blank",
"identity": "creator origin under selected creation context"
},
{
"context": "sandboxed origin flag",
"identity": "opaque identity despite HTTP URL"
},
{
"context": "file URL",
"identity": "implementation-dependent; not simulated"
}
]
}- httpOrigins
- HTTP URL parsing examples, not every Document-origin rule.
- identities
- A normalized tuple or opaque internal identity alias.
- comparisons
- Identity outcomes independent of serialized null equality.
- operations
- Send, embed, read and server policy are separate categories.
- documentContexts
- Creation and sandbox context goes beyond the URL string.
A read-only declarative DOM/origin model; ordinary HTTP URL parser checks do not prove browser SOP. No browser, storage, canvas, sandbox or network runs.
Two reality checks
Two opaque origins are equal if both display null.
Serialization is not identity; different opaque origins can produce the same string.
SOP never sends a cross-origin request to a server.
Read isolation differs from send/embed; an ordinary request can travel without exposing its response to script.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
A cross-origin preview iframe is loaded. Can the parent script automatically read the frame DOM?
- No; selected embed is true and scriptReadable false.
- Yes; if an iframe can load, all DOM access is permitted.
Read the explained answer
No; selected embed is true and scriptReadable false. — The SOP read boundary does not equate loading or embedding with reading.
A read-only cross-origin GET has sent=true but scriptReadable=false. Is this a network-firewall outcome?
Selected lesson artifact fields; teaching example
- operations[1]
- {"kind":"selected cross-origin readonly GET, no CORS sharing","sent":true,"embedded":false,"scriptReadable":false,"serverActionAuthorized":"selected public read only"}
- Yes; if the script cannot read, the request cannot reach the server.
- No; the request was sent while the script-read gate is closed.
Read the explained answer
No; the request was sent while the script-read gate is closed. — SOP/CORS response visibility is evaluated separately from the selected server public-read policy.
Why may a sandboxed document have an opaque origin despite an HTTP URL? Which context matters for about:blank?
Read the explained answer
The selected sandboxed-origin flag establishes an opaque identity instead of a tuple identity; matching URL hosts do not remove it. about:blank may inherit the creator origin in the selected creation context; there is no globally assigned origin for every about:blank. File-origin behavior is separately implementation-dependent.
□ I distinguished URL tuples from document-origin context.
□ I explained opaque/inherited cases conditionally.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- WHATWG HTML — Origins and sandboxing§7.1.1 Origins: tuple/opaque, serialization, same-origin equality · §7.1.1.1 Sites; §7.1.1.2 Relaxing the same-origin restriction · §7.1.5 Sandboxing: sandboxed origin and scripts flags
- MDN — Same-origin policyDefinition of an origin; Inherited origins; File origins · Cross-origin network access: writes, embeds, reads · Cross-origin script API access: Window and Location · Cross-origin data storage access
- WHATWG Fetch — CORS protocol and algorithms§2.2.1 CORS-safelisted method; §2.2.2 CORS-safelisted request-header · §3.3.2 HTTP requests; §3.3.3 HTTP responses · §3.3.5 CORS protocol and credentials · §4.8 CORS-preflight fetch; §4.9 CORS-preflight cache; §4.10 CORS check