Skip to content

fix(window): enforce parent-origin and native receiver access checks - #1651

Merged
ldm0 merged 4 commits into
mainfrom
cross-origin-follow-up
Oct 17, 2026
Merged

ldm0 merged 4 commits into
mainfrom
cross-origin-follow-up

Conversation

@ldm0

@ldm0 ldm0 commented Oct 17, 2026

Copy link
Copy Markdown
Member

Nested cross-origin frames currently authorize contentDocument against the top Window, so A → B → A can expose A’s Document to B while A → B → B incorrectly returns null. frameElement and borrowed native Window callbacks also expose foreign objects, and inert DOMParser iframes can create an unprotected synthetic Window that synchronously loads its src.

This follow-up to #1594 fixes those paths in four commits:

  • Authorize contentDocument and cached frameElement against the iframe’s actual node Document, including navigation and document.domain changes.
  • Check borrowed native methods, getters, and setters before conversion or Realm entry; reject forged receivers. Use the actual accessing context for child WindowProxy materialization and give facades unique security tokens. Preserve retired Realm SameObject and network shutdown behavior without allowing old callbacks to follow a reused proxy into a foreign Realm.
  • Make held computed style declarations follow their Element after adoption, with live iframe fixtures preserving the existing style coverage.
  • Remove the inert iframe synthetic Window, synchronous document loading, and eval/messaging emulation. Windowless or disconnected iframe elements return null; active frames use the protected native WindowProxy.

Validation from the repository root with CARGO_BUILD_JOBS=24:

  • cargo fmt --all
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo nextest run --no-fail-fast: 20,249 passed, 18 skipped
  • cargo build -p moli
  • Fresh CLI/CDP probe against Chromium 145: matching three-origin frame document visibility and identity, blank/srcdoc/opaque children, frameElement, borrowed native calls, forged receivers, inert iframe null behavior, and held computed styles after adoption.

Borrowed getter reflection for Window aliases, onmessage, and location still has compatibility differences from Chromium. The same differences occur in the baseline probe; they are outside this change.

Remaining work from the broader audit includes consolidating cross-origin property policy, reviewing the standalone lightweight popup fallback, and expanding the WPT matrix. This PR does not claim that every special Window construction path has been unified.

ldm0 added 4 commits October 18, 2026 00:10
Compare contentDocument and frameElement with the frame owner Document, including navigation and document.domain changes. Publish child Documents through the native private slot instead of redefining Window.document.
Add declarative V8 receiver access checks and Window brand validation. Authorize SameObject getters before cache reads, preserve captured objects for retired Realms, and materialize child proxies for the actual accessing context with isolated facade tokens.
Resolve the current owner Document and viewport when reading held child computed styles. Exercise adoption, pseudo-elements, argument conversion, and declaration identity with real iframe Realms.
Keep windowless and disconnected iframe elements without a contentWindow or contentDocument. Delete synchronous document loading and synthetic Window eval, style, and messaging code; migrate MIME and lifecycle coverage to protected live frames or standard null behavior.
@ldm0 ldm0 added the 1.1.19 label Oct 17, 2026
@github-actions

Copy link
Copy Markdown

Sequential Navigation Soak A/B

⚠️ Benchmark infrastructure failed before a comparison could be produced.

Workflow: timed_out. Inspect the workflow run for the failing build, harness, or artifact step.

No navigation resilience or memory conclusion is available for this run.

@github-actions

Copy link
Copy Markdown

Spider Bench A/B

⚠️ Spider Bench infrastructure failed before a comparison could be produced.

Workflow: timed_out. Inspect the workflow run for the failing build, harness, or artifact step.

No benchmark result or performance conclusion is available for this run.

@github-actions

Copy link
Copy Markdown

CI Regression Report

Source CI run · source state at render: timed_out · artifacts: 5/6

Check Status Signal
Release regression ✅ HEAD/base failures 0/0; raw binary +0.001356%
Frontend differential ✅ 1,020/1,020 cases matched; 0 issues
Agent episodes ⚪ artifact unavailable or invalid
Runtime/CDP contracts ✅ 26 contract cases; 0 failures
CDP smoke ✅ 52/52 groups passed; 621 scenarios
WebMainBench ✅ 545/545 completed; 0 unexpected failures
Release regression — ✅ HEAD/base failures 0/0; raw binary +0.001356%

Package and image size

Metric Base HEAD Delta Delta %
Raw binary 153.09 MiB 153.09 MiB +2.13 KiB +0.001356%
Stripped binary 106.39 MiB 106.39 MiB +4.00 KiB +0.003672%
gzip binary 52.71 MiB 52.71 MiB −5.43 KiB −0.010064%
Rootfs 159.99 MiB 159.99 MiB 0 B 0.00%
gzip rootfs 61.75 MiB 61.75 MiB −3.83 KiB −0.006060%

Startup latency and PSS

Case Base p50 HEAD p50 Delta Base PSS HEAD PSS Delta
Serve ready 27.45 ms 27.28 ms −0.17 ms 4.81 MiB 4.27 MiB −552.00 KiB
CDP first page 50.77 ms 49.67 ms −1.10 ms 4.59 MiB 3.93 MiB −675.00 KiB
CDP warm page 12.04 ms 12.19 ms +0.15 ms 50.86 MiB 50.92 MiB +65.00 KiB
CLI about:blank 15.10 ms 15.64 ms +0.54 ms 3.03 MiB 3.84 MiB +835.00 KiB
CLI local JS 18.87 ms 19.72 ms +0.85 ms 3.11 MiB 3.53 MiB +425.50 KiB

Concurrency matrix

Concurrency Base p50 HEAD p50 Delta Base PSS HEAD PSS Delta HEAD failures Unstable B/H
1 18.30 ms 17.90 ms −0.40 ms 772.00 KiB 727.00 KiB −45.00 KiB 0 0/0
5 20.73 ms 21.53 ms +0.79 ms 23.98 MiB 13.84 MiB −10.14 MiB 0 0/0
10 20.95 ms 20.88 ms −0.07 ms 28.01 MiB 14.11 MiB −13.90 MiB 0 0/0
25 20.35 ms 20.86 ms +0.51 ms 28.10 MiB 28.12 MiB +20.00 KiB 0 0/0
100 21.17 ms 20.73 ms −0.45 ms 21.52 MiB 12.79 MiB −8.73 MiB 0 0/0
Frontend differential — ✅ 1,020/1,020 cases matched; 0 issues
Match DOM mismatch Diagnostic mismatch Moli error Reference error Infrastructure error Mismatched frames Duration
1,020 0 0 0 0 0 0 6m 27.75s
Agent episodes · Moli vs Chromium — ⚪ artifact unavailable or invalid

Artifact unavailable or invalid. See the source CI run for infrastructure details.

Runtime and CDP session contracts — ✅ 26 contract cases; 0 failures
Suite Cases Failures Median case p50 Median case p95 Median peak PSS p50
Synthetic fetch 13 0 17.97 ms 18.74 ms 789.00 KiB
Long-lived CDP session 13 0 17.72 ms 18.51 ms —
CDP smoke — ✅ 52/52 groups passed; 621 scenarios

Workers: 4 · cumulative group time: 132.98 s · failed groups: 0

Slowest group Scenarios Duration Status
scrollbar-visibility 22 14.86 s ✅
target-lifecycle 24 10.08 s ✅
chromium-cdp 56 8.67 s ✅
dom-input 27 8.40 s ✅
multi-page 45 7.33 s ✅
WebMainBench · 545 pages — ✅ 545/545 completed; 0 unexpected failures
Completed Successful Expected DNS failure Unexpected failures Panics Crashes Timeouts Empty output
545/545 544 1 0 0 0 0 0

Frozen HTML · Linux · --wait done · 45 seconds per page · no retries. Content quality is evaluated separately.

Diagnostics: webmainbench-results — every page's Markdown, stderr, and exit status. Source run and artifacts

All artifact fields are parsed by the trusted default-branch renderer; missing or invalid inputs remain visible as unavailable.

@ldm0
ldm0 merged commit ba5cd6f into main Oct 17, 2026
18 of 20 checks passed
ldm0 added a commit that referenced this pull request Oct 18, 2026
A retained child's original SameObject getter captured undefined when
its lazy surface had never been read. Returning that snapshot after retirement
made Window.screen disappear when an iframe was removed before its first read.

Use captured objects when present, and let the exact retained native global
materialize an untouched surface in its original Realm. Retain receiver and
cross-origin authorization. Cover cold Screen reads, identity and zero geometry.

Fixes: 9f11881 (PR #1651)

Validation of the complete fix set, with unchanged source content across
the separate logical commits:
- cargo fmt --all
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo nextest run --no-fail-fast: 20374 passed, 18 skipped
ldm0 added a commit that referenced this pull request Oct 19, 2026
A retained child's original SameObject getter captured undefined when
its lazy surface had never been read. Returning that snapshot after retirement
made Window.screen disappear when an iframe was removed before its first read.

Use captured objects when present, and let the exact retained native global
materialize an untouched surface in its original Realm. Retain receiver and
cross-origin authorization. Cover cold Screen reads, identity and zero geometry.

Fixes: 9f11881 (PR #1651)

Validation of the complete fix set, with unchanged source content across
the separate logical commits:
- cargo fmt --all
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo nextest run --no-fail-fast: 20374 passed, 18 skipped

Original-commit: d61a6c8
ldm0 added a commit that referenced this pull request Oct 21, 2026
A retained child's original SameObject getter captured undefined when
its lazy surface had never been read. Returning that snapshot after retirement
made Window.screen disappear when an iframe was removed before its first read.

Use captured objects when present, and let the exact retained native global
materialize an untouched surface in its original Realm. Retain receiver and
cross-origin authorization. Cover cold Screen reads, identity and zero geometry.

Fixes: 9f11881 (PR #1651)

Validation of the complete fix set, with unchanged source content across
the separate logical commits:
- cargo fmt --all
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo nextest run --no-fail-fast: 20374 passed, 18 skipped

Original-commit: d61a6c8
ldm0 added a commit that referenced this pull request Oct 22, 2026
A retained child's original SameObject getter captured undefined when
its lazy surface had never been read. Returning that snapshot after retirement
made Window.screen disappear when an iframe was removed before its first read.

Use captured objects when present, and let the exact retained native global
materialize an untouched surface in its original Realm. Retain receiver and
cross-origin authorization. Cover cold Screen reads, identity and zero geometry.

Fixes: 9f11881 (PR #1651)

Validation of the complete fix set, with unchanged source content across
the separate logical commits:
- cargo fmt --all
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo nextest run --no-fail-fast: 20374 passed, 18 skipped

Original-commit: d61a6c8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant