Welcome to the final chapter of our journey!
In the previous chapter, Data Model & Communication Protocol, we defined the language our agent speaks. We ensured that when components talk to each other, they use a strict grammar so nothing gets lost in translation.
Now, we face a more serious question: Trust.
We have built a powerful AI agent. It can edit files, run terminal commands, and browse the internet. But what if it makes a mistake? What if it tries to delete your operating system or upload your passwords to a random server?
In this chapter, we explore Sandboxing & Security Configuration, the safety harness that ensures our AI stays within the boundaries we set.
Imagine you are babysitting a toddler. You want them to have fun and play, but you don't want them to stick a fork in the electrical outlet or wander out into the street.
To solve this, you create a Playpen:
The Problem: An AI agent running on your computer usually has the same permissions as you. If you can delete a file, the AI can delete that file. If you can access your banking website, the AI can access it too. This is dangerous.
The Solution: We use a Sandbox. We wrap the agent in a digital bubble. We explicitly tell it: "You can only read these files," and "You can only talk to these websites."
The definition of these rules lives in sandboxTypes.ts. It uses our trusty validator Zod (from the previous chapter) to define exactly what is allowed.
There are three main pillars of security configuration:
Let's say you are working on a project that contains a file called .env with your secret passwords. You want the AI to help you code, but you want to guarantee it never reads that file, and never sends data to evil-hacker.com.
Here is how we configure the sandbox to solve this.
By default, we might want to block all internet access except for trusted documentation sites.
// Define allowed network destinations
const networkConfig = {
// Only allow talking to these domains
allowedDomains: [
'google.com',
'github.com',
'stackoverflow.com'
],
// Block everything else not in the list
allowManagedDomainsOnly: true
};
Explanation:
This configuration creates a "Walled Garden." If the agent tries to fetch data from evil-hacker.com, the request will be blocked immediately because it isn't on the list.
We can specifically deny access to sensitive files.
// Define filesystem permissions
const fsConfig = {
// The agent can write files in the current folder
allowWrite: ['./src'],
// BUT it cannot read this specific file
denyRead: ['./.env', '/etc/passwd']
};
Explanation:
Even if the agent tries to run a command like cat .env, the sandbox intercepts the operation and says, "Permission Denied."
How does the system actually enforce these rules? It acts like a border guard. Every time the agent tries to do something "risky" (like opening a file or a socket), it must show its papers to the Sandbox Manager.
Let's look at the actual code in sandboxTypes.ts that defines these structures.
This schema defines the shape of the network rules.
export const SandboxNetworkConfigSchema = lazySchema(() =>
z.object({
// List of domains the agent can contact
allowedDomains: z.array(z.string()).optional(),
// macOS specific: Allow secure Unix sockets
allowUnixSockets: z.array(z.string()).optional(),
// Allow hosting a local server?
allowLocalBinding: z.boolean().optional(),
})
.optional()
);
Explanation:
This defines the JSON structure for network rules. allowLocalBinding is interestingβit controls whether the agent is allowed to start a web server on your machine (which could be a security risk if exposed to the internet).
This schema handles the complex logic of overlapping permissions (e.g., "Allow the whole folder, but deny this one file inside it").
export const SandboxFilesystemConfigSchema = lazySchema(() =>
z.object({
// Explicitly allowed write paths
allowWrite: z.array(z.string()).optional(),
// Explicitly denied read paths (e.g., secrets)
denyRead: z.array(z.string()).optional(),
// Exceptions to the deny list
allowRead: z.array(z.string()).optional(),
})
.optional()
);
Explanation:
denyRead: The blacklist.allowRead: This is an override. You might deny reading /User/home, but allow reading /User/home/project.
Finally, we wrap everything in the main SandboxSettingsSchema. This controls the global state of the sandbox.
export const SandboxSettingsSchema = lazySchema(() =>
z.object({
// Master switch to turn sandboxing on/off
enabled: z.boolean().optional(),
// If the sandbox can't start, should the app crash?
failIfUnavailable: z.boolean().optional(),
// Link to the schemas we defined above
network: SandboxNetworkConfigSchema(),
filesystem: SandboxFilesystemConfigSchema(),
})
.passthrough() // Allow extra keys for platform specific tweaks
);
Key Concept: failIfUnavailable
In high-security corporate environments, if the sandbox fails to initialize (maybe the OS doesn't support it), you want the application to crash immediately rather than running unsafely. Setting failIfUnavailable: true ensures safety is mandatory, not optional.
Sometimes, security gets in the way of getting work done. The configuration includes specific "Escape Hatches" for advanced users, though they are discouraged for beginners.
// DANGEROUS: Allow specific commands to bypass the sandbox
allowUnsandboxedCommands: z.boolean().optional(),
// macOS specific: Weaken security to allow system certificate checks
enableWeakerNetworkIsolation: z.boolean().optional()
Explanation:
allowUnsandboxedCommands: If set to false, the dangerouslyDisableSandbox parameter (used in code) is ignored. It forces everything to stay in the playpen.enableWeakerNetworkIsolation: Some tools (like git or curl) need access to macOS system certificates to verify HTTPS. Enabling this makes the tools work better but opens a small security hole.In this chapter, we learned that Sandboxing & Security Configuration is the responsible guardian of our application.
You have now completed the Entrypoints tutorial series!
We started by walking through the CLI Entrypoint, initialized the system, built a programmable Agent SDK, connected it to the world via MCP, defined a strict Data Model, and finally secured it all with a Sandbox.
You now understand the complete architecture of a modern, secure, and high-performance AI agent application. Happy coding!
Generated by Code IQ