An iframe sandboxed with both allow-scripts and allow-same-origin can escape its sandbox because the combination lets the embedded content run JavaScript and retain the page's real origin. With scripts running under a legitimate origin, the frame can reach its own sandbox attribute through the DOM and remove the restrictive tokens, leaving the frame unconstrained. The protection is designed to fail in this case, and browser documentation warns explicitly against it.

How the sandbox attribute actually works

The sandbox attribute applies a set of restrictions to whatever document loads inside the frame. Each restriction is opt-out: the frame is locked down by default, and each listed token re-enables one capability. Without any tokens, the framed page cannot run scripts, submit forms, open popups, lock the pointer, or store data as if it had a normal origin. Browsers also treat the framed document as belonging to an opaque, unique origin, which prevents it from reaching back into the parent page or reading the parent's cookies and storage.

Every token is a permission slip. allow-scripts restores JavaScript execution. allow-same-origin restores the embedded document's real origin and its access to origin-scoped state such as cookies, localStorage, and IndexedDB. The design intends each token to be granted only when the parent trusts the framed content enough to accept the specific risk.

The escape arises from the interaction between two permission slips. A script with a real same-origin identity is, from the browser's point of view, the same site as the parent when the frame loads a same-site URL. Same-origin scripts are allowed to walk the DOM across the frame boundary. That includes reading and writing the iframe element's own attributes in the parent document.

The concrete sequence is short. The framed script loads, runs because allow-scripts is present, and resolves its origin to the parent's origin because allow-same-origin is present. It then accesses its containing frame through window.frameElement, reads the sandbox attribute, strips the remaining restrictive tokens, and reloads itself. On the reload the sandbox restriction is gone or reduced, and the document now behaves as an ordinary same-origin frame with full script, form, and storage privileges.

The mechanism does not require a browser bug. It is specified, observable behavior, and it matches the guidance on the MDN sandbox page and in the HTML standard's discussion of sandboxing flags. The combination effectively grants the framed code the authority to redefine its own confinement.

What the combination quantitatively unlocks

Removing the sandbox restriction is not the only outcome. The two tokens together hand the frame a broad set of capabilities that each token alone would not. An allow-scripts-only frame cannot read the parent's cookies because its origin is opaque. An allow-same-origin-only frame cannot execute the code that would use them. Combined, the frame can read and write origin-scoped storage, read and set cookies not marked HttpOnly, and issue same-origin credentialed requests.

The scope of that authority tracks the parent's origin. If the parent sits on a domain with cookies scoped to a broad registrable domain, the framed script can reach any of those cookies the browser exposes to scripts. Session cookies marked HttpOnly remain invisible to JavaScript, which caps the damage, but server-side session identifiers that are script-readable are fair game.

Timing is fast and requires no user interaction. The escape is a few DOM operations and can complete during page load. The framed document can do it before the user sees content, so there is no visible sign that confinement was removed. Revoking the sandbox on the parent's element, if the parent tries, races against the frame's own script and does not reliably win.

The permission model is binary per token. There is no partial allow-scripts and no scoped allow-same-origin. A single misconfiguration flips the frame from opaque-origin and script-blocked to fully origin-privileged and script-running. That is why the combination should be treated as equivalent to not sandboxing at all for trust purposes: the frame can undo whatever the parent intended to keep.

Edge cases and the counterintuitive detail

The escape depends on the parent and the frame sharing an origin. If the iframe loads a URL on a different site, allow-same-origin restores that site's origin, not the parent's, and the frame cannot reach the parent's DOM. The combination is still dangerous because it grants the embedded site full script and storage authority over its own origin, but it cannot rewrite the parent's sandbox attribute. Cross-origin framing with both tokens is misconfigured in a different way.

The counterintuitive detail is that removing allow-same-origin does not always remove the origin privilege. When the parent page and the framed document are same-site, some browser behaviors around sandboxed same-origin documents still expose origin-scoped state. The safest reading is not to rely on partial token removal to contain a frame that already ran code; treat any granted allow-scripts as a code-execution trust boundary.

A second edge case involves nested frames. A frame that has escaped can itself create child frames and choose their sandbox attributes, spreading the privilege downward. The parent's original intent is no longer enforceable once a same-origin scripted child exists.

A third is the srcdoc and about:blank case. A frame whose content is supplied inline or generated inherits the parent's origin. With both tokens, that inherited origin is real, so inline framed scripts gain full same-origin reach immediately.

Why the misconception persists

Many developers assume sandbox with a long token list is safer than no sandbox. That assumption is wrong for this specific pair. The tokens do not sum to partial protection; they multiply into full escape. A frame with allow-scripts and allow-same-origin is functionally equivalent in trust terms to an unsandboxed frame on the same origin.

Another misconception is that the browser blocks the combination. Browsers do not block it, and no console warning is guaranteed to stop a determined frame. The configuration is accepted and behaves as specified, which is why warnings appear in documentation rather than in enforcement.

A third is that allow-same-origin is needed for cookies or storage inside a frame. A frame can use storage on its own origin without inheriting the parent's, so the permission is often unnecessary. Granting it is a convenience that buys risk.

A comparison of sandbox token strategies

Token configuration Scripts run Origin privileges Can rewrite its sandbox Typical use
No tokens No Opaque origin No Untrusted, static HTML
allow-scripts only Yes Opaque origin No Untrusted interactive widgets
allow-same-origin only No Real origin No Static same-site content
allow-scripts + allow-same-origin Yes Real origin Yes Should be avoided for untrusted content
allow-scripts + allow-forms Yes Opaque origin No Form-based untrusted widgets
allow-scripts + allow-popups Yes Opaque origin No Untrusted content that opens links

The table shows the two-token row is the only one where the frame can edit its own restriction. That single capability is the escape.

Practical actions and thresholds

Concrete steps:

Audit every iframe element and its sandbox attribute. Flag any element containing both allow-scripts and allow-same-origin for review. Remove allow-same-origin from untrusted frames and confirm the embedded content still works with an opaque origin. Host untrusted content on a separate registrable domain when it truly needs scripts, so its origin cannot reach the parent. Read the sandbox attribute in the parent after load and verify it still contains the intended tokens. Serve untrusted frames with a Content-Security-Policy that limits script and frame sources. Treat any frame granted allow-scripts as capable of executing arbitrary code and isolate it accordingly.

Red-flag warnings to treat as blockers:

A same-site framed URL with both tokens is an open escape path. A frame that renders user-supplied HTML with both tokens is a code-execution surface. A parent that assumes its sandbox survives frame-script execution is mistaken. A build tool or template that adds both tokens by default is unsafe.

The thresholds matter less than the presence of the pair. There is no safe quantity; any occurrence of both tokens on an untrusted frame should be removed and replaced with a cross-origin pattern or token reduction.

Limitations of what sandboxing can promise

Sandboxing is a restriction on capabilities, not a malware sandbox or a security boundary against a determined same-origin script. It cannot contain code that has been granted script execution and a real origin, because that code can reconfigure its container. The correct mental model is that sandbox tokens are trust decisions, and the two-token pair is a decision to trust the frame as if it were the parent.

A cross-origin deployment is the reliable alternative, but it requires separate hosting and origin isolation, which costs infrastructure and setup effort. For low-trust content, the practical default is to remove script execution or remove origin inheritance, never both-granted. The remaining risk is not eliminable by attribute editing alone; it requires isolation at the origin and network layers.