praxis-sec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -0
  3. package/ai-defense/cost-protection.md +292 -0
  4. package/ai-defense/llm-security-checklist.md +324 -0
  5. package/ai-defense/prompt-injection-patterns.js +283 -0
  6. package/ai-defense/system-prompt-armor.md +327 -0
  7. package/checklists/launch-day.md +168 -0
  8. package/cli/agents/abom-generator.js +225 -0
  9. package/cli/agents/agent-attestation-agent.js +318 -0
  10. package/cli/agents/agent-config-scanner.js +787 -0
  11. package/cli/agents/agent-telemetry-agent.js +415 -0
  12. package/cli/agents/agentic-security-agent.js +296 -0
  13. package/cli/agents/agentic-supply-chain-agent.js +463 -0
  14. package/cli/agents/ai-infra-inventory-agent.js +449 -0
  15. package/cli/agents/api-fuzzer.js +345 -0
  16. package/cli/agents/auth-bypass-agent.js +348 -0
  17. package/cli/agents/base-agent.js +280 -0
  18. package/cli/agents/cicd-scanner.js +300 -0
  19. package/cli/agents/config-auditor.js +757 -0
  20. package/cli/agents/deep-analyzer.js +776 -0
  21. package/cli/agents/endpoint-agent-abuse-agent.js +404 -0
  22. package/cli/agents/exception-handler-agent.js +187 -0
  23. package/cli/agents/git-history-scanner.js +169 -0
  24. package/cli/agents/governance-audits.js +138 -0
  25. package/cli/agents/hermes-security-agent.js +536 -0
  26. package/cli/agents/html-reporter.js +1125 -0
  27. package/cli/agents/index.js +147 -0
  28. package/cli/agents/injection-tester.js +502 -0
  29. package/cli/agents/legal-risk-agent.js +328 -0
  30. package/cli/agents/llm-redteam.js +199 -0
  31. package/cli/agents/managed-agent-scanner.js +333 -0
  32. package/cli/agents/mcp-security-agent.js +588 -0
  33. package/cli/agents/memory-poisoning-agent.js +305 -0
  34. package/cli/agents/mobile-scanner.js +231 -0
  35. package/cli/agents/model-file-scanner.js +259 -0
  36. package/cli/agents/orchestrator.js +355 -0
  37. package/cli/agents/pii-compliance-agent.js +301 -0
  38. package/cli/agents/policy-engine.js +229 -0
  39. package/cli/agents/prompt-injection-prober.js +224 -0
  40. package/cli/agents/rag-security-agent.js +204 -0
  41. package/cli/agents/recon-agent.js +207 -0
  42. package/cli/agents/sbom-generator.js +265 -0
  43. package/cli/agents/scoring-engine.js +273 -0
  44. package/cli/agents/ssrf-prober.js +130 -0
  45. package/cli/agents/stateful-watcher.js +238 -0
  46. package/cli/agents/supabase-rls-agent.js +154 -0
  47. package/cli/agents/supply-chain-agent.js +857 -0
  48. package/cli/agents/swarm-orchestrator.js +200 -0
  49. package/cli/agents/verifier-agent.js +303 -0
  50. package/cli/agents/vibe-coding-agent.js +250 -0
  51. package/cli/bin/praxis.js +866 -0
  52. package/cli/commands/abom.js +73 -0
  53. package/cli/commands/agent-fix.js +1245 -0
  54. package/cli/commands/audit.js +1180 -0
  55. package/cli/commands/autofix.js +383 -0
  56. package/cli/commands/baseline.js +193 -0
  57. package/cli/commands/benchmark.js +327 -0
  58. package/cli/commands/checklist.js +223 -0
  59. package/cli/commands/ci.js +403 -0
  60. package/cli/commands/deps.js +516 -0
  61. package/cli/commands/diff.js +200 -0
  62. package/cli/commands/doctor.js +195 -0
  63. package/cli/commands/env-audit.js +349 -0
  64. package/cli/commands/fix.js +218 -0
  65. package/cli/commands/guard.js +396 -0
  66. package/cli/commands/hooks.js +278 -0
  67. package/cli/commands/init.js +514 -0
  68. package/cli/commands/legal.js +158 -0
  69. package/cli/commands/live-advisories.js +241 -0
  70. package/cli/commands/mcp.js +660 -0
  71. package/cli/commands/openclaw.js +386 -0
  72. package/cli/commands/red-team.js +350 -0
  73. package/cli/commands/redteam.js +78 -0
  74. package/cli/commands/remediate.js +797 -0
  75. package/cli/commands/rotate.js +768 -0
  76. package/cli/commands/rules.js +196 -0
  77. package/cli/commands/scan-mcp.js +534 -0
  78. package/cli/commands/scan-skill.js +588 -0
  79. package/cli/commands/scan-standard.js +251 -0
  80. package/cli/commands/scan.js +524 -0
  81. package/cli/commands/score.js +449 -0
  82. package/cli/commands/shell.js +514 -0
  83. package/cli/commands/team-report.js +398 -0
  84. package/cli/commands/undo.js +161 -0
  85. package/cli/commands/update-intel.js +126 -0
  86. package/cli/commands/vibe-check.js +276 -0
  87. package/cli/commands/watch.js +757 -0
  88. package/cli/commands/web.js +63 -0
  89. package/cli/core/ast/guardrail-detector.js +141 -0
  90. package/cli/core/ast/index.js +22 -0
  91. package/cli/core/ast/parser.js +676 -0
  92. package/cli/core/ast/scope-tree.js +287 -0
  93. package/cli/core/ast/taint-tracker.js +158 -0
  94. package/cli/core/branding.js +37 -0
  95. package/cli/core/env.js +38 -0
  96. package/cli/core/errors.js +61 -0
  97. package/cli/core/fs.js +62 -0
  98. package/cli/core/output/compliance.js +90 -0
  99. package/cli/core/output/html-theme.js +158 -0
  100. package/cli/core/output/index.js +57 -0
  101. package/cli/core/output/json.js +48 -0
  102. package/cli/core/output/sarif.js +240 -0
  103. package/cli/core/version.js +67 -0
  104. package/cli/core/web/jobs.js +183 -0
  105. package/cli/core/web/projects.js +146 -0
  106. package/cli/core/web/server.js +439 -0
  107. package/cli/data/atlas-knowledge.json +5640 -0
  108. package/cli/data/eaa-catalog.json +39 -0
  109. package/cli/data/known-mcps.json +26 -0
  110. package/cli/data/probes/prompt-injection-corpus.json +271 -0
  111. package/cli/data/threat-intel.json +85 -0
  112. package/cli/data/threatpacks/latest.json +41 -0
  113. package/cli/hooks/patterns.js +313 -0
  114. package/cli/hooks/post-tool-use.js +140 -0
  115. package/cli/hooks/pre-tool-use.js +186 -0
  116. package/cli/index.js +90 -0
  117. package/cli/providers/llm-provider.js +766 -0
  118. package/cli/utils/autofix-rules.js +74 -0
  119. package/cli/utils/cache-manager.js +310 -0
  120. package/cli/utils/compliance-map.js +191 -0
  121. package/cli/utils/entropy.js +132 -0
  122. package/cli/utils/fix-ledger.js +127 -0
  123. package/cli/utils/hermes-tool-registry.js +252 -0
  124. package/cli/utils/intel/cache.js +61 -0
  125. package/cli/utils/intel/http.js +88 -0
  126. package/cli/utils/intel/index.js +235 -0
  127. package/cli/utils/intel/merge.js +229 -0
  128. package/cli/utils/intel/sources/epss.js +54 -0
  129. package/cli/utils/intel/sources/ghsa.js +81 -0
  130. package/cli/utils/intel/sources/gitguardian.js +40 -0
  131. package/cli/utils/intel/sources/gitleaks.js +101 -0
  132. package/cli/utils/intel/sources/kev.js +38 -0
  133. package/cli/utils/intel/sources/nvd.js +84 -0
  134. package/cli/utils/intel/sources/osv.js +132 -0
  135. package/cli/utils/intel/sources/phylum.js +44 -0
  136. package/cli/utils/intel/sources/snyk.js +46 -0
  137. package/cli/utils/intel/sources/socket.js +69 -0
  138. package/cli/utils/intel/sources/sonatype.js +84 -0
  139. package/cli/utils/intel/sources/threatpack.js +69 -0
  140. package/cli/utils/mcp-trust.js +60 -0
  141. package/cli/utils/output.js +251 -0
  142. package/cli/utils/patterns.js +1130 -0
  143. package/cli/utils/pdf-generator.js +94 -0
  144. package/cli/utils/plugin-loader.js +364 -0
  145. package/cli/utils/rule-import.js +228 -0
  146. package/cli/utils/rule-registry.js +426 -0
  147. package/cli/utils/scan-fingerprint.js +109 -0
  148. package/cli/utils/scan-playbook.js +312 -0
  149. package/cli/utils/score-history.js +119 -0
  150. package/cli/utils/secrets-verifier.js +247 -0
  151. package/cli/utils/security-memory.js +296 -0
  152. package/cli/utils/standards/atlas-knowledge.js +87 -0
  153. package/cli/utils/standards/index.js +127 -0
  154. package/cli/utils/standards/sources/avid.js +45 -0
  155. package/cli/utils/standards/sources/eu-ai-act.js +89 -0
  156. package/cli/utils/standards/sources/google-saif.js +39 -0
  157. package/cli/utils/standards/sources/iso-42001.js +94 -0
  158. package/cli/utils/standards/sources/mitre-atlas.js +54 -0
  159. package/cli/utils/standards/sources/nist-ai-600-1.js +45 -0
  160. package/cli/utils/standards/sources/owasp-llm.js +45 -0
  161. package/cli/utils/standards/sources/owasp-ml.js +45 -0
  162. package/cli/utils/threat-intel.js +265 -0
  163. package/configs/firebase/firestore-rules.txt +215 -0
  164. package/configs/firebase/security-checklist.md +236 -0
  165. package/configs/firebase/storage-rules.txt +206 -0
  166. package/configs/gitignore-template +258 -0
  167. package/configs/nextjs-security-headers.js +220 -0
  168. package/configs/praxisignore-template +50 -0
  169. package/configs/supabase/secure-client.ts +225 -0
  170. package/configs/supabase/security-checklist.md +278 -0
  171. package/docs/THIRD_PARTY_NOTICES.md +26 -0
  172. package/docs/THREAT_INTEL.md +292 -0
  173. package/docs/USAGE.md +1205 -0
  174. package/docs/design/WEB-UI.md +82 -0
  175. package/package.json +71 -0
  176. package/scripts/check-determinism.mjs +119 -0
  177. package/snippets/README.md +122 -0
  178. package/snippets/api-security/api-security-checklist.md +412 -0
  179. package/snippets/api-security/cors-config.ts +322 -0
  180. package/snippets/api-security/input-validation.ts +430 -0
  181. package/snippets/auth/jwt-checklist.md +322 -0
  182. package/snippets/rate-limiting/nextjs-middleware.ts +211 -0
  183. package/snippets/rate-limiting/upstash-ratelimit.ts +229 -0
