Skip to main content

lean_ctx/core/
owasp_alignment.rs

1//! Maps lean-ctx security features to the OWASP Top 10 for Agentic Applications (2025).
2//! Used by `lean-ctx audit` CLI and `/v1/audit/events` endpoint.
3
4use serde::Serialize;
5
6#[derive(Debug, Clone, Serialize)]
7pub struct OwaspMapping {
8    pub owasp_id: &'static str,
9    pub owasp_title: &'static str,
10    pub risk_description: &'static str,
11    pub lean_ctx_mitigations: Vec<Mitigation>,
12    pub coverage: Coverage,
13}
14
15#[derive(Debug, Clone, Serialize)]
16pub struct Mitigation {
17    pub feature: &'static str,
18    pub module: &'static str,
19    pub description: &'static str,
20}
21
22#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
23pub enum Coverage {
24    Full,
25    Partial,
26    Minimal,
27}
28
29pub fn alignment() -> Vec<OwaspMapping> {
30    vec![
31        OwaspMapping {
32            owasp_id: "OWASP-AGENT-01",
33            owasp_title: "Excessive Agency",
34            risk_description: "Agent performs actions beyond intended scope or without proper authorization",
35            lean_ctx_mitigations: vec![
36                Mitigation { feature: "Capability System", module: "core/capabilities.rs", description: "Fine-grained capability declarations per tool (fs:read, fs:write, exec, net)" },
37                Mitigation { feature: "Role Guard", module: "server/role_guard.rs", description: "5 built-in roles with tool allowlists and shell policy" },
38                Mitigation { feature: "Shell Allowlist", module: "core/shell_allowlist.rs", description: "Opt-in command allowlist restricting which binaries agents can execute" },
39                Mitigation { feature: "Context Budget", module: "core/agent_budget.rs", description: "Per-agent token budgets preventing resource exhaustion" },
40            ],
41            coverage: Coverage::Full,
42        },
43        OwaspMapping {
44            owasp_id: "OWASP-AGENT-02",
45            owasp_title: "Prompt Injection",
46            risk_description: "Malicious instructions injected via data processed by the agent",
47            lean_ctx_mitigations: vec![
48                Mitigation { feature: "Context Compression", module: "core/terse/", description: "Deterministic compression reduces attack surface in injected content" },
49                Mitigation { feature: "Secret Detection", module: "core/secret_detection.rs", description: "Pre-read scanning detects and optionally redacts sensitive patterns" },
50                Mitigation { feature: "I/O Boundary", module: "core/io_boundary.rs", description: "Content filtering and secret-like path blocking before agent consumption" },
51            ],
52            coverage: Coverage::Partial,
53        },
54        OwaspMapping {
55            owasp_id: "OWASP-AGENT-03",
56            owasp_title: "Sensitive Information Disclosure",
57            risk_description: "Agent exposes confidential data through outputs or tool interactions",
58            lean_ctx_mitigations: vec![
59                Mitigation { feature: "PathJail", module: "core/pathjail.rs", description: "Filesystem jail prevents reads outside project root" },
60                Mitigation { feature: "I/O Boundary", module: "core/io_boundary.rs", description: "Secret-like path detection (.env, .ssh, credentials)" },
61                Mitigation { feature: "Secret Detection", module: "core/secret_detection.rs", description: "Regex-based detection of API keys, tokens, passwords in file content" },
62                Mitigation { feature: "Proxy Header Allowlist", module: "proxy/forward.rs", description: "Prevents leaking Set-Cookie and other sensitive headers" },
63                Mitigation { feature: "Memory Boundary", module: "core/memory_boundary.rs", description: "Cross-project access control with audit trail" },
64            ],
65            coverage: Coverage::Full,
66        },
67        OwaspMapping {
68            owasp_id: "OWASP-AGENT-04",
69            owasp_title: "Denial of Service",
70            risk_description: "Agent overwhelms system resources or causes service disruption",
71            lean_ctx_mitigations: vec![
72                Mitigation { feature: "Rate Limiter", module: "core/a2a/rate_limiter.rs", description: "Per-agent per-tool rate limiting" },
73                Mitigation { feature: "Memory Guard", module: "core/config/memory.rs", description: "RAM usage caps and idle cleanup" },
74                Mitigation { feature: "Budget Tracker", module: "core/agent_budget.rs", description: "Token budget enforcement with hard limits" },
75                Mitigation { feature: "Loop Detection", module: "config loop_detection", description: "Detects and throttles repetitive tool call patterns" },
76                Mitigation { feature: "Tool Timeout", module: "engine/mod.rs", description: "120s timeout on tool execution prevents indefinite hangs" },
77            ],
78            coverage: Coverage::Full,
79        },
80        OwaspMapping {
81            owasp_id: "OWASP-AGENT-05",
82            owasp_title: "Supply Chain Vulnerabilities",
83            risk_description: "Compromised tools, plugins, or dependencies affect agent behavior",
84            lean_ctx_mitigations: vec![
85                Mitigation { feature: "Signed Handoff Bundles", module: "core/handoff_transfer_bundle.rs", description: "Ed25519 signatures verify integrity and provenance of transferred data" },
86                Mitigation { feature: "Audit Trail", module: "core/audit_trail.rs", description: "SHA-256 chained append-only log of all tool calls and security events" },
87                Mitigation { feature: "Agent Identity", module: "core/agent_identity.rs", description: "Per-agent Ed25519 keypairs for cryptographic identity" },
88            ],
89            coverage: Coverage::Partial,
90        },
91        OwaspMapping {
92            owasp_id: "OWASP-AGENT-06",
93            owasp_title: "Insufficient Logging and Monitoring",
94            risk_description: "Lack of visibility into agent actions and security events",
95            lean_ctx_mitigations: vec![
96                Mitigation { feature: "Audit Trail", module: "core/audit_trail.rs", description: "Every tool call logged with agent ID, role, input hash, output tokens" },
97                Mitigation { feature: "Compliance Reports", module: "cli/audit_report.rs", description: "CLI command to generate aggregated compliance reports" },
98                Mitigation { feature: "Context OS Events", module: "core/context_os.rs", description: "Real-time event bus with SSE streaming for dashboard" },
99                Mitigation { feature: "Proxy Metrics", module: "proxy/metrics.rs", description: "Atomic counters for requests, tokens saved, bytes compressed" },
100            ],
101            coverage: Coverage::Full,
102        },
103        OwaspMapping {
104            owasp_id: "OWASP-AGENT-07",
105            owasp_title: "Insecure Code Execution",
106            risk_description: "Agent executes arbitrary or unsafe code without proper sandboxing",
107            lean_ctx_mitigations: vec![
108                Mitigation { feature: "Sandbox Level 0", module: "core/sandbox.rs", description: "Subprocess isolation with env_clear and timeout" },
109                Mitigation { feature: "Sandbox Level 1 (macOS)", module: "core/sandbox_seatbelt.rs", description: "OS-level Seatbelt profiles restricting filesystem and network" },
110                Mitigation { feature: "Sandbox Level 1 (Linux)", module: "core/sandbox_landlock.rs", description: "Landlock LSM restricting filesystem access" },
111                Mitigation { feature: "Command Blocklist", module: "tools ctx_shell", description: "Dangerous command patterns blocked before execution" },
112            ],
113            coverage: Coverage::Full,
114        },
115        OwaspMapping {
116            owasp_id: "OWASP-AGENT-08",
117            owasp_title: "Broken Access Control",
118            risk_description: "Agent accesses resources or performs actions beyond its permissions",
119            lean_ctx_mitigations: vec![
120                Mitigation { feature: "RBAC", module: "core/roles.rs", description: "5 built-in roles (viewer, coder, admin, ci, restricted) with granular policies" },
121                Mitigation { feature: "Capability System", module: "core/capabilities.rs", description: "Tool-level capability requirements checked against role grants" },
122                Mitigation { feature: "PathJail", module: "core/pathjail.rs", description: "All path arguments jailed to project root" },
123                Mitigation { feature: "Boundary Policy", module: "core/memory_boundary.rs", description: "Cross-project access control configurable per policy" },
124            ],
125            coverage: Coverage::Full,
126        },
127        OwaspMapping {
128            owasp_id: "OWASP-AGENT-09",
129            owasp_title: "Improper Multi-Agent Orchestration",
130            risk_description: "Coordination failures between agents lead to conflicts or data corruption",
131            lean_ctx_mitigations: vec![
132                Mitigation { feature: "Per-Agent Ledger", module: "core/context_ledger.rs", description: "Isolated context tracking per agent, preventing cross-contamination" },
133                Mitigation { feature: "Agent Registry", module: "core/agents.rs", description: "HTTP-backed registration with heartbeat and auto-deregistration" },
134                Mitigation { feature: "TaskStore File Locks", module: "core/a2a/task.rs", description: "Advisory file locks prevent lost updates from concurrent access" },
135                Mitigation { feature: "Atomic Writes", module: "core/context_ledger.rs", description: "Crash-safe temp+rename writes for all JSON stores" },
136            ],
137            coverage: Coverage::Full,
138        },
139        OwaspMapping {
140            owasp_id: "OWASP-AGENT-10",
141            owasp_title: "Insufficient Governance",
142            risk_description: "Lack of organizational policies and controls over agent behavior",
143            lean_ctx_mitigations: vec![
144                Mitigation { feature: "Policy Engine", module: "core/context_policies.rs", description: "Declarative policies with agent, content, and time-based conditions" },
145                Mitigation { feature: "Compliance Reports", module: "cli/audit_report.rs", description: "Aggregated reports: reads, compressions, denials, budget usage" },
146                Mitigation { feature: "Auto-Reroot Protection", module: "tools/server_paths.rs", description: "Opt-in control over project root changes, audited" },
147                Mitigation { feature: "Config-Driven", module: "core/config/mod.rs", description: "All security features configurable via config.toml" },
148            ],
149            coverage: Coverage::Full,
150        },
151    ]
152}
153
154/// Returns a compact summary suitable for CLI output.
155pub fn summary() -> String {
156    let mappings = alignment();
157    let mut out = String::from("OWASP Top 10 for Agentic Applications — lean-ctx Alignment\n");
158    out.push_str(&"=".repeat(60));
159    out.push('\n');
160    for m in &mappings {
161        let icon = match m.coverage {
162            Coverage::Full => "●",
163            Coverage::Partial => "◐",
164            Coverage::Minimal => "○",
165        };
166        out.push_str(&format!(
167            "\n{icon} {} — {}\n  Mitigations: {}\n",
168            m.owasp_id,
169            m.owasp_title,
170            m.lean_ctx_mitigations
171                .iter()
172                .map(|m| m.feature)
173                .collect::<Vec<_>>()
174                .join(", ")
175        ));
176    }
177    let full = mappings
178        .iter()
179        .filter(|m| m.coverage == Coverage::Full)
180        .count();
181    let partial = mappings
182        .iter()
183        .filter(|m| m.coverage == Coverage::Partial)
184        .count();
185    out.push_str(&format!(
186        "\nCoverage: {full}/10 Full, {partial}/10 Partial\n"
187    ));
188    out
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn alignment_covers_all_ten() {
197        let a = alignment();
198        assert_eq!(a.len(), 10);
199        for (i, m) in a.iter().enumerate() {
200            assert_eq!(m.owasp_id, format!("OWASP-AGENT-{:02}", i + 1));
201            assert!(!m.lean_ctx_mitigations.is_empty());
202        }
203    }
204
205    #[test]
206    fn summary_contains_all_ids() {
207        let s = summary();
208        for i in 1..=10 {
209            assert!(s.contains(&format!("OWASP-AGENT-{i:02}")));
210        }
211    }
212}