Skip to content

gojiplus/bubblewrap

Repository files navigation

Bubblewrap

Build Security Tests License: MIT

A secure, generic sandboxing wrapper for any AI coding assistant or command-line tool. Works with Aider, code-puppy, Cursor, Copilot, or any other tool. Cross-platform support (Linux + macOS), inspired by Claude Code's sandboxing approach.

Tested on: Linux (Ubuntu) βœ“ | macOS βœ“ | Windows βœ—

Features

  • Filesystem Isolation: Uses bubblewrap (Linux) or sandbox-exec (macOS) to restrict file access to working directory only
  • Cross-Platform: Works on both Linux and macOS with platform-specific sandboxing
  • Network Proxy: Routes all network traffic through a controlled proxy with domain allowlisting
  • Permission System: User approval required for sensitive operations
  • Sensitive Path Protection: Automatically blocks access to:
    • SSH keys (~/.ssh)
    • AWS credentials (~/.aws)
    • Google Cloud credentials (~/.config/gcloud)
    • Kubernetes config (~/.kube)
    • GPG keys (~/.gnupg)
    • Docker credentials (~/.docker)
  • Minimal Overhead: ~5-10ms per command execution

Installation

From npm (recommended)

npm install -g bubblewrap
# or
npm install bubblewrap

From source

git clone https://github.com/soodoku/bubblewrap.git
cd bubblewrap
npm install
npm run build
npm link  # Optional: for global CLI access

Prerequisites

# Linux: Install bubblewrap
sudo apt-get install bubblewrap  # Debian/Ubuntu
sudo dnf install bubblewrap      # Fedora
sudo pacman -S bubblewrap        # Arch

# macOS: sandbox-exec is included by default (no installation needed)
which sandbox-exec  # Verify it's available

# Install your preferred AI coding assistant (optional)
pip install aider-chat        # For Aider
npm install -g code-puppy     # For code-puppy
# or use Cursor, Copilot, etc.

Quick Start

CLI Usage

# Execute any command in the sandbox
sandbox exec ls -la
sandbox exec python script.py
sandbox exec node app.js

# Run Aider with a message (if installed)
sandbox aider run "Add error handling to the login function" -f src/auth.ts

# Run code-puppy (if installed)
sandbox code-puppy run "Implement user authentication" -f src/auth.ts

# Run npm/git commands in sandbox
sandbox npm test
sandbox git status

# Or use the safe-code CLI
safe-code exec your-command

Installed Globally

If you installed globally with npm install -g bubblewrap, use:

sandbox exec <command>
safe-code exec <command>

Local Installation

If installed locally, use via npm scripts or npx:

npx sandbox exec <command>
# or add to package.json scripts

Programmatic Usage

Generic Command Wrapper (Works with ANY tool)

import { CommandWrapper } from 'bubblewrap';

// Create a sandboxed command wrapper
const wrapper = new CommandWrapper({
  workingDir: process.cwd(),
  autoApproveRead: false,
  autoApproveWrite: false,
});

// Set up event handlers for permission requests
wrapper.on('permission-required', (data) => {
  console.log(`Permission requested: ${data.type} for ${data.resource}`);
  data.approve(); // or data.deny()
});

wrapper.on('network-approval-required', (data) => {
  console.log(`Network access requested to: ${data.domain}`);
  data.approve(); // or data.deny()
});

// Initialize the sandbox
await wrapper.initialize();

// Execute any command
const result = await wrapper.execute(['python', 'script.py']);
console.log(result.stdout);

// Clean up
await wrapper.shutdown();

Tool-Specific Wrappers (Optional Convenience)

import { AiderWrapper, CodePuppyWrapper, GenericToolWrapper } from 'bubblewrap';

// For Aider
const aider = new AiderWrapper({
  workingDir: process.cwd(),
  model: 'gpt-4',
  autoCommit: false,
});
await aider.initialize();
await aider.runMessage('Add validation', ['src/validator.ts']);
await aider.shutdown();

// For code-puppy
const codePuppy = new CodePuppyWrapper({
  workingDir: process.cwd(),
  model: 'claude-3-5-sonnet',
  provider: 'anthropic',
});
await codePuppy.initialize();
await codePuppy.runPrompt('Implement auth', ['src/auth.ts']);
await codePuppy.shutdown();

// Generic tool wrapper with convenience methods
const tool = new GenericToolWrapper({ workingDir: process.cwd() });
await tool.initialize();
await tool.runNpm('test');
await tool.runGit(['status']);
await tool.shutdown();

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Any Tool (Aider, code-puppy, npm, git...)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CommandWrapper / SandboxManager             β”‚
β”‚ - Permission system                         β”‚
β”‚ - Domain allowlist/blocklist                β”‚
β”‚ - Filesystem path restrictions              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Filesystem Sandbox β”‚ β”‚ Network Proxy      β”‚
β”‚ (bubblewrap/macOS) β”‚ β”‚ (Unix socket)      β”‚
β”‚                    β”‚ β”‚                    β”‚
β”‚ - Unshare all      β”‚ β”‚ - Domain filter    β”‚
β”‚ - Bind mounts      β”‚ β”‚ - User approval    β”‚
β”‚ - Read-only /usr   β”‚ β”‚ - Traffic logging  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Security Features

