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.
- package/LICENSE +21 -0
- package/README.md +170 -0
- package/ai-defense/cost-protection.md +292 -0
- package/ai-defense/llm-security-checklist.md +324 -0
- package/ai-defense/prompt-injection-patterns.js +283 -0
- package/ai-defense/system-prompt-armor.md +327 -0
- package/checklists/launch-day.md +168 -0
- package/cli/agents/abom-generator.js +225 -0
- package/cli/agents/agent-attestation-agent.js +318 -0
- package/cli/agents/agent-config-scanner.js +787 -0
- package/cli/agents/agent-telemetry-agent.js +415 -0
- package/cli/agents/agentic-security-agent.js +296 -0
- package/cli/agents/agentic-supply-chain-agent.js +463 -0
- package/cli/agents/ai-infra-inventory-agent.js +449 -0
- package/cli/agents/api-fuzzer.js +345 -0
- package/cli/agents/auth-bypass-agent.js +348 -0
- package/cli/agents/base-agent.js +280 -0
- package/cli/agents/cicd-scanner.js +300 -0
- package/cli/agents/config-auditor.js +757 -0
- package/cli/agents/deep-analyzer.js +776 -0
- package/cli/agents/endpoint-agent-abuse-agent.js +404 -0
- package/cli/agents/exception-handler-agent.js +187 -0
- package/cli/agents/git-history-scanner.js +169 -0
- package/cli/agents/governance-audits.js +138 -0
- package/cli/agents/hermes-security-agent.js +536 -0
- package/cli/agents/html-reporter.js +1125 -0
- package/cli/agents/index.js +147 -0
- package/cli/agents/injection-tester.js +502 -0
- package/cli/agents/legal-risk-agent.js +328 -0
- package/cli/agents/llm-redteam.js +199 -0
- package/cli/agents/managed-agent-scanner.js +333 -0
- package/cli/agents/mcp-security-agent.js +588 -0
- package/cli/agents/memory-poisoning-agent.js +305 -0
- package/cli/agents/mobile-scanner.js +231 -0
- package/cli/agents/model-file-scanner.js +259 -0
- package/cli/agents/orchestrator.js +355 -0
- package/cli/agents/pii-compliance-agent.js +301 -0
- package/cli/agents/policy-engine.js +229 -0
- package/cli/agents/prompt-injection-prober.js +224 -0
- package/cli/agents/rag-security-agent.js +204 -0
- package/cli/agents/recon-agent.js +207 -0
- package/cli/agents/sbom-generator.js +265 -0
- package/cli/agents/scoring-engine.js +273 -0
- package/cli/agents/ssrf-prober.js +130 -0
- package/cli/agents/stateful-watcher.js +238 -0
- package/cli/agents/supabase-rls-agent.js +154 -0
- package/cli/agents/supply-chain-agent.js +857 -0
- package/cli/agents/swarm-orchestrator.js +200 -0
- package/cli/agents/verifier-agent.js +303 -0
- package/cli/agents/vibe-coding-agent.js +250 -0
- package/cli/bin/praxis.js +866 -0
- package/cli/commands/abom.js +73 -0
- package/cli/commands/agent-fix.js +1245 -0
- package/cli/commands/audit.js +1180 -0
- package/cli/commands/autofix.js +383 -0
- package/cli/commands/baseline.js +193 -0
- package/cli/commands/benchmark.js +327 -0
- package/cli/commands/checklist.js +223 -0
- package/cli/commands/ci.js +403 -0
- package/cli/commands/deps.js +516 -0
- package/cli/commands/diff.js +200 -0
- package/cli/commands/doctor.js +195 -0
- package/cli/commands/env-audit.js +349 -0
- package/cli/commands/fix.js +218 -0
- package/cli/commands/guard.js +396 -0
- package/cli/commands/hooks.js +278 -0
- package/cli/commands/init.js +514 -0
- package/cli/commands/legal.js +158 -0
- package/cli/commands/live-advisories.js +241 -0
- package/cli/commands/mcp.js +660 -0
- package/cli/commands/openclaw.js +386 -0
- package/cli/commands/red-team.js +350 -0
- package/cli/commands/redteam.js +78 -0
- package/cli/commands/remediate.js +797 -0
- package/cli/commands/rotate.js +768 -0
- package/cli/commands/rules.js +196 -0
- package/cli/commands/scan-mcp.js +534 -0
- package/cli/commands/scan-skill.js +588 -0
- package/cli/commands/scan-standard.js +251 -0
- package/cli/commands/scan.js +524 -0
- package/cli/commands/score.js +449 -0
- package/cli/commands/shell.js +514 -0
- package/cli/commands/team-report.js +398 -0
- package/cli/commands/undo.js +161 -0
- package/cli/commands/update-intel.js +126 -0
- package/cli/commands/vibe-check.js +276 -0
- package/cli/commands/watch.js +757 -0
- package/cli/commands/web.js +63 -0
- package/cli/core/ast/guardrail-detector.js +141 -0
- package/cli/core/ast/index.js +22 -0
- package/cli/core/ast/parser.js +676 -0
- package/cli/core/ast/scope-tree.js +287 -0
- package/cli/core/ast/taint-tracker.js +158 -0
- package/cli/core/branding.js +37 -0
- package/cli/core/env.js +38 -0
- package/cli/core/errors.js +61 -0
- package/cli/core/fs.js +62 -0
- package/cli/core/output/compliance.js +90 -0
- package/cli/core/output/html-theme.js +158 -0
- package/cli/core/output/index.js +57 -0
- package/cli/core/output/json.js +48 -0
- package/cli/core/output/sarif.js +240 -0
- package/cli/core/version.js +67 -0
- package/cli/core/web/jobs.js +183 -0
- package/cli/core/web/projects.js +146 -0
- package/cli/core/web/server.js +439 -0
- package/cli/data/atlas-knowledge.json +5640 -0
- package/cli/data/eaa-catalog.json +39 -0
- package/cli/data/known-mcps.json +26 -0
- package/cli/data/probes/prompt-injection-corpus.json +271 -0
- package/cli/data/threat-intel.json +85 -0
- package/cli/data/threatpacks/latest.json +41 -0
- package/cli/hooks/patterns.js +313 -0
- package/cli/hooks/post-tool-use.js +140 -0
- package/cli/hooks/pre-tool-use.js +186 -0
- package/cli/index.js +90 -0
- package/cli/providers/llm-provider.js +766 -0
- package/cli/utils/autofix-rules.js +74 -0
- package/cli/utils/cache-manager.js +310 -0
- package/cli/utils/compliance-map.js +191 -0
- package/cli/utils/entropy.js +132 -0
- package/cli/utils/fix-ledger.js +127 -0
- package/cli/utils/hermes-tool-registry.js +252 -0
- package/cli/utils/intel/cache.js +61 -0
- package/cli/utils/intel/http.js +88 -0
- package/cli/utils/intel/index.js +235 -0
- package/cli/utils/intel/merge.js +229 -0
- package/cli/utils/intel/sources/epss.js +54 -0
- package/cli/utils/intel/sources/ghsa.js +81 -0
- package/cli/utils/intel/sources/gitguardian.js +40 -0
- package/cli/utils/intel/sources/gitleaks.js +101 -0
- package/cli/utils/intel/sources/kev.js +38 -0
- package/cli/utils/intel/sources/nvd.js +84 -0
- package/cli/utils/intel/sources/osv.js +132 -0
- package/cli/utils/intel/sources/phylum.js +44 -0
- package/cli/utils/intel/sources/snyk.js +46 -0
- package/cli/utils/intel/sources/socket.js +69 -0
- package/cli/utils/intel/sources/sonatype.js +84 -0
- package/cli/utils/intel/sources/threatpack.js +69 -0
- package/cli/utils/mcp-trust.js +60 -0
- package/cli/utils/output.js +251 -0
- package/cli/utils/patterns.js +1130 -0
- package/cli/utils/pdf-generator.js +94 -0
- package/cli/utils/plugin-loader.js +364 -0
- package/cli/utils/rule-import.js +228 -0
- package/cli/utils/rule-registry.js +426 -0
- package/cli/utils/scan-fingerprint.js +109 -0
- package/cli/utils/scan-playbook.js +312 -0
- package/cli/utils/score-history.js +119 -0
- package/cli/utils/secrets-verifier.js +247 -0
- package/cli/utils/security-memory.js +296 -0
- package/cli/utils/standards/atlas-knowledge.js +87 -0
- package/cli/utils/standards/index.js +127 -0
- package/cli/utils/standards/sources/avid.js +45 -0
- package/cli/utils/standards/sources/eu-ai-act.js +89 -0
- package/cli/utils/standards/sources/google-saif.js +39 -0
- package/cli/utils/standards/sources/iso-42001.js +94 -0
- package/cli/utils/standards/sources/mitre-atlas.js +54 -0
- package/cli/utils/standards/sources/nist-ai-600-1.js +45 -0
- package/cli/utils/standards/sources/owasp-llm.js +45 -0
- package/cli/utils/standards/sources/owasp-ml.js +45 -0
- package/cli/utils/threat-intel.js +265 -0
- package/configs/firebase/firestore-rules.txt +215 -0
- package/configs/firebase/security-checklist.md +236 -0
- package/configs/firebase/storage-rules.txt +206 -0
- package/configs/gitignore-template +258 -0
- package/configs/nextjs-security-headers.js +220 -0
- package/configs/praxisignore-template +50 -0
- package/configs/supabase/secure-client.ts +225 -0
- package/configs/supabase/security-checklist.md +278 -0
- package/docs/THIRD_PARTY_NOTICES.md +26 -0
- package/docs/THREAT_INTEL.md +292 -0
- package/docs/USAGE.md +1205 -0
- package/docs/design/WEB-UI.md +82 -0
- package/package.json +71 -0
- package/scripts/check-determinism.mjs +119 -0
- package/snippets/README.md +122 -0
- package/snippets/api-security/api-security-checklist.md +412 -0
- package/snippets/api-security/cors-config.ts +322 -0
- package/snippets/api-security/input-validation.ts +430 -0
- package/snippets/auth/jwt-checklist.md +322 -0
- package/snippets/rate-limiting/nextjs-middleware.ts +211 -0
- 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.
|