Tools: I Reverse Engineered ChatGPT Apps Iframe Sandbox

Tools: I Reverse Engineered ChatGPT Apps Iframe Sandbox

Source: Dev.to

Before ChatGPT Apps, I Had to Solve The Same Problem! ## The ChatGPT Apps SDK ## Hmmm, that Looks familiar 🤔 ## Iframes, magnets How do they work? ## The double-iframe trick ## Why the double iframe matters ## The spec caught up (and improved it) ## Conclusion When I was working on the first MCP-UI Client in production at Postman, I hit a brick wall fast. MCP-UI apps render untrusted code inside an iframe, and most real-world production applications block third party content and enforce it via their Content Security Policy (CSP). If the host only whitelists known domains, how do you load arbitrary apps? You do not! That is the point! 😅 I've been fighting CSPs since my Amex days. We built a dynamic CSP generator for micro‑frontend apps at runtime so each page could assemble the right script-src/frame-src on the fly. That taught me early: The CSP is never the easy part, but it's the part you can't dodge. So I reached out to Liad and Ido from MCPI-UI and worked with them to come up with a solution on how to allow untrusted third party apps (the point of MCP-UI) while ensuring the host application remained secure, keeping the host's CSP tight and without having to whitelist the whole internet. The solution was a double iframe architecture safe enough for production. Fast forward to the ChatGPT Apps SDK release. I found a lot of gaps in the developer experience while building ChatGPT apps, i.e having to connect via an ngrok tunnel, setting up a CDN server that was available to the tunnel, caching issues etc. So my first thought was to allow ChatGPT apps to render inside Postman so you can build and debug them faster! (We are probably one of the only MCP Hosts where it makes sense to render ChatGPT apps outside of ChatGPT). This is the video of explaining the DX gaps and how Postman MCP inspector support for chatGPT apps solves the problem For this I had to figure out how the ChatGPT Apps SDK client implementation worked, with no public facing documentation! (nobody apart from ChatGPT needs this! 😅). I started poking around the dev console inside ChatGPT and saw a very familiar setup. Same idea: a sandbox proxy iframe wrapping an inner iframe, with a message bridge in the middle! I had already built this once for MCP-UI, so I reverse engineered their flavor and used it to unlock ChatGPT Apps inside Postman. If your host enforces a CSP, you cannot just drop in any third-party iframe frame-src is an allowlist. An allowlist of "every MCP app that will ever exist" is not a thing. Also, you cannot just disable the CSP. That is a non starter for security teams. So the only way out is a fixed, trusted domain that the host can allow, and then a controlled way to render the actual app behind it. This is the core trick. Without this, MCP‑UI apps were basically dead in real enterprise hosts. The proxy is not a real proxy server. It is a static HTML page hosted on its own origin different to the host's origin. The host only whitelists that one domain. Everything else is controlled by the sandbox iframe. You need two layers to make the security model work: 1) The outer iframe (sandbox proxy) is on a different origin and sandboxed with a configured CSP 2) The inner iframe hosts the untrusted app with a relaxed CSP The CSP can also be enforceable per app. The MCP server (app) can provide a custom CSP to the sandbox. With the launch of MCP Apps, this architecture is now formalised and accepted as the default security model for third party UI via MCP. The MCP Apps working group took the learnings from MCP-UI and ChatGPT apps and added to the spec: The MCP Apps spec also added the use of metadata on UI resources so a server can declare what it needs: The host then builds CSP headers from that list. If the list is empty, defaults are restrictive. The CSP is annoying, but it is also the best guardrail we have for untrusted UI. You do not remove it. You configure it! and the double iframe trick was perfect for this use case! Disclaimer: This is by no means an obscure / innovative technique, it is what most of the industry uses in these cases for untrusted embedded UI. ChatGPT told me that during my research! 😂 If you want the deep docs, start here: Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse - Host loads the proxy on an allowlisted domain. - Proxy signals ready; host posts HTML + CSP metadata. - Proxy creates the inner iframe, sends the HTML via document.write() and relays messages. - Host and sandbox must be different origins - Sandbox must be allow-scripts allow-same-origin - Proxy must enforce CSP derived from UI metadata - Proxy must forward messages between host and guest - connectDomains for API calls - resourceDomains for scripts, styles, images, fonts - frameDomains for nested iframes - baseUriDomains for base tags - MCP-UI proxy flow and CSP details - MCP Apps spec (sandbox proxy section)