In the previous chapter, Environment Health Diagnostics, we built a system to scan the computer and ensure all necessary security tools (like bubblewrap or ripgrep) are installed.
But scanning is just one part of the puzzle. Our React UI needs to do many things: read configuration files, check network rules, toggle settings, and run system commands.
We need a central bridge to connect our pretty User Interface to the messy Operating System.
Welcome to the Sandbox Data Adapter.
Imagine you are at a restaurant.
You don't walk into the kitchen to cook your own burger. You talk to the Waiter. The waiter takes your polite request ("I'd like the burger"), translates it into kitchen shorthand, hands it to the chef, and brings you back the result.
The Sandbox Data Adapter (implemented as SandboxManager) is the waiter.
React components are good at rendering buttons and text. They are bad at:
We create a single class, SandboxManager, that abstracts all this complexity. The UI asks simple questions like isSandboxingEnabled(), and the Manager handles the hard work of looking up the answer.
This is a classic programming pattern. We "adapt" the complex reality of the operating system into a clean, simple API that our frontend can understand.
The Manager handles two types of traffic:
The UI shouldn't care if it's running on a Mac or Linux. The Manager hides these details. If we ask for "Dependencies," the Manager knows which tools to look for based on the OS.
The SandboxManager is designed to be static and easy to call from anywhere in the UI.
This is how the Settings Orchestrator knows which tab to show.
import { SandboxManager } from '../../utils/sandbox/sandbox-adapter.js';
// Ask the manager a simple question
const isEnabled = SandboxManager.isSandboxingEnabled();
// Output: true or false
console.log("Is the sandbox on?", isEnabled);
Explanation: The UI doesn't know which JSON file stores this setting. It just asks the Manager.
When a user clicks a button, we tell the Manager to update the system.
// The user wants to enable 'Auto-Allow' mode
await SandboxManager.setSandboxSettings({
enabled: true,
autoAllowBashIfSandboxed: true
});
Explanation: The setSandboxSettings function handles opening the config file, updating the JSON, and saving it back to the disk safely.
What happens when we call these functions? Let's trace the flow of data when the Environment Health Diagnostics asks for a health check.
Let's look at simplified versions of the internal logic within the Adapter.
The Manager reads the raw settings from the disk and provides helper methods to access specific parts, like the Network config.
// Inside SandboxManager implementation
static getNetworkRestrictionConfig() {
// 1. Read the full settings object
const settings = this.getSettings();
// 2. Extract only the network portion
return settings.sandbox?.network || {
allowedHosts: [],
deniedHosts: []
};
}
Explanation: This safeguards the UI. Even if the config file is empty or missing, this function ensures we return a valid object (empty arrays) so the UI doesn't crash.
This is the logic that powers the "Doctor" section. It aggregates checks into a single report.
static checkDependencies() {
const errors = [];
// Check specifically for 'ripgrep'
if (!this.hasRipgrep()) {
errors.push("ripgrep (rg) is missing");
}
// Return a clean object the UI can map over
return { errors, warnings: [] };
}
Explanation: The UI doesn't need to know how we checked for ripgrep. It just receives a list of strings to display.
Now we can see how the Sandbox Data Adapter connects all the previous chapters together:
setSandboxSettings to change modes.getFsReadConfig to show allowed files.areUnsandboxedCommandsAllowed to decide if retries are okay.checkDependencies to see if tools are installed.It is the beating heart of the sandbox application.
We have completed the Sandbox tutorial series!
We started with a user interface in the Settings Orchestrator, visualized complex rules with the Security Inspector, handled errors gracefully with the Fallback Manager, diagnosed system health with Diagnostics, and finally connected it all to the system with the Data Adapter.
By separating our code into these five distinct layers, we've created a security tool that is:
You now have a fully functional, secure, and user-friendly sandbox environment!
Generated by Code IQ