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
package/docs/USAGE.md ADDED
@@ -0,0 +1,1205 @@
1
+ # Praxis — Complete Usage Guide
2
+
3
+ AI-native security CLI for AI-augmented codebases. Single binary, find→fix→verify
4
+ loop on autopilot. 28 parallel security agents (24 built-in + ModelFileScanner +
5
+ PromptInjectionProber + AgentTelemetryAgent + EndpointAgentAbuseAgent), multi-source threat intel, modular alignment with 8 AI-security
6
+ standards, LLM-powered remediation with diff review and undo log. Works fully
7
+ offline; LLM features are optional.
8
+
9
+ ---
10
+
11
+ ## Table of contents
12
+
13
+ 1. [Install](#install)
14
+ 2. [Quick start](#quick-start)
15
+ 3. [Command groups overview](#command-groups-overview)
16
+ 4. [`praxis scan` — security scans](#praxis-scan--security-scans)
17
+ 5. [`praxis fix` — apply remediations](#praxis-fix--apply-remediations)
18
+ 6. [`praxis agents` — AI agent surface](#praxis-agents--ai-agent-surface)
19
+ - [MCP trust registry](#mcp-trust-registry)
20
+ - [Governance absence-audits](#governance-absence-audits)
21
+ 7. [`praxis intel` — threat intelligence](#praxis-intel--threat-intelligence)
22
+ 8. [`praxis report` — format/share results](#praxis-report--formatshare-results)
23
+ 9. [`praxis project` — setup & state](#praxis-project--setup--state)
24
+ 10. [`praxis rules` — portable rule inventory](#praxis-rules--portable-rule-inventory)
25
+ 11. [`praxis web` — local web UI](#praxis-web--local-web-ui)
26
+ 12. [Top-level shortcuts](#top-level-shortcuts)
27
+ 13. [AI security standards alignment](#ai-security-standards-alignment)
28
+ 14. [AST & CST dataflow analysis engine](#ast--cst-dataflow-analysis-engine)
29
+ 15. [Threat packs (AI attack-vector signatures)](#threat-packs-ai-attack-vector-signatures)
30
+ 16. [Environment variables](#environment-variables)
31
+ 17. [Configuration files](#configuration-files)
32
+ 18. [Output formats](#output-formats)
33
+ 19. [CI/CD integration](#cicd-integration)
34
+ 20. [Custom plugins](#custom-plugins)
35
+ 21. [Troubleshooting](#troubleshooting)
36
+ 22. [`praxis mcp` — MCP server mode](#praxis-mcp--mcp-server-mode)
37
+ 23. [Get help](#get-help)
38
+
39
+ ---
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ # From source (this repo)
45
+ npm install
46
+ npm link # exposes `praxis` globally
47
+
48
+ # Or run directly without linking
49
+ node cli/bin/praxis.js --help
50
+ ```
51
+
52
+ Requires Node.js ≥ 18. No build step — Praxis runs from source via the `bin`
53
+ entry in `package.json`.
54
+
55
+ ---
56
+
57
+ ## Quick start
58
+
59
+ ```bash
60
+ praxis scan . # Full audit: secrets + 28 agents + deps + score
61
+ praxis fix . # Interactive LLM-guided fixes
62
+ praxis agents audit . # Audit CLAUDE.md, .cursorrules, MCP, skills
63
+ praxis intel update # Refresh threat-intel feed
64
+ praxis project init # Add security configs to your project
65
+ praxis vibe . # Emoji-graded A–F score
66
+ praxis --help # Show all groups
67
+ ```
68
+
69
+ Running `praxis` with no args on a TTY drops into the interactive REPL.
70
+
71
+ ---
72
+
73
+ ## Command groups overview
74
+
75
+ | Group | Purpose |
76
+ | --- | --- |
77
+ | `scan` | Run security scans |
78
+ | `fix` | Apply remediations |
79
+ | `agents` | Audit the AI/agent surface (skills, MCP, configs, attestation, BOM) |
80
+ | `intel` | Threat-intelligence feed updates and advisory operations |
81
+ | `report` | Format, diff, or share existing scan results |
82
+ | `project` | Init, hooks, watch, doctor, baseline, plugins, policies |
83
+ | `rules` | Inspect and export the detection rules (portable Semgrep-compatible bundle) |
84
+ | `web` | Local web UI for running scans and managing scan projects |
85
+
86
+ Plus three top-level shortcuts: `praxis vibe`, `praxis score`, and `praxis` alone (REPL on a TTY), plus [legacy flat aliases](#legacy-top-level-aliases) for the original command names.
87
+
88
+ ---
89
+
90
+ ## `praxis scan` — security scans
91
+
92
+ ### `scan full [path]` (default)
93
+
94
+ Full audit: secrets + 28 agents + deps + score + remediation plan.
95
+
96
+ | Flag | Description |
97
+ | --- | --- |
98
+ | `--json` | Output results as JSON |
99
+ | `--sarif` | Output as SARIF 2.1.0 |
100
+ | `--csv` | Output as CSV |
101
+ | `--md` | Output as Markdown |
102
+ | `--html [file]` | HTML report path (default: `praxis-report.html`) |
103
+ | `--pdf [file]` | Generate PDF (requires Chrome/Chromium) |
104
+ | `--compare` | Detailed comparison with last scan |
105
+ | `--timeout <ms>` | Per-agent timeout in ms (default 30000) |
106
+ | `--no-deps` | Skip dependency audit |
107
+ | `--no-ai` | Skip AI classification |
108
+ | `--no-cache` | Force full rescan |
109
+ | `--baseline` | Only show findings not in the baseline |
110
+ | `--deep` | LLM-powered taint analysis for critical/high findings |
111
+ | `--think` | Enable extended thinking mode |
112
+ | `--local` | Use local Ollama for deep analysis |
113
+ | `--model <model>` | LLM model for deep/AI analysis |
114
+ | `--provider <name>` | LLM provider (anthropic/openai/google/ollama/openai-compatible) |
115
+ | `--base-url <url>` | Custom OpenAI-compatible endpoint |
116
+ | `--budget <cents>` | Max spend in cents for deep analysis (default 50) |
117
+ | `--verify` | Check if leaked secrets are still active |
118
+ | `--include-legal` | Also run the legal risk scan |
119
+ | `--agentic [iterations]` | Agentic scan→fix→verify loop |
120
+ | `--agentic-target <score>` | Target security score for agentic loop |
121
+ | `--hermes-only` | Run only Hermes-relevant agents |
122
+ | `--fail-below <threshold>` | Exit 1 if score < threshold |
123
+ | `-v, --verbose` | Verbose output |
124
+
125
+ ### `scan secrets [path]`
126
+
127
+ Fast pattern-based secret scan only (no agents).
128
+
129
+ | Flag | Description |
130
+ | --- | --- |
131
+ | `-v, --verbose` | Show all files being scanned |
132
+ | `--no-color` | Disable colored output |
133
+ | `--json` | JSON output |
134
+ | `--sarif` | SARIF output |
135
+ | `--include-tests` | Also scan test files |
136
+ | `--no-cache` | Force full rescan |
137
+
138
+ ### `scan changed [ref]`
139
+
140
+ Scan only files changed since `<ref>` (default: `HEAD`).
141
+
142
+ | Flag | Description |
143
+ | --- | --- |
144
+ | `--staged` | Scan only staged changes |
145
+ | `--json` | JSON output |
146
+ | `-p, --path <path>` | Project path (default: cwd) |
147
+ | `--timeout <ms>` | Per-agent timeout in ms |
148
+
149
+ ### `scan env [path]`
150
+
151
+ Credential health check: `.env` coverage, source cross-ref, git history.
152
+
153
+ | Flag | Description |
154
+ | --- | --- |
155
+ | `--json` | JSON output |
156
+
157
+ ### `scan redteam [path]` / `praxis redteam [target]`
158
+
159
+ Dynamic AI Red Teaming & DAST Prober: executes 80+ attack classes statically and probes live LLM endpoints / agent runtimes with jailbreak, prompt injection, and goal-hijacking payloads.
160
+
161
+ | Flag | Description |
162
+ | --- | --- |
163
+ | `--endpoint <url>` | Target live LLM API endpoint for dynamic DAST probing |
164
+ | `--model <model>` | Target model identifier |
165
+ | `--probes <tags>` | Comma-separated probe categories (`jailbreak`, `injection`, `override`, `exfil`) |
166
+ | `--agents <list>` | Comma-separated list of static agents to run |
167
+ | `--json` | JSON output |
168
+ | `--sarif` | SARIF output |
169
+ | `--html [file]` | Generate interactive Pro HTML security report |
170
+ | `--sbom [file]` | Generate CycloneDX SBOM / ABOM |
171
+ | `--no-deps` | Skip dependency audit |
172
+ | `--no-ai` | Skip AI classification |
173
+ | `--deep` | LLM-powered taint analysis with AST scope evaluation |
174
+ | `--swarm` | AI swarm mode — 23 parallel agents via DeepSeek/Kimi |
175
+ | `--think`, `--local`, `--model`, `--provider`, `--base-url`, `--budget` | LLM controls (same as `scan full`) |
176
+ | `-v, --verbose` | Verbose output |
177
+
178
+ ### `scan standard [name] [path]`
179
+
180
+ Filter findings by AI-security standard. **New in this release.**
181
+
182
+ | Flag | Description |
183
+ | --- | --- |
184
+ | `--list` | List available standards and exit |
185
+ | `--control <id>` | Filter to a single control (e.g. `LLM01`) |
186
+ | `--json` | JSON output |
187
+ | `--sarif` | SARIF output |
188
+ | `--format <name>` | Output format from registry (json/sarif) |
189
+
190
+ Standards available: `owasp-llm`, `mitre-atlas`, `nist-ai-600-1`, `avid`,
191
+ `owasp-ml`, `eu-ai-act`, `iso-42001`, `google-saif`. See
192
+ [AI security standards alignment](#ai-security-standards-alignment).
193
+
194
+ ### `scan ci [path]`
195
+
196
+ CI/CD pipeline mode: scan, score, exit 1 on failure.
197
+
198
+ | Flag | Description |
199
+ | --- | --- |
200
+ | `--threshold <score>` | Minimum passing score (default 75) |
201
+ | `--fail-on <severity>` | Fail on findings ≥ this severity |
202
+ | `--always-fail-on <severity>` | Severity floor that even an accepted baseline cannot suppress |
203
+ | `--include-findings` | Include finding identities (`file`/`rule`/`severity`) in JSON output — used by the GitHub Action's net-new PR diff |
204
+ | `--sarif <file>` | Write SARIF for GitHub Code Scanning |
205
+ | `--json` | JSON output |
206
+ | `--no-deps` | Skip dependency audit |
207
+ | `--baseline` | Only check new findings |
208
+ | `--github-pr` | Post findings as a GitHub PR comment |
209
+ | `--strict-intel` | Fail if threat-intel feed is stale |
210
+ | `--max-intel-age <duration>` | Max acceptable intel age (default `7d`) — accepts `7d`/`24h`/`30m`/`60s` |
211
+
212
+ ---
213
+
214
+ ## `praxis fix` — apply remediations
215
+
216
+ ### `fix interactive [path]` (default)
217
+
218
+ Interactive LLM-guided: scan → plan → diff → ask → apply → **verification ladder**.
219
+
220
+ The verification ladder (all gates are executable oracles, never model judgment):
221
+
222
+ 1. **Build/lint** — the project's own build or lint command must still pass (npm/cargo/go/make detected automatically)
223
+ 2. **Test suite** — the project's test command must still pass
224
+ 3. **Re-scan** — the original findings must be gone from the fixed file
225
+
226
+ On failure, the failing tier's evidence is fed into a retry plan; if the final attempt still fails, the fix is **automatically reverted** and the file restored. Fix prompts require sibling-call-site coverage and a regression test in the diff. Every applied fix is recorded in `.praxis/fixes.jsonl` with its verification class.
227
+
228
+ | Flag | Description |
229
+ | --- | --- |
230
+ | `--plan-only` | Generate plans for review but never write |
231
+ | `--severity <level>` | Minimum severity to fix (default `low`) |
232
+ | `--provider <name>` | LLM provider |
233
+ | `--model <model>` | Specific model name |
234
+ | `--think` | Enable extended thinking |
235
+ | `--allow-dirty` | Allow running with uncommitted changes |
236
+ | `--branch [name]` | Create a branch and commit one fix per file |
237
+ | `--pr` | Push branch + open PR via `gh` (requires `--branch`) |
238
+ | `--yolo` | Auto-accept every plan (dangerous) |
239
+ | `--auto-low` | Auto-accept plans marked `risk:low` |
240
+ | `--max-attempts <n>` | Max plan attempts per file (verification-ladder retries, default 2) |
241
+ | `--sandbox` | Verify each fix in a Docker sandbox |
242
+ | `--ci` | Non-interactive CI/CD mode (auto-accept fixes) |
243
+
244
+ ### `fix quick [path]`
245
+
246
+ Deterministic secret fixer: rewrite source + write `.env`. No LLM.
247
+
248
+ | Flag | Description |
249
+ | --- | --- |
250
+ | `--dry-run` | Preview without writing |
251
+ | `--yes` | Apply all fixes without prompting |
252
+ | `--stage` | Run `git add` on modified files |
253
+ | `--all` | Also fix common agent findings (debug, TLS bypass, shell injection) |
254
+
255
+ ### `fix from-report [path]`
256
+
257
+ Apply LLM fixes from a deep-analysis JSON report and open a PR.
258
+
259
+ | Flag | Description |
260
+ | --- | --- |
261
+ | `--report <file>` | Path to praxis JSON report |
262
+ | `--severity <level>` | Minimum severity to fix |
263
+ | `--dry-run` | Preview without applying |
264
+ | `--yes` | Skip confirmation |
265
+
266
+ ### `fix rotate [path]`
267
+
268
+ Open provider dashboards to revoke exposed secrets.
269
+
270
+ | Flag | Description |
271
+ | --- | --- |
272
+ | `--provider <name>` | Only rotate secrets for a specific provider |
273
+ | `--plan <file>` | Execute a rotation plan |
274
+
275
+ ### `fix undo [path]`
276
+
277
+ Revert the last interactive fix (or all with `--all`).
278
+
279
+ | Flag | Description |
280
+ | --- | --- |
281
+ | `--all` | Revert every fix in the log |
282
+ | `--dry-run` | Show what would be reverted |
283
+
284
+ ### `fix env-template`
285
+
286
+ Generate a `.env.example` with placeholder values from found secrets.
287
+
288
+ | Flag | Description |
289
+ | --- | --- |
290
+ | `--dry-run` | Preview without writing |
291
+
292
+ ---
293
+
294
+ ## `praxis agents` — AI agent surface
295
+
296
+ ### `agents audit [path]` (default)
297
+
298
+ Audit AI agent configs (CLAUDE.md, .cursorrules, MCP servers, skills).
299
+
300
+ | Flag | Description |
301
+ | --- | --- |
302
+ | `--fix` | Auto-harden agent configurations |
303
+ | `--preflight` | Exit non-zero on critical findings (for CI) |
304
+ | `--red-team` | Simulate adversarial attacks against agent configs |
305
+ | `--json` | JSON output |
306
+
307
+ ### `agents skill [target]`
308
+
309
+ Vet an AI agent skill (URL or path) before installing it.
310
+
311
+ | Flag | Description |
312
+ | --- | --- |
313
+ | `--all` | Scan all skills defined in `openclaw.json` |
314
+ | `--json` | JSON output |
315
+
316
+ ### `agents mcp [target]`
317
+
318
+ Vet an MCP server's tool manifest before connecting, and optionally perform live protocol probing.
319
+
320
+ | Flag | Description |
321
+ | --- | --- |
322
+ | `--test-live` | Perform runtime JSON-RPC handshakes, tool enumeration, schema validation, and tool fuzzing |
323
+ | `--json` | JSON output |
324
+
325
+ ### `agents bom [path]`
326
+
327
+ Generate Agent Bill of Materials (CycloneDX ABOM).
328
+
329
+ | Flag | Description |
330
+ | --- | --- |
331
+ | `-o, --output <file>` | Output file path (default `abom.json`) |
332
+ | `--json` | Output to stdout as JSON |
333
+
334
+ ### `agents serve`
335
+
336
+ Start praxis as an MCP server (Claude Desktop, Cursor, Windsurf).
337
+
338
+ ### MCP trust registry
339
+
340
+ Every scan consults a bundled registry of known MCP servers
341
+ (`cli/data/known-mcps.json`, SHA-256 integrity-checked at load):
342
+
343
+ - **verified** (official reference servers, trust 90) and **community** (trust 50–70) packages pass silently.
344
+ - Anything else triggers `MCP_UNVERIFIED_SOURCE` (medium) — an unknown MCP server gains the agent's tools, credentials, and filesystem context.
345
+ - Typosquat detection (edit distance ≤ 3) covers the full registry, not just the official list.
346
+
347
+ Registry updates are quarterly + incident-driven; a tampered registry degrades gracefully (integrity check fails → unknown-tier lookups) instead of silently trusting anything.
348
+
349
+ ---
350
+
351
+ ## Governance absence-audits
352
+
353
+ Beyond finding what *is* there, Praxis detects what *isn't*:
354
+
355
+ | Rule | What it checks | Framing |
356
+ | --- | --- | --- |
357
+ | `NO_HUMAN_OVERSIGHT` (high) | High-blast-radius agent actions (financial/destructive tools, excessive agency) with **no approval-gate pattern** anywhere in the repo (`interrupt_before`, `requires_approval`, `human_in_the_loop`, ...) | EU AI Act Art. 14, ISO 42001 A.12.4 |
358
+ | `NO_OBSERVABILITY` (medium) | AI is in use but **no tracing wiring** exists outside dependency manifests (LangSmith, Langfuse, Helicone, OpenTelemetry, ... — a transitive dependency is not proof of wiring) | EU AI Act Art. 12, ISO 42001 A.6.2.6 |
359
+
360
+ Both run as post-processors on every full scan — no flags needed.
361
+
362
+ ---
363
+
364
+ ## `praxis intel` — threat intelligence
365
+
366
+ ### `intel update`
367
+
368
+ Refresh OSV, GHSA, KEV, EPSS, NVD, Gitleaks (+optional paid sources).
369
+
370
+ | Flag | Description |
371
+ | --- | --- |
372
+ | `--only <sources>` | Comma-separated subset (e.g. `osv,kev,epss`) |
373
+ | `--force` | Ignore per-source TTL caches |
374
+ | `--list` | Print available sources and exit |
375
+
376
+ ### `intel deps [path]`
377
+
378
+ Audit deps via package manager (npm/yarn/pnpm/pip-audit/bundler-audit).
379
+
380
+ | Flag | Description |
381
+ | --- | --- |
382
+ | `--fix` | Run package manager fix command after auditing |
383
+
384
+ ### `intel advisories [path]`
385
+
386
+ Check deps against live advisory feeds (OSV.dev, GitHub Advisories).
387
+
388
+ | Flag | Description |
389
+ | --- | --- |
390
+ | `--ecosystem <type>` | Filter by ecosystem (`npm`, `PyPI`) |
391
+ | `--json` | JSON output |
392
+
393
+ ---
394
+
395
+ ## `praxis report` — format/share results
396
+
397
+ ### `report team [file]`
398
+
399
+ Convert Hermes Agent team output into a Praxis report.
400
+
401
+ | Flag | Description |
402
+ | --- | --- |
403
+ | `--html [path]` | Save as HTML report |
404
+ | `--json` | JSON output |
405
+
406
+ ### `report legal [path]`
407
+
408
+ Legal risk audit: DMCA, leaked-source derivatives, IP disputes.
409
+
410
+ | Flag | Description |
411
+ | --- | --- |
412
+ | `--json` | JSON output |
413
+
414
+ ### `report checklist`
415
+
416
+ Run the launch-day security checklist interactively.
417
+
418
+ | Flag | Description |
419
+ | --- | --- |
420
+ | `--no-interactive` | Print checklist without prompts |
421
+
422
+ ### `report sbom [path]`
423
+
424
+ Generate Software Bill of Materials (CycloneDX SBOM).
425
+
426
+ | Flag | Description |
427
+ | --- | --- |
428
+ | `-o, --output <file>` | Output file path (default `sbom.json`) |
429
+
430
+ ### `report benchmark [path]`
431
+
432
+ Run the ground-truth benchmark harness to evaluate Praxis accuracy, false-positive resistance, precision, recall, and F1 score against curated positive and negative security fixtures.
433
+
434
+ | Flag | Description |
435
+ | --- | --- |
436
+ | `--json` | JSON output |
437
+ | `--verbose` | Show per-fixture detection details |
438
+
439
+ ---
440
+
441
+ ## `praxis project` — setup & state
442
+
443
+ ### `project init`
444
+
445
+ Initialize security configs in your project.
446
+
447
+ | Flag | Description |
448
+ | --- | --- |
449
+ | `-f, --force` | Overwrite existing files |
450
+ | `--gitignore` | Only copy `.gitignore` |
451
+ | `--headers` | Only copy security headers config |
452
+ | `--agents` | Only add security rules to AI agent instruction files |
453
+ | `--openclaw` | Generate a hardened `openclaw.json` template |
454
+ | `--hermes` | Bootstrap Hermes Agent security config |
455
+ | `--from <url>` | Fetch a pre-built Hermes config bundle from a setup URL |
456
+
457
+ ### `project doctor`
458
+
459
+ Diagnose environment: Node.js, git, API keys, cache, dependencies.
460
+
461
+ ### `project hooks [action]`
462
+
463
+ Manage Claude Code hooks — real-time security gate on tool calls.
464
+
465
+ ### `project guard [action]`
466
+
467
+ Install pre-commit/pre-push git hook to block secret commits.
468
+
469
+ | Flag | Description |
470
+ | --- | --- |
471
+ | `--pre-commit` | Install as pre-commit hook (instead of pre-push) |
472
+ | `--generate-hooks` | Generate defensive Claude Code hooks |
473
+
474
+ ### `project watch [path]`
475
+
476
+ Continuous monitoring: watch files for security issues in real-time.
477
+
478
+ | Flag | Description |
479
+ | --- | --- |
480
+ | `--poll` | Use polling mode |
481
+ | `--configs` | Watch only agent config files |
482
+ | `--deep` | Run full agent scanning on changes |
483
+ | `--stateful` | Keep Kimi K2.6 conversation context between scans |
484
+ | `--model <model>` | LLM model for stateful watch |
485
+ | `--provider <name>` | LLM provider for stateful watch |
486
+ | `--status` | Show current watch status and exit |
487
+ | `--threshold <score>` | Alert when score drops below threshold |
488
+ | `--debounce <ms>` | Debounce interval in ms |
489
+ | `--slack [webhook]` | Post findings to Slack webhook |
490
+ | `--pr-comment` | Post inline findings as GitHub PR review comments |
491
+
492
+ ### `project baseline [path]`
493
+
494
+ Create/manage a findings baseline — only report new findings.
495
+
496
+ | Flag | Description |
497
+ | --- | --- |
498
+ | `--diff` | Show what changed since baseline |
499
+ | `--clear` | Remove the baseline |
500
+
501
+ ### `project memory [subcommand]`
502
+
503
+ Manage false-positive memory. Subcommands: `list`, `forget <key>`, `clear`.
504
+
505
+ ### `project playbook [subcommand]`
506
+
507
+ Manage repo-specific LLM context playbook. Subcommands: `show`, `add-note "text"`.
508
+
509
+ ### `project plugins [action]`
510
+
511
+ Manage custom security agent plugins from `.praxis/agents/`. Action `new <name>` scaffolds a new plugin.
512
+
513
+ ### `project policy <action>`
514
+
515
+ Manage security policies. Action `init` creates a `.praxis.policy.json` template.
516
+
517
+ ---
518
+
519
+ ## `praxis rules` — portable rule inventory
520
+
521
+ Inspect Praxis's detection rules and export them in a form other tools can read.
522
+ The rules are data, not lock-in.
523
+
524
+ ### `rules list`
525
+
526
+ Summarise the inventory by source, severity and portability.
527
+
528
+ ```bash
529
+ praxis rules list
530
+ praxis rules list --json
531
+ ```
532
+
533
+ Reports how many rules are exportable and validated, the severity mix, and which
534
+ sources contribute. Also names the layers that have **no** portable equivalent (see below).
535
+
536
+ ### `rules export`
537
+
538
+ Write a portable bundle. Three files:
539
+
540
+ | File | Purpose |
541
+ | --- | --- |
542
+ | `praxis-rules.yaml` | Semgrep-compatible, using `pattern-regex` (PCRE2) |
543
+ | `praxis-rules.json` | Canonical format, re-importable by Praxis |
544
+ | `praxis-rules.manifest.json` | What is portable, what is Praxis-only, and why |
545
+
546
+ ```bash
547
+ praxis rules export -o ./rules
548
+ semgrep --config ./rules/praxis-rules.yaml .
549
+ ```
550
+
551
+ Every pattern is validated before the bundle is written, and the export **refuses to
552
+ write** if any pattern is malformed — a partially broken bundle would fail inside
553
+ someone else's Semgrep with no useful context. Patterns that are valid PCRE2 but have no
554
+ JavaScript equivalent (atomic groups, POSIX classes) are reported as *unverifiable* rather
555
+ than silently passed off as checked.
556
+
557
+ Rule **ids are identifiers** (`AWS_ACCESS_KEY_ID`, not `AWS Access Key ID`), because
558
+ Semgrep suppressions (`# nosemgrep:`) and baselining key on them.
559
+
560
+ **Scope — what the export does not cover.** 411 of the rules are static patterns. Three
561
+ layers have no Semgrep representation and are declared in the manifest rather than
562
+ approximated:
563
+
564
+ | Layer | Why it is Praxis-only |
565
+ | --- | --- |
566
+ | AST / taint dataflow | "User input reaches this sink" is not a pattern |
567
+ | Prompt-injection probe corpus | Versioned data with its own compiler and ReDoS guard |
568
+ | Entropy-checked secrets (10 rules) | A runtime Shannon-entropy heuristic over the match |
569
+ | LLM deep analysis (`--deep`) | Runtime exploitability verdicts |
570
+
571
+ ### `rules import <bundle>`
572
+
573
+ Load a portable bundle and optionally emit a runnable plugin.
574
+
575
+ ```bash
576
+ # Preview: what would be accepted or rejected, and why
577
+ praxis rules import ./rules/praxis-rules.json
578
+
579
+ # Emit a plugin that participates in real scans
580
+ praxis rules import ./rules/praxis-rules.json --write-plugin .praxis/agents
581
+ ```
582
+
583
+ Import accepts **pattern rules only**. Anything it cannot execute as a static pattern is
584
+ **rejected with a stated reason**, never imported in a degraded form.
585
+
586
+ The canonical round-trip format is the JSON, not the YAML: Praxis has no YAML runtime
587
+ dependency, and adding one for this would not be worth it. Handing it the Semgrep YAML
588
+ produces an explanation rather than a silent failure.
589
+
590
+ | Flag | Description |
591
+ | --- | --- |
592
+ | `--write-plugin <dir>` | Write a runnable plugin (e.g. `.praxis/agents`) |
593
+ | `--name <name>` | Plugin class name prefix |
594
+ | `--json` | Machine-readable output |
595
+
596
+ ---
597
+
598
+ ## `praxis web` — local web UI
599
+
600
+ A browser front-end for running scans and managing scan projects: register projects, run
601
+ single or concurrent scans, watch live progress over SSE, and browse findings.
602
+
603
+ **Read-only by design.** It orchestrates scans and shows results; it deliberately does
604
+ **not** expose fix application. See [`docs/design/WEB-UI.md`](design/WEB-UI.md) for the
605
+ full threat model.
606
+
607
+ ```bash
608
+ praxis web # http://127.0.0.1:7317
609
+ praxis web --port 8080
610
+ ```
611
+
612
+ | Flag | Default | Description |
613
+ | --- | --- | --- |
614
+ | `--port <port>` | `7317` | Port to listen on |
615
+ | `--host <host>` | `127.0.0.1` | Host to bind |
616
+ | `--allow-remote` | off | Permit a non-loopback bind (requires `--token`) |
617
+ | `--token <token>` | — | Bearer token required for every request when remotely bound |
618
+
619
+ ### Security model
620
+
621
+ - **Loopback-only by default.** A non-loopback bind is refused unless *both*
622
+ `--allow-remote` and a `--token` of at least 16 characters are supplied.
623
+ - **The browser never sends a filesystem path.** Projects are registered by the operator,
624
+ resolved and pinned server-side, then addressed only by **id** — so no request can ask
625
+ the server to scan `/` or a home directory.
626
+ - **Anti-CSRF.** Mutating requests must carry a header a cross-origin form cannot set,
627
+ plus a same-origin `Origin` (defends against DNS rebinding).
628
+ - **Nothing is served from disk.** The frontend is generated in memory from the shared
629
+ theme, so there is no static-file path to traverse.
630
+ - **Bounded work.** Concurrency, queue depth and request body size are all capped.
631
+ - Loopback-only is a safe default, **not** a boundary against an attacker already on the
632
+ machine. There is no authentication, multi-user or tenancy support.
633
+
634
+ ---
635
+
636
+ ## Top-level shortcuts
637
+
638
+ ### `praxis vibe [path]`
639
+
640
+ Vibe-graded security score with emoji and shareable badge.
641
+
642
+ | Flag | Description |
643
+ | --- | --- |
644
+ | `--badge` | Generate a shields.io markdown badge |
645
+
646
+ ### `praxis score [path]`
647
+
648
+ Compute a 0–100 security health score.
649
+
650
+ | Flag | Description |
651
+ | --- | --- |
652
+ | `--no-deps` | Skip dependency audit |
653
+
654
+ ### `praxis` (no args)
655
+
656
+ - On a TTY → drops into the interactive REPL.
657
+ - Otherwise → prints quick-start help.
658
+
659
+ ### Legacy top-level aliases
660
+
661
+ Praxis was reorganized into verb-led groups. The original flat commands still work as
662
+ aliases, so existing scripts and CI configs keep running. **Prefer the grouped form** in
663
+ new work — the aliases are maintained for compatibility, not as the primary interface.
664
+
665
+ | Alias | Use instead |
666
+ | --- | --- |
667
+ | `praxis ci` | `praxis scan ci` |
668
+ | `praxis audit` · `praxis openclaw` | `praxis agents audit` |
669
+ | `praxis scan-mcp` | `praxis agents mcp` |
670
+ | `praxis scan-skill` | `praxis agents skill` |
671
+ | `praxis abom` | `praxis agents bom` |
672
+ | `praxis mcp` | `praxis agents serve` |
673
+ | `praxis scan-standard` | `praxis scan standard` |
674
+ | `praxis red-team` | `praxis scan redteam` |
675
+ | `praxis update-intel` | `praxis intel update` |
676
+ | `praxis deps` | `praxis intel deps` |
677
+ | `praxis advisories` | `praxis intel advisories` |
678
+ | `praxis remediate` | `praxis fix quick` |
679
+ | `praxis rotate` | `praxis fix rotate` |
680
+ | `praxis undo` | `praxis fix undo` |
681
+ | `praxis env-template` | `praxis fix env-template` |
682
+ | `praxis legal` | `praxis report legal` |
683
+ | `praxis team` | `praxis report team` |
684
+ | `praxis checklist` | `praxis report checklist` |
685
+ | `praxis benchmark` | `praxis report benchmark` |
686
+ | `praxis init` | `praxis project init` |
687
+ | `praxis doctor` | `praxis project doctor` |
688
+ | `praxis baseline` | `praxis project baseline` |
689
+ | `praxis guard` | `praxis project guard` |
690
+ | `praxis watch` | `praxis project watch` |
691
+ | `praxis shell` | `praxis` (no args, on a TTY) |
692
+
693
+ Note: `vibe`, `score` and the no-argument REPL are **not** aliases — they are distinct
694
+ top-level commands.
695
+
696
+ ---
697
+
698
+ ## AI security standards alignment
699
+
700
+ Every finding is auto-tagged with all applicable AI-security standards. Reports
701
+ include a per-standard coverage summary with a **3-state coverage map**:
702
+
703
+ | State | Meaning |
704
+ | --- | --- |
705
+ | **Flagged** | This scan produced evidence for that control |
706
+ | **No evidence in this scan** | The tool can detect it; this repo showed nothing — *not proof of safety* |
707
+ | **No detection rule** | Praxis has no code-level check for this control (e.g. registration duties, fundamental-rights impact assessments) — an honest tool-gap marker |
708
+
709
+ MITRE ATLAS findings are enriched from the vendored official knowledge
710
+ snapshot (2026-04): every flagged `AML.T####` technique renders its tactic,
711
+ recommended mitigations (`AML.M####`), and real-world case studies
712
+ (`AML.CS####`). The snapshot date is shown in reports.
713
+
714
+ | Standard | Module name | Controls |
715
+ | --- | --- | --- |
716
+ | OWASP Top 10 for LLM Applications (2025) | `owasp-llm` | LLM01–LLM10 |
717
+ | MITRE ATLAS (2026-04 snapshot) | `mitre-atlas` | AML.T0010, T0018, T0024, T0034, T0040, T0043, T0048, T0051, T0053, T0054, T0057, T0070 |
718
+ | NIST AI 600-1 (Generative AI Profile) | `nist-ai-600-1` | GV/MP/MS/MG actions tagged `-GAI` |
719
+ | AVID — AI Vulnerability Database taxonomy | `avid` | S0100, S0200, S0301, S0400, S0500, P0201, P0204, P0301, E0101 |
720
+ | OWASP ML Security Top 10 | `owasp-ml` | ML01–ML10 |
721
+ | EU AI Act (Regulation 2024/1689) | `eu-ai-act` | Articles 5, 9–15, 17, 25–27, 49, 50, 53, 55, 72, 73 (18 controls) |
722
+ | ISO/IEC 42001 (AI Management System) | `iso-42001` | A.5–A.13 Annex outline (21 controls) |
723
+ | Google Secure AI Framework (SAIF) | `google-saif` | SAIF-1 through SAIF-6 |
724
+
725
+ ```bash
726
+ # List all standards
727
+ praxis scan standard --list
728
+
729
+ # Filter to a single standard
730
+ praxis scan standard owasp-llm .
731
+
732
+ # Filter to a single control within a standard
733
+ praxis scan standard owasp-llm . --control LLM01
734
+
735
+ # Programmatic JSON for tooling (mitre-atlas includes the enrichment block)
736
+ praxis scan standard mitre-atlas . --json
737
+
738
+ # Audit-ready compliance export (GRC report)
739
+ praxis scan standard nist-ai-600-1 . --format compliance
740
+ ```
741
+
742
+ In the JSON / SARIF / HTML reports:
743
+ - Each finding carries `standards: { 'owasp-llm': ['LLM01'], ... }`.
744
+ - The top-level `standardsSummary` shows per-standard coverage (e.g. `4/10`) with per-control `status` and `detectable` flags.
745
+ - `mitre-atlas` JSON reports include an `atlas` block hydrating flagged techniques with tactics, mitigations, and case studies.
746
+ - SARIF embeds standards as `result.properties.standards` plus a flat `tags`
747
+ array — GitHub Code Scanning will display them as labels.
748
+ - HTML reports render a "Standards Compliance" section with the 3-state coverage map and a reading legend.
749
+
750
+ **Adding a new standard**: drop a module under
751
+ `cli/utils/standards/sources/<name>.js` exporting `name`, `version`, `title`,
752
+ `description`, `url`, `controls`, and `mapFinding(finding)`; register it in
753
+ `ALL_STANDARDS` in `cli/utils/standards/index.js`. No other changes needed.
754
+ Mark controls with `detectable: false` when no `mapFinding` path can ever
755
+ produce them, so reports can distinguish tool gaps from absent evidence.
756
+
757
+ ---
758
+
759
+ ## AST & CST Dataflow Analysis Engine
760
+
761
+ Praxis incorporates a pure ESM, zero-native-dependency AST & CST analysis engine (`cli/core/ast/`):
762
+
763
+ - **JS/TS Parsing**: Babel parser based AST engine providing complete syntax trees for modern JavaScript, TypeScript, JSX, and TSX.
764
+ - **Python Parsing**: CST tokenizer and indentation block tree parser providing function scope and statement hierarchy without requiring Python runtime dependencies.
765
+ - **Lexical Scope Resolution (`scope-tree.js`)**: Tracks variable declarations, parameter bindings, enclosing function contexts, and variable shadowing.
766
+ - **Intra-File Source-to-Sink Taint Tracking (`taint-tracker.js`)**: Tracks untrusted user inputs (`req.body`, `req.query`, `process.env`, `input()`, `request.args`) as they propagate across variable assignments, template strings, and function calls into dangerous sinks (`eval`, `exec`, `spawn`, `child_process`, SQL queries, filesystem writes).
767
+ - **AI Guardrail Detection (`guardrail-detector.js`)**: Identifies input/output defense wrappers (NeMo Guardrails, Llama Guard, Guardrails AI, LangKit, custom validator functions) and suppresses false positives when inputs are provably sanitized.
768
+ - **Tier 0 Syntax Verification**: Integrates with the LLM remediation ladder to immediately reject syntactically broken patches before running heavier test suites.
769
+
770
+ ---
771
+
772
+ ## Environment variables
773
+
774
+ ### LLM providers (auto-detected by `--deep`, `fix`, `watch --stateful`)
775
+
776
+ | Variable | Purpose |
777
+ | --- | --- |
778
+ | `ANTHROPIC_API_KEY` | Claude (Opus / Sonnet / Haiku) |
779
+ | `OPENAI_API_KEY` | OpenAI (GPT-4 / GPT-4o / o1) |
780
+ | `GOOGLE_AI_API_KEY` | Gemini |
781
+ | `MOONSHOT_API_KEY` | Kimi |
782
+ | `OPENAI_BASE_URL` | Custom OpenAI-compatible endpoint (OpenRouter, Groq, DeepSeek, LM Studio, vLLM, ...) |
783
+ | `PRAXIS_LLM_MODEL` | Default model when no `--model` flag is given |
784
+ | `PRAXIS_LLM_REASONING` | `low`/`medium`/`high` — enables extended thinking (reasoning_effort) |
785
+
786
+ `--local` uses Ollama; no key needed.
787
+
788
+ ### `.env` loading
789
+
790
+ Praxis loads a `.env` file from your **working directory** at startup
791
+ (`.env.example` in the repo is the documented template; `.env` is gitignored).
792
+ Real environment variables always win over `.env`; CLI flags
793
+ (`--provider`, `--model`, `--base-url`) win over both. `OPENAI_BASE_URL`
794
+ applies only to OpenAI-shaped providers (never anthropic/google/ollama).
795
+
796
+ ```bash
797
+ # .env — cloud LLM features without any flags
798
+ OPENAI_API_KEY=sk-...
799
+ OPENAI_BASE_URL=https://your-gateway.example/v1/chat/completions
800
+ PRAXIS_LLM_MODEL=your-model-name
801
+ PRAXIS_LLM_REASONING=high
802
+
803
+ praxis project doctor # connectivity check ("custom LLM responding successfully")
804
+ praxis scan full . --deep # LLM taint analysis, no flags needed
805
+ praxis fix interactive . # LLM remediation planning
806
+ ```
807
+
808
+ Run Praxis from the directory that holds your `.env` (the config is the
809
+ operator's, not the target's).
810
+
811
+ ### Threat intelligence (raise rate limits)
812
+
813
+ | Variable | Purpose |
814
+ | --- | --- |
815
+ | `GITHUB_TOKEN` / `GH_TOKEN` | GHSA — raises GitHub rate limit |
816
+ | `NVD_API_KEY` | NVD — drops 6s wait between requests to 600ms |
817
+
818
+ ### Optional paid intel sources
819
+
820
+ | Variable | Source |
821
+ | --- | --- |
822
+ | `SNYK_TOKEN` (+ `SNYK_ORG_ID`) | Snyk Vulnerability DB |
823
+ | `SOCKET_API_KEY` | Socket.dev supply-chain risk |
824
+ | `GITGUARDIAN_API_KEY` | GitGuardian secret detector definitions |
825
+ | `SONATYPE_USER` + `SONATYPE_TOKEN` | OSS Index (works anonymously too) |
826
+ | `PHYLUM_API_KEY` | Phylum supply-chain risk |
827
+
828
+ None are required. The seven core intel sources — OSV, GHSA, KEV, EPSS, NVD, Gitleaks and
829
+ the bundled AI threatpack — plus pattern-based scanning all work with zero config.
830
+
831
+ ### State location override (used by tests)
832
+
833
+ | Variable | Purpose |
834
+ | --- | --- |
835
+ | `HOME` (Unix) / `USERPROFILE` (Windows) | Relocates `~/.praxis/` |
836
+
837
+ ---
838
+
839
+ ## Configuration files
840
+
841
+ ### `.praxisignore`
842
+
843
+ Per-line ignore patterns (gitignore-style) applied during file discovery.
844
+
845
+ ```
846
+ # Skip vendored code
847
+ vendor/
848
+ third_party/
849
+ # Skip generated dirs
850
+ **/dist/**
851
+ ```
852
+
853
+ ### Inline suppression
854
+
855
+ Add `praxis-ignore` (optionally followed by a rule name) on the same line as
856
+ the finding:
857
+
858
+ ```js
859
+ const fakeKey = "sk_test_dummy"; // praxis-ignore stripe-secret
860
+ ```
861
+
862
+ ### `.praxis.policy.json`
863
+
864
+ Project-level policy: severity floors, allowed CWEs, agent enable/disable,
865
+ suppression rules. Generate a template with:
866
+
867
+ ```bash
868
+ praxis project policy init
869
+ ```
870
+
871
+ ### `.praxis/agents/*.js`
872
+
873
+ Custom agent plugins, auto-discovered when running scans from a project
874
+ that contains them. Scaffold one with:
875
+
876
+ ```bash
877
+ praxis project plugins new my-rule
878
+ ```
879
+
880
+ A plugin is any module exporting a class extending `BaseAgent`:
881
+
882
+ ```js
883
+ import { BaseAgent, createFinding } from 'praxis';
884
+
885
+ export default class MyAgent extends BaseAgent {
886
+ constructor() { super('MyAgent', 'description', 'category'); }
887
+ async analyze(context) {
888
+ const findings = [];
889
+ // ...
890
+ return findings;
891
+ }
892
+ }
893
+ ```
894
+
895
+ ### `.praxis/baseline.json`
896
+
897
+ Snapshot of "known" findings. Created by `praxis project baseline .`. After
898
+ that, `--baseline` only surfaces new findings.
899
+
900
+ ### `.praxis/history.json`
901
+
902
+ Trend tracking — last 100 score snapshots. Drives the `Trend` line in scan
903
+ output.
904
+
905
+ ### `~/.praxis/threat-intel.json`
906
+
907
+ Merged threat-intel feed. Populated by `praxis intel update`. Falls back to
908
+ the bundled seed at `cli/data/threat-intel.json` when missing.
909
+
910
+ ---
911
+
912
+ ## Output formats
913
+
914
+ The output formatter registry lives in `cli/core/output/`. Built-in formats:
915
+
916
+ | Format | Flag | Notes |
917
+ | --- | --- | --- |
918
+ | `json` | `--json` | `schemaVersion: 3`, `findings[]`, `standardsSummary`, `compliance`, `agenticSummary`, and a `fingerprint` block (see below) |
919
+ | `sarif` | `--sarif [file]` | SARIF 2.1.0 with **`security-severity`** (critical 9.5 / high 7.5 / medium 5.0 / low 2.5) so GitHub Code Scanning ranks alerts correctly; `result.properties.standards` + flat `tags` |
920
+ | `html` | `--html [file]` | **Professional assessment report** — tabbed single-file report: Overview (KPIs, severity distribution, category breakdown, discovered attack surface, OWASP ASI agentic-risk coverage, score trend), **Agent Coverage**, Findings & AST Dataflow (per-finding rule IDs, severity filter, search, evidence + dataflow panels, LLM verdicts), Standards Matrix, Agent BOM (ABOM), Remediation Plan + **Remediation Ledger** |
921
+ | `pdf` | `--pdf [file]` | Print-rendered PDF (requires Chrome/Chromium) |
922
+ | `csv` | `--csv` | Tabular |
923
+ | `md` | `--md` | Markdown |
924
+
925
+ Add a new format by writing `cli/core/output/<name>.js` exporting
926
+ `default function(report, options): string` and registering it in `REGISTRY`
927
+ in `cli/core/output/index.js`.
928
+
929
+ All HTML surfaces share one theme in `cli/core/output/html-theme.js`, so severity colours,
930
+ badges, tables and escaping stay consistent across reports. Values interpolated into
931
+ report markup are escaped centrally, and severities are mapped through a sanitiser that
932
+ only ever emits a known class name.
933
+
934
+ **Scan fingerprint.** JSON output carries a `fingerprint` block, and every HTML report
935
+ prints a provenance line in its footer:
936
+
937
+ ```
938
+ praxis 1.0.0 · node v24.14.1 · probes v1.1(23) · threatpack v1.1(3) · eaa v0.1.0 · files 197
939
+ ```
940
+
941
+ It records the tool version, the runtime, and the version of every vendored data asset
942
+ that can change detection behaviour. A surprising result should be *attributable* rather
943
+ than mysterious.
944
+
945
+ **Secret redaction invariant:** secret-category findings never expose their
946
+ raw matched value in any report output — `matched` is redacted centrally
947
+ (`sk-***`) in the output renderers, and SARIF carries no matched values.
948
+
949
+ ---
950
+
951
+ ## Threat packs (AI attack-vector signatures)
952
+
953
+ New AI attack-vector signatures arrive as **data**, not code. `intel update`
954
+ fetches a versioned threat pack (`cli/data/threatpacks/latest.json` is the
955
+ bundled seed; `PRAXIS_THREATPACK_URL` overrides the remote source):
956
+
957
+ ```bash
958
+ # Fetch/refresh the AI threat pack (probe signatures + registry updates)
959
+ praxis intel update --only threatpack
960
+
961
+ # Pack version + probe count visible in the feed
962
+ # ~/.praxis/threat-intel.json → threatPack
963
+ ```
964
+
965
+ When a pack contains new prompt-injection probe signatures, the
966
+ PromptInjectionProber overlays them onto its bundled corpus automatically
967
+ (bundled + pack = total active probes; the ReDoS guard still applies at
968
+ compile). This is the mechanism that keeps Praxis current on new attack
969
+ families (jailbreak variants, obfuscation tricks, dataset/eval vectors)
970
+ between releases.
971
+
972
+ ---
973
+
974
+ ## CI/CD integration
975
+
976
+ ### GitHub Action (composite)
977
+
978
+ The repo ships an `action.yml` (composite action) that runs `praxis ci` and
979
+ uploads SARIF.
980
+
981
+ ```yaml
982
+ - uses: ./
983
+ with:
984
+ path: .
985
+ threshold: '80'
986
+ deep: 'false'
987
+ deps: 'true'
988
+ sarif: 'true'
989
+ comment: 'true'
990
+ # PR regression gating — scan the base ref and fail only on NEW findings
991
+ net-new: 'true'
992
+ fail-on-new: 'high'
993
+ # severity floor a baseline can't suppress
994
+ always-fail-on: 'critical'
995
+ env:
996
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
997
+ ```
998
+
999
+ Outputs: `score`, `grade`, `findings`, `secrets`, `vulns`, `cves`, `sarif-file`.
1000
+
1001
+ **Net-new PR gating** (`net-new: true`, pull-request events only): the action
1002
+ checks out the PR base into a worktree, scans it, and diffs finding identities
1003
+ (`file:rule`) against the head scan. Only findings *introduced by the PR* can
1004
+ fail the build, at or above `fail-on-new`. Pre-existing debt never blocks.
1005
+
1006
+ ### Plain GitHub Actions
1007
+
1008
+ ```yaml
1009
+ permissions:
1010
+ security-events: write # required for SARIF upload
1011
+ steps:
1012
+ - run: npm install -g praxis-sec@latest
1013
+ - run: praxis ci . --threshold 80 --sarif results.sarif --strict-intel
1014
+ - uses: github/codeql-action/upload-sarif@v4
1015
+ with: { sarif_file: results.sarif }
1016
+ ```
1017
+
1018
+ `security-events: write` is required — without it the upload fails with a 403 even though
1019
+ the scan itself succeeded.
1020
+
1021
+ ### Using the action from another repository
1022
+
1023
+ Once the action is listed on the GitHub Marketplace and a `v1` release tag exists:
1024
+
1025
+ ```yaml
1026
+ permissions:
1027
+ security-events: write
1028
+ steps:
1029
+ - uses: Ganron007/Praxis@v1
1030
+ with:
1031
+ net-new: 'true'
1032
+ fail-on-new: 'high'
1033
+ ```
1034
+
1035
+ Inside this repository `- uses: ./` works immediately and needs no publishing step.
1036
+
1037
+ ### Determinism gate
1038
+
1039
+ A scan's findings should be identical across runs on identical inputs. `check-determinism`
1040
+ enforces that by comparing finding identities (`file::rule`) between two runs, so a
1041
+ detection change cannot land unnoticed:
1042
+
1043
+ ```bash
1044
+ node scripts/check-determinism.mjs .
1045
+ ```
1046
+
1047
+ CI runs this as its own job. A failure means the rule set, the probe corpus or the
1048
+ threatpack changed behaviour — which is sometimes intended (a version bump should change
1049
+ results), so the gate exists to make the change *deliberate* and visible in the diff
1050
+ rather than silent.
1051
+
1052
+ ---
1053
+
1054
+ ### Pre-commit hook
1055
+
1056
+ ```bash
1057
+ praxis project guard install --pre-commit
1058
+ ```
1059
+
1060
+ ### Agentic loop (auto-fix until score target)
1061
+
1062
+ ```bash
1063
+ praxis fix . --severity high --branch praxis/fixes --pr
1064
+ # review, then if needed:
1065
+ praxis fix undo --all
1066
+ ```
1067
+
1068
+ ---
1069
+
1070
+ ## Custom plugins
1071
+
1072
+ Praxis discovers plugins from `.praxis/agents/` automatically when scans run
1073
+ from that project root. The discovery uses `buildOrchestratorAsync(rootPath)` —
1074
+ the synchronous `buildOrchestrator()` skips plugin loading.
1075
+
1076
+ A plugin extends `BaseAgent` and follows the standard contract:
1077
+
1078
+ ```js
1079
+ import { BaseAgent, createFinding } from 'praxis';
1080
+
1081
+ export default class HardcodedAdminCheck extends BaseAgent {
1082
+ constructor() {
1083
+ super(
1084
+ 'HardcodedAdminCheck',
1085
+ 'Detects hardcoded admin credentials',
1086
+ 'auth' // category — feeds into ScoringEngine
1087
+ );
1088
+ }
1089
+
1090
+ shouldRun(recon) {
1091
+ return recon.languages?.has('javascript') || recon.languages?.has('typescript');
1092
+ }
1093
+
1094
+ async analyze(context) {
1095
+ const files = this.getFilesToScan(context);
1096
+ const findings = [];
1097
+ for (const file of files) {
1098
+ // Use scanFileWithPatterns or your own logic
1099
+ findings.push(...this.scanFileWithPatterns(file, [
1100
+ {
1101
+ rule: 'hardcoded-admin',
1102
+ title: 'Hardcoded admin credential',
1103
+ regex: /admin\s*:\s*['"](password|admin)['"]/gi,
1104
+ severity: 'critical',
1105
+ cwe: 'CWE-798',
1106
+ owasp: 'A07:2021',
1107
+ description: 'Admin credential hardcoded in source.',
1108
+ fix: 'Move to environment variables.',
1109
+ },
1110
+ ]));
1111
+ }
1112
+ return findings;
1113
+ }
1114
+ }
1115
+ ```
1116
+
1117
+ The standards registry will auto-tag these findings during scoring — no
1118
+ plugin-side wiring required.
1119
+
1120
+ ---
1121
+
1122
+ ## Troubleshooting
1123
+
1124
+ | Symptom | Cause / fix |
1125
+ | --- | --- |
1126
+ | `praxis intel update` is slow | NVD rate-limits to 6s/request without a key. Set `NVD_API_KEY`. |
1127
+ | `praxis scan ci --strict-intel` fails locally | Run `praxis intel update` first. Default freshness window is `7d`. |
1128
+ | Custom plugins not loading | Make sure you're running through `buildOrchestratorAsync(rootPath)` — the default `praxis scan` does this; programmatic API callers using `buildOrchestrator()` won't get plugins. |
1129
+ | `node cli/bin/praxis.js` works but `praxis` doesn't | Run `npm link` once (or `npm install -g .` from the repo). |
1130
+ | Test files report secrets | Confidence is auto-downgraded in test/doc/example paths — but use `praxis-ignore` for explicit suppression. |
1131
+ | Feed lives somewhere else | Override `HOME` (Unix) or `USERPROFILE` (Windows) — used by the test suite. |
1132
+ | Standards summary shows `0/X` everywhere | The standards registry maps via `cwe`/`owasp`/`category` on findings. If you've written a custom agent that doesn't set these, populate them in `createFinding({...})`. |
1133
+ | `rules export` refuses to write | A pattern failed validation. The message names the rule and the error — the bundle is not written rather than shipping broken YAML. Fix the pattern, or pass `--allow-invalid` if you understand the risk. |
1134
+ | `rules import` rejects a bundle | Only static pattern rules are importable. The rejection reason is printed per rule; AST/taint, probe-corpus and entropy rules cannot be expressed as a pattern. |
1135
+ | `rules import` says "YAML is an export format" | Import the sibling `praxis-rules.json`. Praxis has no YAML runtime dependency, so YAML is export-only. |
1136
+ | `praxis web` refuses to start on a non-loopback host | Remote bind requires **both** `--allow-remote` and `--token` of at least 16 characters. This is deliberate. |
1137
+ | `praxis web` won't load a project path | Projects are registered by the operator and addressed by **id**. The API intentionally does not accept client-supplied paths. |
1138
+ | Determinism gate fails in CI | Two scans of identical inputs disagreed on `file::rule`. Usually a probe-corpus or threatpack change — check `git diff` on `cli/data/`. Expected when you intentionally change detection. |
1139
+
1140
+ ---
1141
+
1142
+ ## `praxis mcp` — MCP server mode
1143
+
1144
+ Exposes Praxis as a Model Context Protocol (MCP) server over stdio (JSON-RPC
1145
+ 2.0). This lets IDEs (Cursor, Continue, VS Code) call Praxis tools directly
1146
+ from chat — real-time vulnerability feedback without leaving the editor.
1147
+
1148
+ ### Quick start
1149
+
1150
+ ```bash
1151
+ npx praxis-sec mcp
1152
+ # → Praxis MCP server listening on stdio (JSON-RPC 2.0)
1153
+ ```
1154
+
1155
+ ### IDE integration
1156
+
1157
+ Cursor / Continue config (`.continue/config.yaml` or Cursor MCP settings):
1158
+
1159
+ ```yaml
1160
+ mcpServers:
1161
+ - name: praxis
1162
+ transport: stdio
1163
+ command: npx
1164
+ args: ["praxis", "mcp"]
1165
+ ```
1166
+
1167
+ In Docker (a container running praxis):
1168
+
1169
+ ```yaml
1170
+ mcpServers:
1171
+ - name: praxis
1172
+ transport: stdio
1173
+ command: docker
1174
+ args: ["exec", "-i", "darkai-ops", "praxis", "mcp"]
1175
+ ```
1176
+
1177
+ ### Available MCP tools
1178
+
1179
+ | Tool | Input | Returns | Description |
1180
+ |------|-------|---------|-------------|
1181
+ | `scan_secrets` | `{ path }` | findings[] | Scan a file/directory for hardcoded secrets |
1182
+ | `scan_repo` | `{ path, deep? }` | findings[] + score | Full orchestrator scan (all 28 agents + intel) |
1183
+ | `analyze_file` | `{ path }` | findings[] | Deep LLM analysis of a single file |
1184
+ | `get_findings` | `{ severity? }` | findings[] | Retrieve cached findings (optionally filtered) |
1185
+ | `get_checklist` | — | checklist[] | Launch-day security checklist items |
1186
+ | `suppress_finding` | `{ id, reason }` | `{ ok }` | Suppress a finding (writes to `.praxis/ignores.json`) |
1187
+
1188
+ ### Example MCP interaction
1189
+
1190
+ When connected, an IDE user can ask: *"Scan this file for AI vulnerabilities"*
1191
+ and the LLM calls `scan_repo` — Praxis findings appear inline in the chat with
1192
+ file:line references. The `deep` flag triggers LLM-powered taint analysis.
1193
+
1194
+ ---
1195
+
1196
+ ## Get help
1197
+
1198
+ ```bash
1199
+ praxis --help # all groups
1200
+ praxis <group> --help # subcommands for a group
1201
+ praxis <group> <cmd> --help # flags for a specific command
1202
+ ```
1203
+
1204
+ Report Praxis bugs or feature requests via the project's issue tracker on the
1205
+ Praxis GitHub repository.