Files
Luna/Documentation/References/ZeroClaw/Security.md
T
darman 9929941748 Add project documentation and reference materials
Include Luna AI Assistant design docs covering channels, configuration,
core architecture, memory, scheduler, and skills. Add reference docs
from OpenClaw and ZeroClaw projects, plus Mistral and OpenAI API specs.
2026-04-04 04:14:06 +02:00

6.8 KiB

Security

ZeroClaw implements a multi-layered security stack designed to provide defense-in-depth for autonomous agent operations. This system ensures that agents operate within defined boundaries, protect sensitive credentials, and provide a verifiable audit trail of all actions.


SecurityPolicy

The SecurityPolicy is the central enforcement mechanism for all tool and command executions. It defines the agent's level of independence and the specific constraints on its operating environment.

Autonomy Levels

Autonomy is categorized into three distinct levels, controlling the baseline behavior of the agent:

pub enum AutonomyLevel {
    /// Read-only: can observe but not act
    ReadOnly,
    /// Supervised: acts but requires approval for risky operations
    Supervised,
    /// Full: autonomous execution within policy bounds
    Full,
}

Risk Classification

Commands and operations are classified by their potential impact:

pub enum CommandRiskLevel {
    Low,
    Medium,
    High,
}

pub enum ToolOperation {
    Read,
    Act,
}

Action Tracker

ZeroClaw uses a sliding-window rate limiter to prevent automated abuse or runaway processes. It maintains a 1-hour window of all side-effecting actions.

pub struct ActionTracker {
    /// Timestamps of recent actions (kept within the last hour).
    actions: Mutex<Vec<Instant>>,
}

impl ActionTracker {
    pub fn record(&self) -> usize {
        let mut actions = self.actions.lock();
        let cutoff = Instant::now()
            .checked_sub(std::time::Duration::from_secs(3600))
            .unwrap_or_else(Instant::now);
        actions.retain(|t| *t > cutoff);
        actions.push(Instant::now());
        actions.len()
    }
}

Command Allowlist

ZeroClaw employs a deny-by-default strategy for shell execution. Only explicitly listed commands are permitted, and they are subjected to rigorous parsing to prevent bypasses.

Default Allowed Commands

git, npm, cargo, ls, cat, grep, find, echo, pwd, wc, head, tail, date.

Default Forbidden Paths

The system blocks access to 14 system directories (e.g., /etc, /root, /usr, /bin, /proc) and 4 sensitive dotfile locations (~/.ssh, ~/.gnupg, ~/.aws, ~/.config) even if workspace confinement is disabled.

Shell Parsing Logic

To prevent command injection via chained operators or environment variables, ZeroClaw uses a quote-aware shell segment splitter and environment assignment stripper:

fn skip_env_assignments(s: &str) -> &str {
    // Strips 'FOO=bar' from 'FOO=bar cmd args'
}

fn split_unquoted_segments(command: &str) -> Vec<String> {
    // Splits on ';', '|', '&&', '||', and newlines
    // Respects quotes to allow literal separators in arguments
}

Path Validation

The is_path_allowed() function implements multiple layers of protection to enforce workspace confinement and prevent directory traversal.

Validation Logic

pub fn is_path_allowed(&self, path: &str) -> bool {
    // 1. Null-byte injection guard
    if path.contains('\0') { return false; }

    // 2. Directory traversal detection
    if Path::new(path).components().any(|c| matches!(c, Component::ParentDir)) {
        return false;
    }

    // 3. URL-encoding detection (..%2f)
    let lower = path.to_lowercase();
    if lower.contains("..%2f") || lower.contains("%2f..") {
        return false;
    }

    // 4. Tilde expansion guard (blocks ~user forms)
    if path.starts_with('~') && path != "~" && !path.starts_with("~/") {
        return false;
    }

    // 5. Absolute path block and forbidden prefix match
    let expanded = expand_user_path(path);
    if self.workspace_only && expanded.is_absolute() { return false; }
    // ... (forbidden path checks)
}

Sandboxing

ZeroClaw supports multiple isolation backends via a unified Sandbox trait, allowing for varied levels of process and filesystem isolation.

  • Landlock: Linux-native LSM for fine-grained filesystem restriction.
  • Bubblewrap: Unprivileged sandboxing utility (used by Flatpak).
  • Docker: Containerized isolation for high-risk environments.
  • Firejail: SUID-based sandbox for easy desktop application isolation.

Landlock Implementation snippet:

fn apply_restrictions(&self) -> std::io::Result<()> {
    let mut ruleset = Ruleset::default()
        .handle_access(AccessFs::ReadFile | AccessFs::WriteFile | AccessFs::ReadDir | ...)
        .and_then(|ruleset| ruleset.create())?;

    // Grant access only to workspace and necessary system paths (/usr, /bin)
    if let Some(ref workspace) = self.workspace_dir {
        ruleset = ruleset.add_rule(PathBeneath::new(workspace_fd, ...))?;
    }
    ruleset.restrict_self()
}

Secret Management

The SecretStore protects API keys and credentials using authenticated encryption (ChaCha20-Poly1305).

pub struct SecretStore {
    key_path: PathBuf, // ~/.zeroclaw/.secret_key (mode 0600)
    enabled: bool,
}

Encryption ensures that secrets are never stored in plaintext in configuration files, preventing accidental exposure via grep, git log, or file sharing.


Audit Logging

Every security-relevant event is recorded in a structured JSONL format. This provides a forensic trail of what was executed, by whom, and whether it was permitted by policy.

pub struct AuditEvent {
    pub timestamp: DateTime<Utc>,
    pub event_type: AuditEventType,
    pub actor: Option<Actor>,
    pub action: Option<Action>,
    pub result: Option<ExecutionResult>,
    pub security: SecurityContext,
}

Emergency Stop (E-Stop)

The EstopManager provides a "big red button" capability to immediately halt or restrict agent activity.

  • Levels: KillAll, NetworkKill, DomainBlock, ToolFreeze.
  • Fail-Closed: If the state file is corrupt or unreadable, the system defaults to KillAll.
  • OTP Requirement: Resuming operations after an E-Stop engagement can be configured to require a One-Time Password (TOTP) to ensure human authorization.

Relevance to Luna

Luna currently lacks a security framework. Adopting ZeroClaw's security stack is critical before enabling tool execution in non-trusted environments.

Prioritized Adoption Order

  1. Filesystem Guards + Workspace Scoping: Implement is_path_allowed() to prevent Luna from escaping its designated project directory.
  2. Command Allowlist: Restrict shell tools to a known-safe subset with defined autonomy levels.
  3. Path Validation: Integrate component-aware path checking in all file-handling tools.
  4. Secret Store: Migrate Luna's configuration to use ChaCha20-Poly1305 for API keys.
  5. Audit Logging: Implement structured event logging for all tool invocations.
  6. Sandboxing: Introduce Landlock or Docker backends for executing untrusted code.

See also: Core, Skills, Configuration.