1use 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 {
37 feature: "Capability System",
38 module: "core/capabilities.rs",
39 description: "Fine-grained capability declarations per tool (fs:read, fs:write, exec, net)",
40 },
41 Mitigation {
42 feature: "Role Guard",
43 module: "server/role_guard.rs",
44 description: "5 built-in roles with tool allowlists and shell policy",
45 },
46 Mitigation {
47 feature: "Shell Allowlist",
48 module: "core/shell_allowlist.rs",
49 description: "Opt-in command allowlist restricting which binaries agents can execute",
50 },
51 Mitigation {
52 feature: "Context Budget",
53 module: "core/agent_budget.rs",
54 description: "Per-agent token budgets preventing resource exhaustion",
55 },
56 ],
57 coverage: Coverage::Full,
58 },
59 OwaspMapping {
60 owasp_id: "OWASP-AGENT-02",
61 owasp_title: "Prompt Injection",
62 risk_description: "Malicious instructions injected via data processed by the agent",
63 lean_ctx_mitigations: vec![
64 Mitigation {
65 feature: "Context Compression",
66 module: "core/terse/",
67 description: "Deterministic compression reduces attack surface in injected content",
68 },
69 Mitigation {
70 feature: "Secret Detection",
71 module: "core/secret_detection.rs",
72 description: "Pre-read scanning detects and optionally redacts sensitive patterns",
73 },
74 Mitigation {
75 feature: "I/O Boundary",
76 module: "core/io_boundary.rs",
77 description: "Content filtering and secret-like path blocking before agent consumption",
78 },
79 ],
80 coverage: Coverage::Partial,
81 },
82 OwaspMapping {
83 owasp_id: "OWASP-AGENT-03",
84 owasp_title: "Sensitive Information Disclosure",
85 risk_description: "Agent exposes confidential data through outputs or tool interactions",
86 lean_ctx_mitigations: vec![
87 Mitigation {
88 feature: "PathJail",
89 module: "core/pathjail.rs",
90 description: "Filesystem jail prevents reads outside project root",
91 },
92 Mitigation {
93 feature: "I/O Boundary",
94 module: "core/io_boundary.rs",
95 description: "Secret-like path detection (.env, .ssh, credentials)",
96 },
97 Mitigation {
98 feature: "Secret Detection",
99 module: "core/secret_detection.rs",
100 description: "Regex-based detection of API keys, tokens, passwords in file content",
101 },
102 Mitigation {
103 feature: "Proxy Header Allowlist",
104 module: "proxy/forward.rs",
105 description: "Prevents leaking Set-Cookie and other sensitive headers",
106 },
107 Mitigation {
108 feature: "Memory Boundary",
109 module: "core/memory_boundary.rs",
110 description: "Cross-project access control with audit trail",
111 },
112 ],
113 coverage: Coverage::Full,
114 },
115 OwaspMapping {
116 owasp_id: "OWASP-AGENT-04",
117 owasp_title: "Denial of Service",
118 risk_description: "Agent overwhelms system resources or causes service disruption",
119 lean_ctx_mitigations: vec![
120 Mitigation {
121 feature: "Rate Limiter",
122 module: "core/a2a/rate_limiter.rs",
123 description: "Per-agent per-tool rate limiting",
124 },
125 Mitigation {
126 feature: "Memory Guard",
127 module: "core/config/memory.rs",
128 description: "RAM usage caps and idle cleanup",
129 },
130 Mitigation {
131 feature: "Budget Tracker",
132 module: "core/agent_budget.rs",
133 description: "Token budget enforcement with hard limits",
134 },
135 Mitigation {
136 feature: "Loop Detection",
137 module: "config loop_detection",
138 description: "Detects and throttles repetitive tool call patterns",
139 },
140 Mitigation {
141 feature: "Tool Timeout",
142 module: "engine/mod.rs",
143 description: "120s timeout on tool execution prevents indefinite hangs",
144 },
145 ],
146 coverage: Coverage::Full,
147 },
148 OwaspMapping {
149 owasp_id: "OWASP-AGENT-05",
150 owasp_title: "Supply Chain Vulnerabilities",
151 risk_description: "Compromised tools, plugins, or dependencies affect agent behavior",
152 lean_ctx_mitigations: vec![
153 Mitigation {
154 feature: "Signed Handoff Bundles",
155 module: "core/handoff_transfer_bundle.rs",
156 description: "Ed25519 signatures verify integrity and provenance of transferred data",
157 },
158 Mitigation {
159 feature: "Audit Trail",
160 module: "core/audit_trail.rs",
161 description: "SHA-256 chained append-only log of all tool calls and security events",
162 },
163 Mitigation {
164 feature: "Agent Identity",
165 module: "core/agent_identity.rs",
166 description: "Per-agent Ed25519 keypairs for cryptographic identity",
167 },
168 ],
169 coverage: Coverage::Partial,
170 },
171 OwaspMapping {
172 owasp_id: "OWASP-AGENT-06",
173 owasp_title: "Insufficient Logging and Monitoring",
174 risk_description: "Lack of visibility into agent actions and security events",
175 lean_ctx_mitigations: vec![
176 Mitigation {
177 feature: "Audit Trail",
178 module: "core/audit_trail.rs",
179 description: "Every tool call logged with agent ID, role, input hash, output tokens",
180 },
181 Mitigation {
182 feature: "Compliance Reports",
183 module: "cli/audit_report.rs",
184 description: "CLI command to generate aggregated compliance reports",
185 },
186 Mitigation {
187 feature: "Context OS Events",
188 module: "core/context_os.rs",
189 description: "Real-time event bus with SSE streaming for dashboard",
190 },
191 Mitigation {
192 feature: "Proxy Metrics",
193 module: "proxy/metrics.rs",
194 description: "Atomic counters for requests, tokens saved, bytes compressed",
195 },
196 ],
197 coverage: Coverage::Full,
198 },
199 OwaspMapping {
200 owasp_id: "OWASP-AGENT-07",
201 owasp_title: "Insecure Code Execution",
202 risk_description: "Agent executes arbitrary or unsafe code without proper sandboxing",
203 lean_ctx_mitigations: vec![
204 Mitigation {
205 feature: "Sandbox Level 0",
206 module: "core/sandbox.rs",
207 description: "Subprocess isolation with env_clear and timeout",
208 },
209 Mitigation {
210 feature: "Sandbox Level 1 (macOS)",
211 module: "core/sandbox_seatbelt.rs",
212 description: "OS-level Seatbelt profiles restricting filesystem and network",
213 },
214 Mitigation {
215 feature: "Sandbox Level 1 (Linux)",
216 module: "core/sandbox_landlock.rs",
217 description: "Landlock LSM restricting filesystem access",
218 },
219 Mitigation {
220 feature: "Command Blocklist",
221 module: "tools ctx_shell",
222 description: "Dangerous command patterns blocked before execution",
223 },
224 ],
225 coverage: Coverage::Full,
226 },
227 OwaspMapping {
228 owasp_id: "OWASP-AGENT-08",
229 owasp_title: "Broken Access Control",
230 risk_description: "Agent accesses resources or performs actions beyond its permissions",
231 lean_ctx_mitigations: vec![
232 Mitigation {
233 feature: "RBAC",
234 module: "core/roles.rs",
235 description: "5 built-in roles (viewer, coder, admin, ci, restricted) with granular policies",
236 },
237 Mitigation {
238 feature: "Capability System",
239 module: "core/capabilities.rs",
240 description: "Tool-level capability requirements checked against role grants",
241 },
242 Mitigation {
243 feature: "PathJail",
244 module: "core/pathjail.rs",
245 description: "All path arguments jailed to project root",
246 },
247 Mitigation {
248 feature: "Boundary Policy",
249 module: "core/memory_boundary.rs",
250 description: "Cross-project access control configurable per policy",
251 },
252 ],
253 coverage: Coverage::Full,
254 },
255 OwaspMapping {
256 owasp_id: "OWASP-AGENT-09",
257 owasp_title: "Improper Multi-Agent Orchestration",
258 risk_description: "Coordination failures between agents lead to conflicts or data corruption",
259 lean_ctx_mitigations: vec![
260 Mitigation {
261 feature: "Per-Agent Ledger",
262 module: "core/context_ledger.rs",
263 description: "Isolated context tracking per agent, preventing cross-contamination",
264 },
265 Mitigation {
266 feature: "Agent Registry",
267 module: "core/agents.rs",
268 description: "HTTP-backed registration with heartbeat and auto-deregistration",
269 },
270 Mitigation {
271 feature: "TaskStore File Locks",
272 module: "core/a2a/task.rs",
273 description: "Advisory file locks prevent lost updates from concurrent access",
274 },
275 Mitigation {
276 feature: "Atomic Writes",
277 module: "core/context_ledger.rs",
278 description: "Crash-safe temp+rename writes for all JSON stores",
279 },
280 ],
281 coverage: Coverage::Full,
282 },
283 OwaspMapping {
284 owasp_id: "OWASP-AGENT-10",
285 owasp_title: "Insufficient Governance",
286 risk_description: "Lack of organizational policies and controls over agent behavior",
287 lean_ctx_mitigations: vec![
288 Mitigation {
289 feature: "Policy Engine",
290 module: "core/context_policies.rs",
291 description: "Declarative policies with agent, content, and time-based conditions",
292 },
293 Mitigation {
294 feature: "Compliance Reports",
295 module: "cli/audit_report.rs",
296 description: "Aggregated reports: reads, compressions, denials, budget usage",
297 },
298 Mitigation {
299 feature: "Auto-Reroot Protection",
300 module: "tools/server_paths.rs",
301 description: "Opt-in control over project root changes, audited",
302 },
303 Mitigation {
304 feature: "Config-Driven",
305 module: "core/config/mod.rs",
306 description: "All security features configurable via config.toml",
307 },
308 ],
309 coverage: Coverage::Full,
310 },
311 ]
312}
313
314pub fn summary() -> String {
316 let mappings = alignment();
317 let mut out = String::from("OWASP Top 10 for Agentic Applications — lean-ctx Alignment\n");
318 out.push_str(&"=".repeat(60));
319 out.push('\n');
320 for m in &mappings {
321 let icon = match m.coverage {
322 Coverage::Full => "●",
323 Coverage::Partial => "◐",
324 Coverage::Minimal => "○",
325 };
326 out.push_str(&format!(
327 "\n{icon} {} — {}\n Mitigations: {}\n",
328 m.owasp_id,
329 m.owasp_title,
330 m.lean_ctx_mitigations
331 .iter()
332 .map(|m| m.feature)
333 .collect::<Vec<_>>()
334 .join(", ")
335 ));
336 }
337 let full = mappings
338 .iter()
339 .filter(|m| m.coverage == Coverage::Full)
340 .count();
341 let partial = mappings
342 .iter()
343 .filter(|m| m.coverage == Coverage::Partial)
344 .count();
345 out.push_str(&format!(
346 "\nCoverage: {full}/10 Full, {partial}/10 Partial\n"
347 ));
348 out
349}
350
351#[cfg(test)]
352mod tests {
353 use super::*;
354
355 #[test]
356 fn alignment_covers_all_ten() {
357 let a = alignment();
358 assert_eq!(a.len(), 10);
359 for (i, m) in a.iter().enumerate() {
360 assert_eq!(m.owasp_id, format!("OWASP-AGENT-{:02}", i + 1));
361 assert!(!m.lean_ctx_mitigations.is_empty());
362 }
363 }
364
365 #[test]
366 fn summary_contains_all_ids() {
367 let s = summary();
368 for i in 1..=10 {
369 assert!(s.contains(&format!("OWASP-AGENT-{i:02}")));
370 }
371 }
372}