@@ -0,0 +1,415 @@
1
+ /**
2
+ * Agent Telemetry Agent — AI Agent Session Audit Scanner
3
+ * =======================================================
4
+ *
5
+ * Audits workspace and developer environment AI agent session histories
6
+ * (Claude Code, Cursor IDE, Codex CLI, Warp Terminal, Cline) for security hazards:
7
+ * 1. Plaintext secrets / API keys embedded in chat transcripts
8
+ * 2. Unverified or dangerous shell execution logs (curl | bash, rm -rf, reverse shells)
9
+ * 3. Prompt injection payloads in agent interaction trails
10
+ * 4. LLM-output exfiltration signatures (EchoLeak-class: zero-width/bidi stego,
11
+ * encoded URL params, base64 blocks, JWT/PEM/bearer leaks)
12
+ * 5. Session forensics (tool-result errors, permission-mode escalation,
13
+ * sub-agent sidechains, transcript tampering/parse errors)
14
+ *
15
+ * Maps to: OWASP Agentic AI ASI01 (Prompt Injection), ASI02 (Tool Misuse),
16
+ * ASI05 (Credential Exposure), ASI03 (Data Compromise).
17
+ *
18
+ * Data-model notes (asftriage-derived): Claude Code transcripts are JSONL
19
+ * records { type, uuid, parentUuid, timestamp, sessionId, isSidechain?,
20
+ * message: { role, content } }; Codex rollout sessions are typed envelopes
21
+ * { timestamp, type, payload }. Never silently drop unknown record types —
22
+ * surface them as generic evidence.
23
+ */
24
+
25
+ import fs from 'fs';
26
+ import { BaseAgent, createFinding } from './base-agent.js';
27
+
28
+ // =============================================================================
29
+ // PATTERNS & REGEXES
30
+ // =============================================================================
31
+
32
+ export const SECRET_PATTERNS = [
33
+ {
34
+ rule: 'AGENT_LOG_EXPOSED_OPENAI_KEY',
35
+ title: 'Exposed OpenAI API Key in Agent Session History',
36
+ regex: /sk-(?:proj-)?[a-zA-Z0-9_-]{32,90}/g,
37
+ severity: 'critical',
38
+ cwe: 'CWE-522',
39
+ owasp: 'A07:2021',
40
+ description: 'Plaintext OpenAI API key detected inside AI agent conversation history or execution log.',
41
+ fix: 'Remove secret from session logs and rotate the compromised credential immediately.',
42
+ },
43
+ {
44
+ rule: 'AGENT_LOG_EXPOSED_ANTHROPIC_KEY',
45
+ title: 'Exposed Anthropic API Key in Agent Session History',
46
+ regex: /sk-ant-api03-[a-zA-Z0-9_-]{40,90}/g,
47
+ severity: 'critical',
48
+ cwe: 'CWE-522',
49
+ owasp: 'A07:2021',
50
+ description: 'Plaintext Anthropic API key detected inside AI agent conversation history.',
51
+ fix: 'Revoke the Anthropic key and ensure agent logs are scrubbed before storage.',
52
+ },
53
+ {
54
+ rule: 'AGENT_LOG_EXPOSED_GITHUB_TOKEN',
55
+ title: 'Exposed GitHub Access Token in Agent Log',
56
+ regex: /gh[po]_[a-zA-Z0-9]{36}/g,
57
+ severity: 'critical',
58
+ cwe: 'CWE-522',
59
+ owasp: 'A07:2021',
60
+ description: 'GitHub Personal Access Token or OAuth token detected in agent session state.',
61
+ fix: 'Revoke the token in GitHub settings and purge telemetry logs.',
62
+ },
63
+ {
64
+ rule: 'AGENT_LOG_EXPOSED_AWS_KEY',
65
+ title: 'Exposed AWS Access Key in Agent Log',
66
+ regex: /A[KS]IA[0-9A-Z]{16}/g,
67
+ severity: 'critical',
68
+ cwe: 'CWE-522',
69
+ owasp: 'A07:2021',
70
+ description: 'AWS Access Key ID (AKIA long-term or ASIA session token) detected in agent transcript.',
71
+ fix: 'Invalidate AWS credentials and configure secret masking in agent tools.',
72
+ },
73
+ ];
74
+
75
+ const HAZARDOUS_CMD_PATTERNS = [
76
+ {
77
+ rule: 'AGENT_LOG_PIPE_REMOTE_SHELL',
78
+ title: 'Piped Remote Shell Execution in Agent History',
79
+ regex: /(?:curl|wget)\s+-[^\n|]*\|\s*(?:bash|sh|powershell)/gi,
80
+ severity: 'high',
81
+ cwe: 'CWE-78',
82
+ owasp: 'A03:2021',
83
+ description: 'Agent session recorded execution of remote shell script pipe (curl | bash).',
84
+ fix: 'Audit agent command execution policies to disallow arbitrary unverified pipe scripts.',
85
+ },
86
+ {
87
+ rule: 'AGENT_LOG_RECURSIVE_DESTRUCTION',
88
+ title: 'Destructive File Deletion in Agent Log',
89
+ regex: /rm\s+-rf\s+[/~]/gi,
90
+ severity: 'high',
91
+ cwe: 'CWE-78',
92
+ owasp: 'A03:2021',
93
+ description: 'Agent session recorded execution of recursive destructive command (rm -rf / or ~).',
94
+ fix: 'Enforce workspace path boundaries on agent tool executions.',
95
+ },
96
+ ];
97
+
98
+ const PROMPT_INJECTION_PATTERNS = [
99
+ {
100
+ rule: 'AGENT_LOG_PROMPT_OVERRIDE',
101
+ title: 'Prompt Injection Override Payload in Transcript',
102
+ regex: /ignore\s+(?:all\s+)?previous\s+instructions/gi,
103
+ severity: 'high',
104
+ cwe: 'CWE-94',
105
+ owasp: 'A03:2021',
106
+ description: 'Agent conversation history contains explicit prompt injection override directive.',
107
+ fix: 'Sanitize incoming tool outputs and user inputs before injecting into context window.',
108
+ },
109
+ ];
110
+
111
+ // LLM-output exfiltration signatures (EchoLeak-class; derived from the
112
+ // MIT-licensed exfil-scan rule set).
113
+ const EXFIL_PATTERNS = [
114
+ {
115
+ rule: 'AGENT_LOG_ZERO_WIDTH_TEXT',
116
+ title: 'Invisible Text in Agent Transcript (EchoLeak class)',
117
+ // eslint-disable-next-line no-misleading-character-class -- deliberate invisible-char detection
118
+ regex: /[\u200B\u200C\u200D\uFEFF\u2060\u180E]/g,
119
+ severity: 'high',
120
+ cwe: 'CWE-506',
121
+ owasp: 'ASI03',
122
+ description: 'Agent transcript contains zero-width/invisible Unicode characters — the canonical EchoLeak / CVE-2025-32711-class hidden-payload signature. A leading BOM (U+FEFF) at file start is benign; mid-text occurrences are steganography.',
123
+ fix: 'Strip invisible characters from prompt-facing content. Inspect with a hex viewer.',
124
+ },
125
+ {
126
+ rule: 'AGENT_LOG_BIDI_CONTROL',
127
+ title: 'Bidi Control Character in Agent Transcript',
128
+ regex: /[\u202A-\u202E\u2066-\u2069]/g,
129
+ severity: 'high',
130
+ cwe: 'CWE-94',
131
+ owasp: 'ASI01',
132
+ description: 'Agent transcript contains bidi control characters (RLO/LRI/PDI/FSI) used to visually reorder hidden instructions or filenames.',
133
+ fix: 'Strip bidi controls from untrusted content and from displayed paths.',
134
+ },
135
+ {
136
+ rule: 'AGENT_LOG_JWT_TOKEN',
137
+ title: 'JWT Token Leaked in Agent Transcript',
138
+ regex: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,
139
+ severity: 'high',
140
+ cwe: 'CWE-200',
141
+ owasp: 'ASI05',
142
+ description: 'A three-segment JWT appears in the transcript — session/auth tokens pasted into prompts or returned by tools.',
143
+ fix: 'Revoke the token and scrub the transcript. Mask tool outputs that may contain credentials.',
144
+ },
145
+ {
146
+ rule: 'AGENT_LOG_SECRET_KV',
147
+ title: 'Credential Assignment Detected in Agent Transcript',
148
+ regex: /\b(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key)\b\s*[:=]\s*["']?([^\s"',;]{8,})/gi,
149
+ severity: 'high',
150
+ cwe: 'CWE-522',
151
+ owasp: 'ASI05',
152
+ description: 'A key=value credential assignment appears in the transcript. Placeholders (REDACTED, <your-...>, changeme, example, ***) are excluded.',
153
+ fix: 'Verify whether the value is a live credential; rotate if so. Mask assignments in future tool output.',
154
+ },
155
+ {
156
+ rule: 'AGENT_LOG_BEARER_TOKEN',
157
+ title: 'Authorization Bearer Token in Agent Transcript',
158
+ regex: /\b(?:Bearer|Authorization:?)\s+[A-Za-z0-9._-]{16,}/gi,
159
+ severity: 'high',
160
+ cwe: 'CWE-200',
161
+ owasp: 'ASI05',
162
+ description: 'A Bearer/Authorization header token appears in the transcript — typically from curl/httpie commands in tool inputs or outputs.',
163
+ fix: 'Rotate the token. Redact Authorization headers from command logs.',
164
+ },
165
+ {
166
+ rule: 'AGENT_LOG_ENCODED_URL_PARAM',
167
+ title: 'Encoded Payload in URL Parameter (Agent Transcript)',
168
+ regex: /https?:\/\/[^\s<>\]\)]+\?[^&\s]*=[A-Za-z0-9+/]{40,}/g,
169
+ severity: 'medium',
170
+ cwe: 'CWE-201',
171
+ owasp: 'ASI03',
172
+ description: 'A URL in the transcript carries a long base64-looking query parameter — a common exfiltration carrier in tool output and citations.',
173
+ fix: 'Review the URL. Long encoded query values should not leave the environment.',
174
+ },
175
+ {
176
+ rule: 'AGENT_LOG_BASE64_BLOCK',
177
+ title: 'Large Base64 Block in Agent Transcript',
178
+ regex: /(?<![A-Za-z0-9+/=])(?:[A-Za-z0-9+/]{4}){8,}(?:==|=)?(?![A-Za-z0-9+/=])/g,
179
+ severity: 'medium',
180
+ cwe: 'CWE-506',
181
+ owasp: 'ASI03',
182
+ description: 'A 32+ character base64 block appears outside code fences — possible encoded payload. Verify before treating as benign.',
183
+ fix: 'Decode and inspect the block. Apply output filtering for encoded payloads.',
184
+ },
185
+ ];
186
+
187
+ const PLACEHOLDER_VALUE = /^(?:REDACTED|\*{2,}|<[^>]{1,40}>|changeme|change_me|example|your[-_ ].*|xxx+|dummy|placeholder|not[_-]?a[_-]?(?:real|valid)[_-]?.*|sk-(?:test|demo))$/i;
188
+
189
+ // Whole-file patterns (multiline)
190
+ const WHOLE_FILE_PATTERNS = [
191
+ {
192
+ rule: 'AGENT_LOG_PEM_PRIVATE_KEY',
193
+ title: 'Private Key Material in Agent Transcript',
194
+ regex: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]{0,8000}?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
195
+ severity: 'critical',
196
+ cwe: 'CWE-320',
197
+ owasp: 'ASI05',
198
+ description: 'A PEM-encoded private key block appears in the transcript. The most severe form of credential exposure in agent telemetry.',
199
+ fix: 'Revoke the key immediately and purge the transcript from all retention.',
200
+ },
201
+ ];
202
+
203
+ // Structural JSONL forensics (asftriage-derived signals)
204
+ const FORENSIC_CHECKS = {
205
+ // Claude Code: tool_result with is_error, or shell exit code != 0
206
+ shellError(rec) {
207
+ if (rec?.type === 'user' && Array.isArray(rec?.message?.content)) {
208
+ for (const block of rec.message.content) {
209
+ if (block?.type === 'tool_result' && block.is_error) return block;
210
+ }
211
+ }
212
+ if (rec?.type === 'tool_result' && rec?.is_error) return rec;
213
+ return null;
214
+ },
215
+ // Claude Code v2: permission-mode escalation records
216
+ permissionMode(rec) {
217
+ if (rec?.type !== 'permission-mode') return null;
218
+ const raw = JSON.stringify(rec);
219
+ if (/bypassPermissions|acceptEdits|"mode"\s*:\s*"(?:bypassPermissions|acceptEdits|dontAsk|plan)"/i.test(raw)) return raw;
220
+ return null;
221
+ },
222
+ // Sub-agent sidechain records (activity hidden from the main timeline)
223
+ sidechain(rec) {
224
+ if (rec?.isSidechain === true) return rec;
225
+ return null;
226
+ },
227
+ };
228
+
229
+ // =============================================================================
230
+ // AGENT CLASS
231
+ // =============================================================================
232
+
233
+ export class AgentTelemetryAgent extends BaseAgent {
234
+ constructor() {
235
+ super(
236
+ 'AgentTelemetryAgent',
237
+ 'Audits AI agent session histories and telemetry logs for credentials, hazardous executions, injection trails, exfiltration signatures, and session forensics',
238
+ 'agentic-security'
239
+ );
240
+ }
241
+
242
+ /**
243
+ * Run telemetry analysis over codebase and agent session artifacts.
244
+ */
245
+ async analyze(context) {
246
+ const findings = [];
247
+ const { files = [] } = context;
248
+
249
+ for (const filePath of files) {
250
+ const lower = filePath.toLowerCase();
251
+ const isAgentArtifact =
252
+ lower.includes('.claude/') ||
253
+ lower.includes('.cursor/') ||
254
+ lower.includes('.codex/') ||
255
+ lower.includes('.cline/') ||
256
+ lower.includes('.warp/') ||
257
+ lower.endsWith('.jsonl') ||
258
+ lower.endsWith('.vscdb') ||
259
+ lower.includes('agent') ||
260
+ lower.includes('session');
261
+
262
+ if (!isAgentArtifact && !lower.endsWith('.json') && !lower.endsWith('.log')) {
263
+ continue;
264
+ }
265
+
266
+ let content = '';
267
+ try {
268
+ content = fs.readFileSync(filePath, 'utf8');
269
+ } catch {
270
+ continue;
271
+ }
272
+ if (!content) continue;
273
+
274
+ const lines = content.split(/\r?\n/);
275
+ const push = (p, lineNo, matched) => {
276
+ findings.push(createFinding({
277
+ file: filePath,
278
+ line: lineNo,
279
+ column: 1,
280
+ severity: p.severity,
281
+ category: this.category,
282
+ rule: p.rule,
283
+ title: p.title,
284
+ description: p.description,
285
+ matched: String(matched).slice(0, 120),
286
+ confidence: 'medium',
287
+ cwe: p.cwe,
288
+ owasp: p.owasp,
289
+ fix: p.fix,
290
+ }));
291
+ };
292
+
293
+ // ── Pass 1: line-scoped regex patterns ───────────────────────────────
294
+ for (const group of [SECRET_PATTERNS, HAZARDOUS_CMD_PATTERNS, PROMPT_INJECTION_PATTERNS, EXFIL_PATTERNS]) {
295
+ for (const pattern of group) {
296
+ for (let i = 0; i < lines.length; i++) {
297
+ pattern.regex.lastIndex = 0;
298
+ let match;
299
+ while ((match = pattern.regex.exec(lines[i])) !== null) {
300
+ // Skip placeholder credential values (docs/examples) for the
301
+ // generic secret-kv rule only.
302
+ if (pattern.rule === 'AGENT_LOG_SECRET_KV' && PLACEHOLDER_VALUE.test(match[1] || '')) break;
303
+ push(pattern, i + 1, match[0]);
304
+ if (!pattern.regex.global) break;
305
+ if (match.index === pattern.regex.lastIndex) pattern.regex.lastIndex++;
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ // ── Pass 2: whole-file (multiline) patterns ──────────────────────────
312
+ for (const pattern of WHOLE_FILE_PATTERNS) {
313
+ pattern.regex.lastIndex = 0;
314
+ let match;
315
+ while ((match = pattern.regex.exec(content)) !== null) {
316
+ const lineNo = content.slice(0, match.index).split('\n').length;
317
+ push(pattern, lineNo, match[0].slice(0, 40));
318
+ if (match.index === pattern.regex.lastIndex) pattern.regex.lastIndex++;
319
+ }
320
+ }
321
+
322
+ // ── Pass 3: structural JSONL forensics ───────────────────────────────
323
+ if (lower.endsWith('.jsonl')) {
324
+ let parseErrors = 0;
325
+ for (let i = 0; i < lines.length; i++) {
326
+ const line = lines[i];
327
+ if (!line.trim()) continue;
328
+ let rec;
329
+ try {
330
+ rec = JSON.parse(line);
331
+ } catch {
332
+ parseErrors++;
333
+ continue;
334
+ }
335
+
336
+ if (FORENSIC_CHECKS.shellError(rec)) {
337
+ findings.push(createFinding({
338
+ file: filePath,
339
+ line: i + 1,
340
+ column: 1,
341
+ severity: 'medium',
342
+ category: this.category,
343
+ rule: 'AGENT_LOG_SHELL_ERROR_EXIT',
344
+ title: 'Failed Shell Execution in Agent Session',
345
+ description: 'A tool result in the transcript records a shell error (is_error or non-zero exit). Failed executions are a key forensic signal — attacker recon and lateral-movement attempts typically leave a trail of failed commands.',
346
+ matched: 'tool_result is_error=true',
347
+ confidence: 'medium',
348
+ cwe: 'CWE-248',
349
+ owasp: 'ASI02',
350
+ fix: 'Review the failed commands and their surrounding session context. Failed-then-succeeded command pairs deserve special scrutiny.',
351
+ }));
352
+ }
353
+
354
+ if (FORENSIC_CHECKS.permissionMode(rec)) {
355
+ findings.push(createFinding({
356
+ file: filePath,
357
+ line: i + 1,
358
+ column: 1,
359
+ severity: 'high',
360
+ category: this.category,
361
+ rule: 'AGENT_LOG_PERMISSION_ESCALATION',
362
+ title: 'Permission-Mode Escalation in Agent Session',
363
+ description: 'The session contains a permission-mode escalation record (bypassPermissions / acceptEdits / plan). An escalation mid-session before destructive tool runs is the strongest intent indicator in insider-threat triage.',
364
+ matched: 'permission-mode escalation',
365
+ confidence: 'high',
366
+ cwe: 'CWE-862',
367
+ owasp: 'ASI02',
368
+ fix: 'Audit what the session did after the escalation. Prefer deny-by-default permission policies.',
369
+ }));
370
+ }
371
+
372
+ if (FORENSIC_CHECKS.sidechain(rec)) {
373
+ findings.push(createFinding({
374
+ file: filePath,
375
+ line: i + 1,
376
+ column: 1,
377
+ severity: 'low',
378
+ category: this.category,
379
+ rule: 'AGENT_LOG_SUBAGENT_SIDECHAIN',
380
+ title: 'Sub-Agent Sidechain Activity in Session',
381
+ description: 'The transcript contains sub-agent sidechain records — activity that runs outside the main conversation timeline and is easy to miss in review.',
382
+ matched: 'isSidechain record',
383
+ confidence: 'medium',
384
+ cwe: 'CWE-250',
385
+ owasp: 'ASI02',
386
+ fix: 'Review sidechain threads (Task/Agent sub-agents) explicitly — they are a common obfuscation vector.',
387
+ }));
388
+ }
389
+ }
390
+
391
+ if (parseErrors > 0 && lines.length >= 5 && parseErrors >= Math.ceil(lines.length * 0.05)) {
392
+ findings.push(createFinding({
393
+ file: filePath,
394
+ line: 1,
395
+ column: 1,
396
+ severity: 'medium',
397
+ category: this.category,
398
+ rule: 'AGENT_LOG_PARSE_ERRORS',
399
+ title: 'Transcript Tampering or Corruption (Parse Errors)',
400
+ description: `${parseErrors}/${lines.length} lines of this session transcript fail to parse as JSONL. Truncated or tampered transcripts are a forensic red flag — evidence may have been altered or deleted.`,
401
+ matched: `${parseErrors} unparseable lines`,
402
+ confidence: 'medium',
403
+ cwe: 'CWE-506',
404
+ owasp: 'ASI03',
405
+ fix: 'Verify the transcript against retention/backup copies. Correlated parse errors with suspicious tool activity indicate tampering.',
406
+ }));
407
+ }
408
+ }
409
+ }
410
+
411
+ return findings;
412
+ }
413
+ }
414
+
415
+ export default AgentTelemetryAgent;