A split plugin sandbox divides a plugin into two parts. One part can read and change the host's data but cannot reach the network or the page. The other part can render UI and call the network but cannot see the host's data. The two parts only exchange messages, so no single piece holds both powers.
The pattern in a real product
Figma's plugin documentation describes this design. Plugin code runs on the main thread inside a sandbox that is a minimal JavaScript environment and does not expose browser APIs. It can read and edit the Figma scene, which is the hierarchy of layers in a document. It cannot call fetch, XMLHttpRequest or touch the DOM.
To show a UI or make a network request, the plugin creates an iframe. Inside the iframe the author can use any browser API, but the iframe cannot access the Figma scene. The two sides communicate through message passing.
The result is a deliberate separation of capabilities. An attacker who takes over the UI half cannot directly read the document. An attacker who takes over the data half cannot directly send it out.
Why this matters for exfiltration
Most plugin abuse follows one shape: read something valuable, then send it somewhere. A split sandbox makes the two steps pass through a message channel you control. That channel becomes a place to inspect, limit and log.
Figma adds a second control on the network half. When a plugin limits network access, any request to a domain not declared in its manifest is blocked and reported as a content security policy error. The documentation also notes the limit applies to the requests the plugin makes directly, and that a website rendered in the iframe can still load its own external resources. That is a useful reminder that boundaries have edges, and you should know where yours are.
How to copy the idea
- Name the two powers in your product. Typically they are reading customer data and talking to the outside world.
- Put each in a separate execution context so that no single plugin context has both.
- Define the message format between them as a small schema. Reject anything that does not match.
- Add size limits and rate limits on messages. A plugin that tries to stream the whole dataset through the channel should stand out.
- Log message counts per plugin. Unusual volume is a signal worth alerting on.
- Require a declared domain list for the network half and block everything else.
Trade-offs
Message passing is slower than a direct call and makes plugin code harder to write. Expect developer pushback and good documentation to ease it. You also need to keep the data half small. If the data half can embed the data in a URL and ask the host to open it, the separation is gone, so exposed host functions must be reviewed with the same care as the boundary.
Some products will find this level of design excessive for low-risk plugins. A reasonable approach is to require the split for any plugin that requests sensitive data scopes and allow a simpler path for read-only, local-only plugins.
Quick check
Does splitting a plugin stop all data theft?
No. It forces data to cross a message channel you control, which helps detection and limits direct access. A plugin allowed to pass data through that channel can still do so unless you restrict what messages may contain.
Is an iframe needed for the network half?
An iframe is one way to get a separate context with browser APIs. The principle is separate contexts with a narrow channel, whatever technology you use.
Safeguard helps on the supply chain side of this design. SBOM and dependency scanning show which libraries each half of a plugin bundles, and policies and gates can block a release that adds a risky one. The free scan takes a manifest and returns findings.
Sources
Last reviewed: 19 October 2026.