Skip to content

Bridge generated-UI target=_blank links through the host openLink capability - #1915

Open
baggiiiie wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
baggiiiie:fix/artifact-links
Open

Bridge generated-UI target=_blank links through the host openLink capability#1915
baggiiiie wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
baggiiiie:fix/artifact-links

Conversation

@baggiiiie

@baggiiiie baggiiiie commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

artifact links (<a target="_blank">) did nothing when clicked. The sandbox iframe intentionally omits allow-popups, so the browser blocks a new browsing context and the click goes nowhere.

This change routes user clicks across the frame boundary to the host's standard MCP Apps openLink capability, host opens only http(s) URLs.

before

executor-artifact-link-bug.mp4

after

executor-artifact-link-after-fix.mp4

Linked issue

no issue open yet, will open one if preferred

Verification

  • bun run format:check
  • bun run lint
  • bun run typecheck
  • bun run test
  • e2e — Artifacts · create-artifact hands a non-apps client a deep-link that renders the live component (adds a "pull request link opens with a normal left-click" step)
  • e2e (desktop) — Desktop (packaged, in a VM) · an artifact link opens in the system browser (desktop-macos, packaged Electron bundle in a tart guest): confirms the link leaves the app for the system browser instead of opening an in-app window — recording

Checklist

  • Added a changeset (bun run changeset), or this change needs none.
  • Added or updated tests for the new behaviour.
  • No secrets, credentials, or private data in the diff.

@baggiiiie
baggiiiie force-pushed the fix/artifact-links branch 4 times, most recently from a7a21c1 to 27cab43 Compare September 1, 2026 08:45
…apability

The sandbox iframe omits allow-popups, so artifact links silently failed. The
trusted renderer now relays a user click across the frame boundary, guarded by
a per-render closure nonce, and the host opens only http(s) URLs.
@devin-ai-integration

Copy link
Copy Markdown

Verdict: mergeable. Real bug (sandbox iframe has no allow-popups, so target=_blank clicks are dropped), fixed the way the codebase already handles it — the shell → host ui/open-link path that artifact-renderer.tsx already wires (bridge.onopenlinkhostRef.current.openLink), and shell-host.ts/desktop setWindowOpenHandler take it the rest of the way. No changes to credentials, tokens, or MCP connection health.

Mechanism check:

  • inner-renderer.tsx: postMessage is bound and the nonce generated before model code runs, and the bundle is an IIFE (packages/hosts/mcp-apps-shell/src/vite.ts), so generated code can't read the nonce; isTrusted blocks synthetic element.click(). Only trusted, unprevented, left-click, target=_blank anchors are relayed.
  • shell-app.tsx: nonce is captured on executor.renderer.ready, cleared on every renderer reset, checked against the current token; isExternalWebUrl restricts to http(s): so javascript: can't cross into the console origin. Adding app to the message-listener effect deps is fine — it's already a dep of the render effect and is stable from mcp-app.tsx.
  • Inner frame keeps sandbox="allow-scripts" (asserted in the new browser test).

Ran locally on the PR branch on top of current main (no conflicts):

  • bun run lint && bun run format:check — pass
  • bun run typecheck — pass (45/45)
  • packages/hosts/mcp-apps-shell bun run test — 83/83 pass, incl. new routes pull request links through the host without granting popup access
  • e2e selfhost, scenarios/artifacts.test.ts "create-artifact hands a non-Apps client a deep link…" (with the new left-click step) — pass

Not verified here: e2e/desktop-vm/artifact-external-link.test.ts (needs a tart guest; relied on the contributor's recording). Nothing pushed. Changeset present. Open 2 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant