feat(tangle-cloud): sandboxed iframe blueprint apps#3175
Merged
Conversation
Adds first-party iframe support for blueprint apps hosted under *.blueprint.tangle.tools / *.blueprint.tangle.sh, gated behind - ops kill switch (VITE_BLUEPRINT_IFRAME_ENABLED) - iframe-eligible publisher allowlist (distinct from verified-publisher) - host suffix allowlist - per-manifest contract + chainId + selector grants Security stack: - iframe sandbox="allow-scripts allow-forms" (no allow-same-origin, no allow-top-navigation) so the frame runs in an opaque origin and cannot reach parent.localStorage / cookies / window.parent.ethereum - iframe allow="" (deny-all Permissions-Policy at element level) - parent-side CSP frame-src allowlist + frame-ancestors 'self' - parent-side Permissions-Policy denying camera/mic/geo/payment/usb/ bluetooth/etc. - X-Frame-Options: SAMEORIGIN on parent for legacy webview clickjack protection - strict origin + source equality on every postMessage event - typed postMessage protocol with bounded payload sizes, ASCII-only correlation ids, calldata size cap, value (wei) string validation - semantic policy gate: contract+selector+chain allowlist BEFORE the approval modal surfaces, so denied requests never prompt the user - approval modal renders the iframe app's display name + origin so users can attribute requests; sign flow goes through wagmi's useSendTransaction / useSignMessage / useSwitchChain in the parent Wallet flow stays in the parent: iframe never touches window.ethereum, sign requests bubble up via correlationId, parent posts results back keyed on that id. 42 new unit tests cover protocol validation, semantic policy, manifest parsing, origin checks.
✅ Deploy Preview for tangle-cloud ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for tangle-dapp ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for tangle-leaderboard ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3171.
Adds first-party iframe support for blueprint apps hosted under
*.blueprint.tangle.tools/*.blueprint.tangle.sh. Designed to onboard the two apps Tangle Labs already operates (ai-trading-blueprint arena, ai-agent-sandbox-blueprint console) without opening the iframe surface to arbitrary publishers.Trust gate (AND of all four)
VITE_BLUEPRINT_IFRAME_ENABLED) — single env flip turns iframe mode off everywhere, falls back to link-out. Default off.Security architecture
What's NOT in scope
Manifest authoring
For each iframe-eligible blueprint, the IPFS metadata's `blueprintUi` block adds:
```json
{
"externalApp": {
"url": "https://trading-arena.blueprint.tangle.tools/\",
"mode": "iframe",
"label": "Open Arena",
"iframe": {
"appId": "trading-arena",
"allowedChainIds": [3799],
"contracts": [
{
"chainId": 3799,
"address": "0x...",
"selectors": ["0xa9059cbb", "0x095ea7b3"]
}
],
"allowReadAccount": true,
"allowChainSwitch": false,
"allowPopups": false
}
},
"publisher": { "namespace": "tangle" }
}
```
Onboarding a new iframe app (runbook)
Files
```
apps/tangle-cloud/src/blueprintApps/
├── policy.ts # iframe gates + kill switch
├── manifest.ts # parser surfaces iframe config
└── components/
├── BlueprintAppFrame.tsx # hardened <iframe>
├── BlueprintAppFrameHost.tsx # frame + bridge + modal
├── IframeAppApprovalModal.tsx # signing UI with attribution
└── BlueprintAppLandingPage.tsx (modified) # mounts the host inline
apps/tangle-cloud/src/blueprintApps/iframe/
├── types.ts # iframe config types
├── manifest.ts # IPFS metadata parser
├── protocol.ts # typed postMessage protocol
├── origin.ts # origin/source equality checks
├── policy.ts # semantic capability gate
└── useIframeBridge.ts # parent-side message handler
apps/tangle-cloud/netlify.toml # CSP + Permissions-Policy + XFO
```
Test plan