Filesystem Isolation

Uses Linux namespaces via bubblewrap to:

  • Restrict write access to working directory only
  • Block access to sensitive files (SSH keys, cloud credentials)
  • Mount system directories as read-only
  • Isolate process tree

Network Control

  • All network traffic routed through Unix socket proxy
  • Domain allowlisting (github.com, npmjs.com, pypi.org by default)
  • User approval required for new domains
  • Blocked domain list support

Permission Management

  • Granular permission types:
    • fs:read - Read file access
    • fs:write - Write file access
    • net:access - Network access
    • proc:spawn - Process execution
  • Time-limited permissions (1 hour default)
  • Auto-approval configuration
  • Permission revocation

Configuration

Default Configuration

{
  workingDir: process.cwd(),
  allowedReadPaths: ['/usr', '/lib', '/lib64', '/bin', '/etc/ssl'],
  allowedWritePaths: [process.cwd()],
  deniedPaths: [
    '~/.ssh',
    '~/.aws',
    '~/.config/gcloud',
    '~/.gnupg',
    '~/.kube',
    '~/.docker',
    '/etc/passwd',
    '/etc/shadow',
    '/etc/sudoers',
  ],
  enableNetworkProxy: true,
  allowedDomains: [
    'github.com',
    'raw.githubusercontent.com',
    'npmjs.com',
    'pypi.org',
    'registry.npmjs.org',
    'api.github.com',
  ],
  requireApprovalForNewDomains: true,
}

Custom Configuration

import { SandboxManager, CommandWrapper, PermissionType } from 'bubblewrap';

// Using SandboxManager directly
const sandbox = new SandboxManager(process.cwd(), {
  allowedDomains: ['*.example.com', 'api.myservice.com'],
  blockedDomains: ['evil.com'],
  requireApprovalForNewDomains: false,
});

// Enable auto-approval for file reads
sandbox.setAutoApprove([PermissionType.FILESYSTEM_READ]);
await sandbox.initialize();

// Or using CommandWrapper with custom config
const wrapper = new CommandWrapper({
  workingDir: process.cwd(),
  allowedDomains: ['github.com', 'npmjs.com'],
  autoApproveRead: true,
  autoApproveWrite: false,
});
await wrapper.initialize();

Testing

# Run tests
npm test

# Run with coverage
npm run test:coverage

Security Tests

The test suite includes security validation:

  • βœ“ Blocks access to SSH keys
  • βœ“ Blocks access to AWS credentials
  • βœ“ Blocks access to GCloud credentials
  • βœ“ Allows access to working directory
  • βœ“ Network traffic routes through proxy
  • βœ“ Permission system enforces approvals

Performance

Based on testing:

  • Command execution overhead: ~5-10ms
  • Memory overhead: ~2-5MB
  • Permission check latency: <1ms

Limitations

Platform Support

  • Linux: Full support with bubblewrap βœ“
  • macOS: Full support with sandbox-exec βœ“
  • Windows: Not supported (would need WSL2 or App Containers)

Interactive Mode

Interactive Aider sessions bypass some sandbox protections for usability. Use non-interactive mode for maximum security.

Network Proxy

  • Unix socket proxy currently supports HTTP/HTTPS
  • Some protocols may not be fully supported
  • DNS resolution happens outside sandbox

Comparison with Claude Code

This implementation is inspired by Claude Code's sandboxing approach:

Feature Claude Code Bubblewrap
Filesystem Isolation βœ“ βœ“
Network Proxy βœ“ βœ“
Permission System βœ“ βœ“
Sensitive Path Protection βœ“ βœ“
Platform Linux/macOS Linux/macOS
Tool Support Claude only Any tool (Aider, code-puppy, etc.)
Implementation Proprietary Open Source
Automated Testing Unknown GitHub Actions (both platforms)
Resource Limiting Unknown CPU/RAM limits βœ“

Documentation

Full documentation is available at: https://soodoku.github.io/bubblewrap/

Examples

See the examples directory for more usage examples:

Contributing

Contributions welcome! Please read our contributing guidelines.

License

MIT

Use Cases

  • AI Coding Assistants: Run Aider, code-puppy, or similar tools safely
  • CI/CD Pipelines: Sandbox untrusted build scripts
  • Code Review: Execute untrusted code changes in isolation
  • Development: Test tools without risking your system
  • Education: Teach coding in a safe environment

Acknowledgments

Security Disclosure

If you discover a security vulnerability, please open a GitHub issue or contact the maintainers directly.

About

No description, website, or topics provided.

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors