Skip to content

Let Smartlinks serve interactive browser apps safely - #116

Merged
jonaslsaa merged 9 commits into
mainfrom
feature/browser-capabilities
Aug 19, 2026
Merged

jonaslsaa merged 9 commits into
mainfrom
feature/browser-capabilities

Conversation

@jonaslsaa

@jonaslsaa jonaslsaa commented Aug 19, 2026 •

Copy link
Copy Markdown
Owner

Problem

Smartlink HTML responses were deliberately inert: the fixed response CSP blocked browser JavaScript, remote resources, connections, frames, embedding, and external form targets. That prevented useful small browser apps even when the capability affected only the artifact and its visitor.

Solution

Run every authored response in a mandatory opaque-origin CSP sandbox, then make external browser boundaries explicit, authenticated artifact policy.

  • Inline JavaScript, CSS, dynamic code, data/blob assets and workers, forms back to the runtime, and user-activated browser interactions work by default.
  • Repeatable --allow-* flags, --referrer, and --cors configure external scripts, connections, subresources, frames, forms, embedding, referrer disclosure, and credential-free CORS for build, run, and run --serve.
  • ctx.compile accepts the same typed browser policy and cors: true. Children choose their own policy rather than inheriting it.
  • Embedding and confirmation are mechanically incompatible; an embeddable child must explicitly set interstitial: false.
  • Browser policy is compact on the wire and bound into author signatures, HPKE secret AAD, and transparent guest-token identity. decode, previews, and interstitial facts expose it.
  • Guest code cannot spoof runtime-owned CORS headers or configure browser reports that disclose the bearer URL. Safe author CSP and cross-origin isolation policies remain available.
  • Valid preflights are answered before rate limiting or guest execution. run --serve uses an unguessable per-session path so local browser requests cannot force execution through the loopback server.
  • Runtime-owned pages retain the existing strict, nonembeddable policy. Authored pages can never enable allow-same-origin, cookies, persistent storage, or service workers on the shared runtime origin.

This keeps policy authorial without giving one Smartlink browser authority over another.

Verification

  • npm run check
    • 208 unit tests
    • 47 real-workerd Worker tests
    • 39 bundled CLI end-to-end tests
    • generated Worker types and Wrangler dry-run
  • Headless Chrome verified inline script execution, opaque-origin isolation, self-CORS, form navigation, and Smartlink-in-Smartlink embedding. The browser pass also caught and fixed the opaque-ancestor behavior for embeddableBy: ["all"].
  • Independent correctness/security, DX/contract, and maintainability reviews were run against the final implementation.

Closes #105
Closes #113
Closes #114

@vercel

vercel Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
smartlinks Ready Ready Preview Aug 19, 2026 6:26pm

@jonaslsaa
jonaslsaa merged commit d64500c into main Aug 19, 2026
3 checks passed
@jonaslsaa
jonaslsaa deleted the feature/browser-capabilities branch August 19, 2026 18:56

This branch was successfully deployed

1 active deployment
Preview — 8172d023 Deployed Aug 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant