8.3 KiB
Frictionless Security: Zero Impact on Wizard
⚠️ Status: Proposal / Roadmap
This document describes proposed approaches and may include hypothetical commands or config. For current runtime behavior, see config-reference.md, operations-runbook.md, and troubleshooting.md.
Core Principle
"Security features should be like airbags — present, protective, and invisible until needed."
Design: Silent Auto-Detection
1. No New Wizard Steps (Stays 9 Steps, < 60 Seconds)
// Wizard remains UNCHANGED
// Security features auto-detect in background
pub fn run_wizard() -> Result<Config> {
// ... existing 9 steps, no changes ...
let config = Config {
// ... existing fields ...
// NEW: Auto-detected security (not shown in wizard)
security: SecurityConfig::autodetect(), // Silent!
};
config.save()?;
Ok(config)
}
2. Auto-Detection Logic (Runs Once at First Start)
// src/security/detect.rs
impl SecurityConfig {
/// Detect available sandboxing and enable automatically
/// Returns smart defaults based on platform + available tools
pub fn autodetect() -> Self {
Self {
// Sandbox: prefer Landlock (native), then Firejail, then none
sandbox: SandboxConfig::autodetect(),
// Resource limits: always enable monitoring
resources: ResourceLimits::default(),
// Audit: enable by default, log to config dir
audit: AuditConfig::default(),
// Everything else: safe defaults
..SecurityConfig::default()
}
}
}
impl SandboxConfig {
pub fn autodetect() -> Self {
#[cfg(target_os = "linux")]
{
// Prefer Landlock (native, no dependency)
if Self::probe_landlock() {
return Self {
enabled: true,
backend: SandboxBackend::Landlock,
..Self::default()
};
}
// Fallback: Firejail if installed
if Self::probe_firejail() {
return Self {
enabled: true,
backend: SandboxBackend::Firejail,
..Self::default()
};
}
}
#[cfg(target_os = "macos")]
{
// Try Bubblewrap on macOS
if Self::probe_bubblewrap() {
return Self {
enabled: true,
backend: SandboxBackend::Bubblewrap,
..Self::default()
};
}
}
// Fallback: disabled (but still has application-layer security)
Self {
enabled: false,
backend: SandboxBackend::None,
..Self::default()
}
}
#[cfg(target_os = "linux")]
fn probe_landlock() -> bool {
// Try creating a minimal Landlock ruleset
// If it works, kernel supports Landlock
landlock::Ruleset::new()
.set_access_fs(landlock::AccessFS::read_file)
.add_path(Path::new("/tmp"), landlock::AccessFS::read_file)
.map(|ruleset| ruleset.restrict_self().is_ok())
.unwrap_or(false)
}
fn probe_firejail() -> bool {
// Check if firejail command exists
std::process::Command::new("firejail")
.arg("--version")
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
}
3. First Run: Silent Logging
$ zeroclaw agent -m "hello"
# First time: silent detection
[INFO] Detecting security features...
[INFO] ✓ Landlock sandbox enabled (kernel 6.2+)
[INFO] ✓ Memory monitoring active (512MB limit)
[INFO] ✓ Audit logging enabled (~/.config/zeroclaw/audit.log)
# Subsequent runs: quiet
$ zeroclaw agent -m "hello"
[agent] Thinking...
4. Config File: All Defaults Hidden
# ~/.config/zeroclaw/config.toml
# These sections are NOT written unless user customizes
# [security.sandbox]
# enabled = true # (default, auto-detected)
# backend = "landlock" # (default, auto-detected)
# [security.resources]
# max_memory_mb = 512 # (default)
# [security.audit]
# enabled = true # (default)
Only when user changes something:
[security.sandbox]
enabled = false # User explicitly disabled
[security.resources]
max_memory_mb = 1024 # User increased limit
5. Advanced Users: Explicit Control
# Check what's active
$ zeroclaw security --status
Security Status:
✓ Sandbox: Landlock (Linux kernel 6.2)
✓ Memory monitoring: 512MB limit
✓ Audit logging: ~/.config/zeroclaw/audit.log
→ 47 events logged today
# Disable sandbox explicitly (writes to config)
$ zeroclaw config set security.sandbox.enabled false
# Enable specific backend
$ zeroclaw config set security.sandbox.backend firejail
# Adjust limits
$ zeroclaw config set security.resources.max_memory_mb 2048
6. Graceful Degradation
| Platform | Best Available | Fallback | Worst Case |
|---|---|---|---|
| Linux 5.13+ | Landlock | None | App-layer only |
| Linux (any) | Firejail | Landlock | App-layer only |
| macOS | Bubblewrap | None | App-layer only |
| Windows | None | - | App-layer only |
App-layer security is always present — this is the existing allowlist/path blocking/injection protection that's already comprehensive.
Config Schema Extension
// src/config/schema.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityConfig {
/// Sandbox configuration (auto-detected if not set)
#[serde(default)]
pub sandbox: SandboxConfig,
/// Resource limits (defaults applied if not set)
#[serde(default)]
pub resources: ResourceLimits,
/// Audit logging (enabled by default)
#[serde(default)]
pub audit: AuditConfig,
}
impl Default for SecurityConfig {
fn default() -> Self {
Self {
sandbox: SandboxConfig::autodetect(), // Silent detection!
resources: ResourceLimits::default(),
audit: AuditConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SandboxConfig {
/// Enable sandboxing (default: auto-detected)
#[serde(default)]
pub enabled: Option<bool>, // None = auto-detect
/// Sandbox backend (default: auto-detect)
#[serde(default)]
pub backend: SandboxBackend,
/// Custom Firejail args (optional)
#[serde(default)]
pub firejail_args: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SandboxBackend {
Auto, // Auto-detect (default)
Landlock, // Linux kernel LSM
Firejail, // User-space sandbox
Bubblewrap, // User namespaces
Docker, // Container (heavy)
None, // Disabled
}
impl Default for SandboxBackend {
fn default() -> Self {
Self::Auto // Always auto-detect by default
}
}
User Experience Comparison
Before (Current)
$ zeroclaw onboard
[1/9] Workspace Setup...
[2/9] AI Provider...
...
[9/9] Workspace Files...
✓ Security: Supervised | workspace-scoped
After (With Frictionless Security)
$ zeroclaw onboard
[1/9] Workspace Setup...
[2/9] AI Provider...
...
[9/9] Workspace Files...
✓ Security: Supervised | workspace-scoped | Landlock sandbox ✓
# ↑ Just one extra word, silent auto-detection!
Advanced User (Explicit Control)
$ zeroclaw onboard --security-level paranoid
[1/9] Workspace Setup...
...
✓ Security: Paranoid | Landlock + Firejail | Audit signed
Backward Compatibility
| Scenario | Behavior |
|---|---|
| Existing config | Works unchanged, new features opt-in |
| New install | Auto-detects and enables available security |
| No sandbox available | Falls back to app-layer (still secure) |
| User disables | One config flag: sandbox.enabled = false |
Summary
✅ Zero impact on wizard — stays 9 steps, < 60 seconds
✅ Zero new prompts — silent auto-detection
✅ Zero breaking changes — backward compatible
✅ Opt-out available — explicit config flags
✅ Status visibility — zeroclaw security --status
The wizard remains "quick setup universal applications" — security is just quietly better.