How Isolation Works
Each Rudel sandbox is fully isolated from the host WordPress installation and from other sandboxes. This page explains the mechanisms that make this possible.
SQLite database
Every sandbox gets its own SQLite database file (wordpress.db). This replaces the host's MySQL database entirely for that sandbox's context. Benefits:
- No shared state: Sandboxes cannot read or write each other's data.
- Instant creation: Creating a database is just copying a file.
- Portable: The entire database is a single file that can be copied, exported, or deleted.
- No credentials: Unlike MySQL, there are no connection strings or passwords to manage or leak.
The SQLite integration is handled by the WordPress SQLite Database Integration, which translates WordPress's MySQL queries to SQLite on the fly.
wp-content directory
Each sandbox has its own wp-content directory containing:
themes/: Sandbox-specific themes (copied from host)plugins/: Sandbox-specific pluginsuploads/: Isolated media uploadsmu-plugins/: Sandbox must-use plugins
WordPress core files (wp-includes/, wp-admin/) are shared from the host installation. Only the content layer is isolated.
Table prefix
Each sandbox uses its own table prefix to avoid any collision, even though the databases are separate files. This provides defense-in-depth and ensures WP-CLI commands operate on the correct tables.
Bootstrap mechanism
The bootstrap.php file in each sandbox sets WordPress constants before WordPress boots:
DB_DIRandDB_FILE: Point to the sandbox's SQLite database.WP_CONTENT_DIRandWP_CONTENT_URL: Point to the sandbox's wp-content.WP_PLUGIN_DIRandWPMU_PLUGIN_DIR: Sandbox plugin directories.WP_TEMP_DIR: Sandbox temp directory.UPLOADS: Sandbox upload path.
These constants are set before wp-settings.php runs, so WordPress sees the sandbox as its entire world.
open_basedir restriction
The bootstrap sets PHP's open_basedir to restrict file access:
ini_set('open_basedir', implode(PATH_SEPARATOR, [
$sandbox_path, // Sandbox directory (read/write)
$wp_core_path, // Shared WP core (read)
$rudel_plugin_dir, // Rudel plugin directory (read)
sys_get_temp_dir(), // PHP temp directory
'/tmp', // Fallback temp directory
]));In CLI mode, the WP-CLI tool's own directory is also added to the allowlist.
Once set, any file operation outside these paths fails silently. The host's wp-config.php, other sandboxes, and the host database are all inaccessible from within a sandbox.
Authentication salts
Each sandbox gets its own set of authentication salts, deterministically derived from the sandbox ID at boot time. This means sessions and cookies from one sandbox are not valid in another, preventing cross-sandbox session hijacking.
WP-CLI scoping
Each sandbox includes a wp-cli.yml file:
path: /var/www/html
require:
- /path/to/sandboxes/sandbox-{id}/bootstrap.phpAny wp command executed from within the sandbox directory automatically uses that sandbox's database and content. No flags needed.
Security model summary
| Attack vector | Defense |
|---|---|
Path traversal (../../) | open_basedir blocks access outside allowlist |
| Sandbox escape to host DB | SQLite is file-based, open_basedir restricts access |
| Cross-sandbox access | Each sandbox's open_basedir only includes its own path |
| Credential leakage | No MySQL credentials exist in sandbox context |
| Agent modifies its own jail | bootstrap.php and wp-cli.yml are read-only |
| Prompt injection via DB/files | Agent instructions in read-only CLAUDE.md; sandbox is disposable |