Skip to content

Expose ServiceWorker in admitted cross-origin iframe realms #892

Description

@wieslawsoltes

Parent: #264 (unchanged Code OSS webviews). Follow-up to closed #265 (ServiceWorker control plane); downstream nested lifecycle: #267. Packaged installed-origin owner: SceneTech/AppScene#398 (PR #399 merged).

Exact installed-product failure — 21 September 2026

Unchanged Code OSS 645f29cc + merged WebScene d3c030fa + AppScene 34ba9e5, built via the verified installed AppScene SDK/CLI and published at vscode-demo/dist/appscene-release-34ba9e5-d3c030fa-webview/Code OSS AppScene.app. Native keyboard Markdown: Open Preview to the Side opens [Preview] README.md while the remote beta/README.md model has exact seven-byte content. The preview is blank. The previous errorCode=loader, status-0 HTTPS prelude document failures are gone after AppScene #399. The first new native error is from the real generated https://<id>.vscode-cdn.net/insider/645f29cc.../pre/index.html at inline line 237: Uncaught Error: Service Workers are not enabled. Webviews will not work. Try disabling private/incognito mode. The unchanged prelude only emits this when navigator.serviceWorker is absent. Native evidence and screenshot: vscode-demo/build/appscene-webview-398/native-preview.log, published-markdown-preview.png.

First owned boundary and proposed fix

In webscene_v8_runtime_cache_and_frames.inc, nested context construction calls install_service_worker_control(local_context, global) only when same_origin_access, which is parent-to-child DOM access. VS Code's prelude is deliberately hosted at a distinct HTTPS origin from its loopback workbench parent and therefore has no same-origin parent DOM access. This mistakenly hides ServiceWorker from a secure, admitted, non-opaque child that may register its own same-origin worker. The first product-neutral native run exposed a second bug in the existing sandbox guard: at realm installation, the child frame_body has not yet been attached to its owning iframe. Walking the child body parent chain therefore misses sandbox="allow-scripts" and incorrectly exposes ServiceWorker to an opaque child. Pass the actual owning iframe into the installer, walk it and its ancestors before child scripts run, and admit secure, non-opaque children independent of parent DOM access. Registration retains its separate secure-origin and same-origin scope checks. Do not alias the child to the workbench origin or expose a worker to an opaque sandboxed frame.

Focused gates before merge

  • Product-neutral native fixture with distinct HTTPS parent and child plus sandbox="allow-scripts allow-same-origin": child sees navigator.serviceWorker, parent cannot read the child DOM, and child registration/request scope stays its own origin; script and document requests use an admitted loader.
  • Secure-context / inherited-srcdoc vs cross-origin, no-sandbox, opaque sandbox, missing allow-scripts, ancestor-sandbox, wrong-origin worker and stale navigation cases align with Chromium/WPT-derived assertions. No untrusted cross-origin response is fetched.
  • Re-run the exact installed unchanged Markdown command: the prelude reaches navigator.serviceWorker.register() and either renders or records the next reduced blocker under [Epic] Qualify unchanged Code OSS webviews and nested document contexts #264/Stream and cache admitted Code OSS webview resources #266/Enforce secure nested-document lifecycle for Code OSS webviews #267. No false claim of complete Markdown from merely exposing a property.
  • Cold register-to-controller p95 <=1 s, warm navigation p95 <=250 ms, bounded 100 create/navigate/dispose cycles without retained workers/clients/ports/frames; visual/security and same-origin regression tests pass. Related native macOS and portable Linux/Windows runner checks pass before focused PR merge.

Focused gate checkpoint — 21 September 2026

The first native fixture confirmed the admitted cross-origin child can see/register its own ServiceWorker once the outer parent-access condition is removed, but also caught the previously masked opaque-sandbox exposure (opaque-sw-visible:true). The worktree now passes the owning iframe explicitly to the installer before attachment; a rebuild and rerun of the same native fixture is in progress. Retain both positive and negative gates before PR.

Focused PR and CI — 21 September 2026

WebScene PR #893 is open at ca635eb9. The native macOS fixture passes: the admitted isolated HTTPS child registers its own ServiceWorker and parent DOM access remains denied; both an opaque iframe and a nested iframe beneath an opaque ancestor have no navigator.serviceWorker. Frame registration plus sandbox checks complete in 230.711 ms against the 1 s gate. Related 100-cycle ServiceWorker lifecycle, Clients/MessagePort and iframe sandbox tests pass. The first PR metadata CI exposed a pre-existing main failure: its IndexedDB bootstrap digest test still expected an older SHA-256. The second commit updates only that expected digest to the current merged source; all five local literal tests pass. New-head metadata and relevant native CI are pending; duplicate old-head jobs were canceled. The exact installed Markdown package still needs a rebuild after merge.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingvscode-oss/plannedPlanned for the AppScene/WebScene VS Code OSS integration

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions