Secure Communication Between Isolated React Native Instances

Authors
Aliaksandr Babrykovich
Senior C++ Engineer
@
Callstack
No items found.

In our previous article, we introduced react-native-sandbox - a library that enables running multiple, isolated React Native instances within a single application. While the initial release focused on host-sandbox communication, we've now added a powerful new feature: direct communication between sandbox instances.

This enhancement opens up new possibilities for building complex multi-instance applications where sandboxes can communicate directly with each other, bypassing the host application entirely, while still maintaining the security.

Understanding Communication Patterns

Before diving into the implementation, let's clarify the two communication patterns available in react-native-sandbox:

Sandbox-Host-Sandbox - The Old Approach

This was the only way sandboxes could communicate with each other - through the host application acting as a message dispatcher. This approach came with performance penalties and unnecessary boilerplate code.

This is the traditional communication pattern where sandboxes communicate through the host application:

Sandbox A → Host → Sandbox B

Implementation:

const handleMessage = (data: any) => {
// Boilerplate routing logic that grows with each sandbox
  if (data.target === 'sandbox-b') {
    sandboxBRef.current?.postMessage(data.payload);
  } else if (data.target === 'sandbox-c') {
    sandboxCRef.current?.postMessage(data.payload);
  } else if (data.target === 'sandbox-d') {
    sandboxDRef.current?.postMessage(data.payload);
  }
// ... more boilerplate for each additional sandbox
};

<SandboxReactNativeView
  ref={sandboxARef}
  onMessage={handleMessage}
/>

<SandboxReactNativeView
  ref={sandboxBRef}
  onMessage={handleMessage}
/>

<SandboxReactNativeView
  ref={sandboxCRef}
  onMessage={handleMessage}
/>

// ... more sandboxes = more boilerplate

This approach required constant maintenance of routing logic in the host application and created tight coupling between sandboxes and the host's message handling implementation.

Sandbox-Sandbox - The New Approach

Sandboxes can now communicate directly with each other, eliminating the host-as-dispatcher pattern and all its associated problems.

This is the new direct communication pattern where sandboxes communicate directly:

Sandbox A ↔ Sandbox B

Implementation:

// Host application - NO message routing needed!export default
function App() {
  return (
    <View style={styles.flexRow}>
      <View style={styles.flex10Margin}>
        <SandboxReactNativeView
          origin="A"
          jsBundleSource="sandbox"
          componentName="SandboxA"
          allowedOrigins={['B']} // Simple configuration
        />
      </View>

      <View style={styles.flex10Margin}>
        <SandboxReactNativeView
          origin="B"
          jsBundleSource="sandbox"
          componentName="SandboxB"
          allowedOrigins={['A']} // Simple configuration
        />
      </View>
    </View>
  );
}

// Sandbox A - Direct communication
const sendToB = () => {
  globalThis.postMessage({ type: 'increment', value: 1 }, 'B');
};

// Sandbox B - Direct communication
const sendToA = () => {
  globalThis.postMessage({ type: 'decrement', value: 1 }, 'A');
};

With direct communication, sandboxes can send messages to each other without any involvement from the host. There’s no need for routing logic, no extra boilerplate, and no changes required in the host when adding new sandboxes. Just set the allowedOrigins prop, and sandboxes can communicate directly and efficiently.

Security Model

Communication maintains the same security principles as the rest of react-native-sandbox:

Origin-Based Access Control

Each sandbox explicitly declares which other sandboxes can send messages to it through the allowedOrigins prop:

// Sandbox A allows messages from Sandbox B
allowedOrigins={['B']}

// Sandbox B allows messages from Sandbox A
allowedOrigins={['A']}

Bidirectional Control

Communication is not automatically bidirectional. If Sandbox A wants to send messages to Sandbox B, both conditions must be met:

  1. Sandbox A's allowedOrigins includes 'B' (to send)
  2. Sandbox B's allowedOrigins includes 'A' (to receive)

Dynamic Permissions

The allowedOrigins can be updated at runtime, allowing for dynamic permission management:

const [allowCommunication, setAllowCommunication] = useState(false);

<SandboxReactNativeView
  origin="A"
  allowedOrigins={allowCommunication ? ['B'] : []}
  // ... other props
/>

Demo time

Check out the p2p-counter example, which demonstrates two sandboxes updating each other's state directly, no host routing required.

Conclusion

Direct communication between React Native sandbox instances represents a significant evolution in the react-native-sandbox library. It provides developers with the flexibility to build complex, multi-instance applications with direct communication capabilities while maintaining the security and isolation benefits that make sandboxing valuable.

Whether you're building a micro-frontend dashboard, or a plugin system, direct sandbox communication enables new architectural patterns that were previously difficult to achieve with React Native.

To get started with direct sandbox communication, check out the p2p-counter example and the complete API documentation.

Ready to build secure, scalable multi-instance applications?

Get started with react-native-sandbox

Table of contents
Need to harden your app’s security?

We assist teams in applying security best practices to protect their apps.

Let’s chat
Link copied to clipboard!
//
Insights

Learn more about

Security

Here's everything we published recently on this topic.

Sort
No items found.
//
Security

We can help you move
it forward!

At Callstack, we work with companies big and small, pushing React Native everyday.

Monitoring & Observability

Enable production-grade monitoring and observability for React Native apps with real-time insights and alerts.

Release Process Optimization

Ship faster with optimized CI/CD pipelines, automated deployments, and scalable release workflows for React Native apps.