praxis-sec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -0
  3. package/ai-defense/cost-protection.md +292 -0
  4. package/ai-defense/llm-security-checklist.md +324 -0
  5. package/ai-defense/prompt-injection-patterns.js +283 -0
  6. package/ai-defense/system-prompt-armor.md +327 -0
  7. package/checklists/launch-day.md +168 -0
  8. package/cli/agents/abom-generator.js +225 -0
  9. package/cli/agents/agent-attestation-agent.js +318 -0
  10. package/cli/agents/agent-config-scanner.js +787 -0
  11. package/cli/agents/agent-telemetry-agent.js +415 -0
  12. package/cli/agents/agentic-security-agent.js +296 -0
  13. package/cli/agents/agentic-supply-chain-agent.js +463 -0
  14. package/cli/agents/ai-infra-inventory-agent.js +449 -0
  15. package/cli/agents/api-fuzzer.js +345 -0
  16. package/cli/agents/auth-bypass-agent.js +348 -0
  17. package/cli/agents/base-agent.js +280 -0
  18. package/cli/agents/cicd-scanner.js +300 -0
  19. package/cli/agents/config-auditor.js +757 -0
  20. package/cli/agents/deep-analyzer.js +776 -0
  21. package/cli/agents/endpoint-agent-abuse-agent.js +404 -0
  22. package/cli/agents/exception-handler-agent.js +187 -0
  23. package/cli/agents/git-history-scanner.js +169 -0
  24. package/cli/agents/governance-audits.js +138 -0
  25. package/cli/agents/hermes-security-agent.js +536 -0
  26. package/cli/agents/html-reporter.js +1125 -0
  27. package/cli/agents/index.js +147 -0
  28. package/cli/agents/injection-tester.js +502 -0
  29. package/cli/agents/legal-risk-agent.js +328 -0
  30. package/cli/agents/llm-redteam.js +199 -0
  31. package/cli/agents/managed-agent-scanner.js +333 -0
  32. package/cli/agents/mcp-security-agent.js +588 -0
  33. package/cli/agents/memory-poisoning-agent.js +305 -0
  34. package/cli/agents/mobile-scanner.js +231 -0
  35. package/cli/agents/model-file-scanner.js +259 -0
  36. package/cli/agents/orchestrator.js +355 -0
  37. package/cli/agents/pii-compliance-agent.js +301 -0
  38. package/cli/agents/policy-engine.js +229 -0
  39. package/cli/agents/prompt-injection-prober.js +224 -0
  40. package/cli/agents/rag-security-agent.js +204 -0
  41. package/cli/agents/recon-agent.js +207 -0
  42. package/cli/agents/sbom-generator.js +265 -0
  43. package/cli/agents/scoring-engine.js +273 -0
  44. package/cli/agents/ssrf-prober.js +130 -0
  45. package/cli/agents/stateful-watcher.js +238 -0
  46. package/cli/agents/supabase-rls-agent.js +154 -0
  47. package/cli/agents/supply-chain-agent.js +857 -0
  48. package/cli/agents/swarm-orchestrator.js +200 -0
  49. package/cli/agents/verifier-agent.js +303 -0
  50. package/cli/agents/vibe-coding-agent.js +250 -0
  51. package/cli/bin/praxis.js +866 -0
  52. package/cli/commands/abom.js +73 -0
  53. package/cli/commands/agent-fix.js +1245 -0
  54. package/cli/commands/audit.js +1180 -0
  55. package/cli/commands/autofix.js +383 -0
  56. package/cli/commands/baseline.js +193 -0
  57. package/cli/commands/benchmark.js +327 -0
  58. package/cli/commands/checklist.js +223 -0
  59. package/cli/commands/ci.js +403 -0
  60. package/cli/commands/deps.js +516 -0
  61. package/cli/commands/diff.js +200 -0
  62. package/cli/commands/doctor.js +195 -0
  63. package/cli/commands/env-audit.js +349 -0
  64. package/cli/commands/fix.js +218 -0
  65. package/cli/commands/guard.js +396 -0
  66. package/cli/commands/hooks.js +278 -0
  67. package/cli/commands/init.js +514 -0
  68. package/cli/commands/legal.js +158 -0
  69. package/cli/commands/live-advisories.js +241 -0
  70. package/cli/commands/mcp.js +660 -0
  71. package/cli/commands/openclaw.js +386 -0
  72. package/cli/commands/red-team.js +350 -0
  73. package/cli/commands/redteam.js +78 -0
  74. package/cli/commands/remediate.js +797 -0
  75. package/cli/commands/rotate.js +768 -0
  76. package/cli/commands/rules.js +196 -0
  77. package/cli/commands/scan-mcp.js +534 -0
  78. package/cli/commands/scan-skill.js +588 -0
  79. package/cli/commands/scan-standard.js +251 -0
  80. package/cli/commands/scan.js +524 -0
  81. package/cli/commands/score.js +449 -0
  82. package/cli/commands/shell.js +514 -0
  83. package/cli/commands/team-report.js +398 -0
  84. package/cli/commands/undo.js +161 -0
  85. package/cli/commands/update-intel.js +126 -0
  86. package/cli/commands/vibe-check.js +276 -0
  87. package/cli/commands/watch.js +757 -0
  88. package/cli/commands/web.js +63 -0
  89. package/cli/core/ast/guardrail-detector.js +141 -0
  90. package/cli/core/ast/index.js +22 -0
  91. package/cli/core/ast/parser.js +676 -0
  92. package/cli/core/ast/scope-tree.js +287 -0
  93. package/cli/core/ast/taint-tracker.js +158 -0
  94. package/cli/core/branding.js +37 -0
  95. package/cli/core/env.js +38 -0
  96. package/cli/core/errors.js +61 -0
  97. package/cli/core/fs.js +62 -0
  98. package/cli/core/output/compliance.js +90 -0
  99. package/cli/core/output/html-theme.js +158 -0
  100. package/cli/core/output/index.js +57 -0
  101. package/cli/core/output/json.js +48 -0
  102. package/cli/core/output/sarif.js +240 -0
  103. package/cli/core/version.js +67 -0
  104. package/cli/core/web/jobs.js +183 -0
  105. package/cli/core/web/projects.js +146 -0
  106. package/cli/core/web/server.js +439 -0
  107. package/cli/data/atlas-knowledge.json +5640 -0
  108. package/cli/data/eaa-catalog.json +39 -0
  109. package/cli/data/known-mcps.json +26 -0
  110. package/cli/data/probes/prompt-injection-corpus.json +271 -0
  111. package/cli/data/threat-intel.json +85 -0
  112. package/cli/data/threatpacks/latest.json +41 -0
  113. package/cli/hooks/patterns.js +313 -0
  114. package/cli/hooks/post-tool-use.js +140 -0
  115. package/cli/hooks/pre-tool-use.js +186 -0
  116. package/cli/index.js +90 -0
  117. package/cli/providers/llm-provider.js +766 -0
  118. package/cli/utils/autofix-rules.js +74 -0
  119. package/cli/utils/cache-manager.js +310 -0
  120. package/cli/utils/compliance-map.js +191 -0
  121. package/cli/utils/entropy.js +132 -0
  122. package/cli/utils/fix-ledger.js +127 -0
  123. package/cli/utils/hermes-tool-registry.js +252 -0
  124. package/cli/utils/intel/cache.js +61 -0
  125. package/cli/utils/intel/http.js +88 -0
  126. package/cli/utils/intel/index.js +235 -0
  127. package/cli/utils/intel/merge.js +229 -0
  128. package/cli/utils/intel/sources/epss.js +54 -0
  129. package/cli/utils/intel/sources/ghsa.js +81 -0
  130. package/cli/utils/intel/sources/gitguardian.js +40 -0
  131. package/cli/utils/intel/sources/gitleaks.js +101 -0
  132. package/cli/utils/intel/sources/kev.js +38 -0
  133. package/cli/utils/intel/sources/nvd.js +84 -0
  134. package/cli/utils/intel/sources/osv.js +132 -0
  135. package/cli/utils/intel/sources/phylum.js +44 -0
  136. package/cli/utils/intel/sources/snyk.js +46 -0
  137. package/cli/utils/intel/sources/socket.js +69 -0
  138. package/cli/utils/intel/sources/sonatype.js +84 -0
  139. package/cli/utils/intel/sources/threatpack.js +69 -0
  140. package/cli/utils/mcp-trust.js +60 -0
  141. package/cli/utils/output.js +251 -0
  142. package/cli/utils/patterns.js +1130 -0
  143. package/cli/utils/pdf-generator.js +94 -0
  144. package/cli/utils/plugin-loader.js +364 -0
  145. package/cli/utils/rule-import.js +228 -0
  146. package/cli/utils/rule-registry.js +426 -0
  147. package/cli/utils/scan-fingerprint.js +109 -0
  148. package/cli/utils/scan-playbook.js +312 -0
  149. package/cli/utils/score-history.js +119 -0
  150. package/cli/utils/secrets-verifier.js +247 -0
  151. package/cli/utils/security-memory.js +296 -0
  152. package/cli/utils/standards/atlas-knowledge.js +87 -0
  153. package/cli/utils/standards/index.js +127 -0
  154. package/cli/utils/standards/sources/avid.js +45 -0
  155. package/cli/utils/standards/sources/eu-ai-act.js +89 -0
  156. package/cli/utils/standards/sources/google-saif.js +39 -0
  157. package/cli/utils/standards/sources/iso-42001.js +94 -0
  158. package/cli/utils/standards/sources/mitre-atlas.js +54 -0
  159. package/cli/utils/standards/sources/nist-ai-600-1.js +45 -0
  160. package/cli/utils/standards/sources/owasp-llm.js +45 -0
  161. package/cli/utils/standards/sources/owasp-ml.js +45 -0
  162. package/cli/utils/threat-intel.js +265 -0
  163. package/configs/firebase/firestore-rules.txt +215 -0
  164. package/configs/firebase/security-checklist.md +236 -0
  165. package/configs/firebase/storage-rules.txt +206 -0
  166. package/configs/gitignore-template +258 -0
  167. package/configs/nextjs-security-headers.js +220 -0
  168. package/configs/praxisignore-template +50 -0
  169. package/configs/supabase/secure-client.ts +225 -0
  170. package/configs/supabase/security-checklist.md +278 -0
  171. package/docs/THIRD_PARTY_NOTICES.md +26 -0
  172. package/docs/THREAT_INTEL.md +292 -0
  173. package/docs/USAGE.md +1205 -0
  174. package/docs/design/WEB-UI.md +82 -0
  175. package/package.json +71 -0
  176. package/scripts/check-determinism.mjs +119 -0
  177. package/snippets/README.md +122 -0
  178. package/snippets/api-security/api-security-checklist.md +412 -0
  179. package/snippets/api-security/cors-config.ts +322 -0
  180. package/snippets/api-security/input-validation.ts +430 -0
  181. package/snippets/auth/jwt-checklist.md +322 -0
  182. package/snippets/rate-limiting/nextjs-middleware.ts +211 -0
  183. package/snippets/rate-limiting/upstash-ratelimit.ts +229 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Scan Standard Command
3
+ * =====================
4
+ *
5
+ * Runs a normal scan and filters the result to findings tagged with a
6
+ * specific AI-security standard (OWASP LLM, MITRE ATLAS, NIST AI 600-1, etc.).
7
+ *
8
+ * USAGE:
9
+ * praxis scan standard --list # list available standards
10
+ * praxis scan standard owasp-llm . # findings tagged with the OWASP LLM Top 10
11
+ * praxis scan standard mitre-atlas . --json # ATLAS findings as JSON
12
+ * praxis scan standard owasp-llm . --control LLM01 # filter to a single control
13
+ */
14
+
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+ import chalk from 'chalk';
18
+ import ora from 'ora';
19
+ import { buildOrchestratorAsync } from '../agents/index.js';
20
+ import { ScoringEngine } from '../agents/scoring-engine.js';
21
+ import {
22
+ ALL_STANDARDS,
23
+ listStandards,
24
+ getStandard,
25
+ filterFindingsByStandard,
26
+ } from '../utils/standards/index.js';
27
+ import { render, hasFormat } from '../core/output/index.js';
28
+
29
+ const SEV_COLORS = {
30
+ critical: chalk.red.bold,
31
+ high: chalk.red,
32
+ medium: chalk.yellow,
33
+ low: chalk.blue,
34
+ };
35
+
36
+ export async function scanStandardCommand(name, targetPath = '.', options = {}) {
37
+ if (options.list || name === 'list') {
38
+ return printStandardsList(options);
39
+ }
40
+
41
+ if (!name) {
42
+ console.error(chalk.red(' Missing standard name.'));
43
+ console.error(chalk.gray(' Usage: praxis scan standard <name> [path]'));
44
+ console.error(chalk.gray(' praxis scan standard --list'));
45
+ process.exit(1);
46
+ }
47
+
48
+ const standard = getStandard(name);
49
+ if (!standard) {
50
+ console.error(chalk.red(` Unknown standard: ${name}`));
51
+ console.error(chalk.gray(' Available:'));
52
+ for (const s of listStandards()) {
53
+ console.error(chalk.gray(` ${s.name.padEnd(16)} ${s.title}`));
54
+ }
55
+ process.exit(1);
56
+ }
57
+
58
+ const absolutePath = path.resolve(targetPath);
59
+ if (!fs.existsSync(absolutePath)) {
60
+ console.error(chalk.red(` Path does not exist: ${absolutePath}`));
61
+ process.exit(1);
62
+ }
63
+
64
+ const machine = !!(options.json || options.sarif);
65
+
66
+ if (!machine) {
67
+ console.log();
68
+ console.log(chalk.cyan.bold(` Praxis — ${standard.title} (${standard.version})`));
69
+ console.log(chalk.gray(` ${standard.description}`));
70
+ console.log(chalk.gray(` ${standard.url}`));
71
+ console.log();
72
+ }
73
+
74
+ const spinner = machine ? null : ora({ text: 'Running agents...', color: 'cyan' }).start();
75
+ const orchestrator = await buildOrchestratorAsync(absolutePath, { quiet: true });
76
+ const result = await orchestrator.runAll(absolutePath, { quiet: true });
77
+ if (spinner) spinner.succeed(chalk.green(`Scanned ${result.findings.length} finding(s) total`));
78
+
79
+ const scoring = new ScoringEngine();
80
+ const scoreResult = scoring.compute(result.findings);
81
+
82
+ const filtered = filterFindingsByStandard(
83
+ result.findings,
84
+ standard.name,
85
+ options.control || null
86
+ );
87
+
88
+ const standardSummary = buildStandardSummary(standard, filtered, options.control);
89
+
90
+ const report = {
91
+ standard: {
92
+ name: standard.name,
93
+ version: standard.version,
94
+ title: standard.title,
95
+ url: standard.url,
96
+ },
97
+ control: options.control || null,
98
+ totalFindings: filtered.length,
99
+ coverage: standardSummary.coverage,
100
+ flaggedControls: standardSummary.flaggedControls,
101
+ totalControls: standardSummary.totalControls,
102
+ controls: standardSummary.controls,
103
+ findings: filtered.map(f => ({
104
+ ...f,
105
+ file: String(f.file || '')
106
+ .replace(/\\/g, '/')
107
+ .replace(/^[a-zA-Z]:\/+/, '')
108
+ .replace(/^.*\/Praxis\/showcase-target\//, 'showcase-target/')
109
+ .replace(/^.*\/Praxis\//, ''),
110
+ })),
111
+ score: scoreResult.score,
112
+ grade: scoreResult.grade?.letter || 'A',
113
+ scannedAt: new Date().toISOString(),
114
+ };
115
+
116
+ // ATLAS enrichment: hydrate flagged techniques with mitigations + case studies
117
+ if (standard.name === 'mitre-atlas') {
118
+ try {
119
+ const { getTechniqueDetails, atlasSnapshot } = await import('../utils/standards/sources/mitre-atlas.js');
120
+ report.atlas = {
121
+ snapshot: atlasSnapshot(),
122
+ techniques: Object.fromEntries(
123
+ standardSummary.controls
124
+ .filter(c => c.findingCount > 0)
125
+ .map(c => [c.id, getTechniqueDetails(c.id)])
126
+ .filter(([, d]) => d)
127
+ ),
128
+ };
129
+ } catch { /* enrichment is best-effort */ }
130
+ }
131
+
132
+ if (options.json) {
133
+ console.log(render('json', report));
134
+ return;
135
+ }
136
+ if (options.sarif) {
137
+ console.log(render('sarif', report));
138
+ return;
139
+ }
140
+ if (options.format && hasFormat(options.format)) {
141
+ console.log(render(options.format, report));
142
+ return;
143
+ }
144
+
145
+ await printHumanReport(standard, report, options);
146
+ }
147
+
148
+ function buildStandardSummary(standard, findings, controlFilter) {
149
+ const counts = {};
150
+ for (const f of findings) {
151
+ const ids = (f.standards || {})[standard.name] || [];
152
+ for (const id of ids) {
153
+ if (controlFilter && id !== controlFilter) continue;
154
+ counts[id] = (counts[id] || 0) + 1;
155
+ }
156
+ }
157
+ const controls = (standard.controls || [])
158
+ .filter(c => !controlFilter || c.id === controlFilter)
159
+ .map(c => ({
160
+ ...c,
161
+ findingCount: counts[c.id] || 0,
162
+ status: counts[c.id] ? 'flagged' : 'clear',
163
+ }));
164
+ const flaggedControls = controls.filter(c => c.findingCount > 0).length;
165
+ return {
166
+ totalControls: controls.length,
167
+ flaggedControls,
168
+ coverage: `${flaggedControls}/${controls.length}`,
169
+ controls,
170
+ };
171
+ }
172
+
173
+ function printStandardsList(options) {
174
+ if (options.json) {
175
+ console.log(JSON.stringify(listStandards(), null, 2));
176
+ return;
177
+ }
178
+ console.log();
179
+ console.log(chalk.cyan.bold(' Available AI-security standards'));
180
+ console.log();
181
+ for (const s of listStandards()) {
182
+ console.log(` ${chalk.white.bold(s.name.padEnd(16))} ${chalk.gray(`v${s.version}`).padEnd(12)} ${s.title}`);
183
+ console.log(chalk.gray(` ${s.controlCount} controls — ${s.url}`));
184
+ }
185
+ console.log();
186
+ console.log(chalk.gray(` Total: ${ALL_STANDARDS.length} standards.`));
187
+ console.log();
188
+ }
189
+
190
+ async function printHumanReport(standard, report) { console.log(chalk.white.bold(` Coverage: ${report.coverage} (${report.totalFindings} finding${report.totalFindings === 1 ? '' : 's'})`));
191
+ console.log();
192
+
193
+ for (const ctrl of report.controls) {
194
+ const statusIcon = ctrl.findingCount > 0 ? chalk.red('●') : chalk.green('○');
195
+ const head = ctrl.findingCount > 0
196
+ ? chalk.white.bold(`${ctrl.id} — ${ctrl.title}`) + chalk.yellow(` (${ctrl.findingCount})`)
197
+ : chalk.gray(`${ctrl.id} — ${ctrl.title}`);
198
+ console.log(` ${statusIcon} ${head}`);
199
+ }
200
+ console.log();
201
+
202
+ // ATLAS enrichment: mitigations + case studies for flagged techniques
203
+ if (standard.name === 'mitre-atlas') {
204
+ try {
205
+ const { getTechniqueDetails, atlasSnapshot } = await import('../utils/standards/sources/mitre-atlas.js');
206
+ const flagged = report.controls.filter(c => c.findingCount > 0);
207
+ if (flagged.length > 0) {
208
+ console.log(chalk.gray(` ATLAS knowledge snapshot: ${atlasSnapshot()}`));
209
+ console.log(chalk.white.bold(' Recommended mitigations (ATLAS):'));
210
+ console.log();
211
+ const shown = new Set();
212
+ for (const ctrl of flagged) {
213
+ const details = getTechniqueDetails(ctrl.id);
214
+ if (!details) continue;
215
+ for (const m of details.mitigations) {
216
+ if (shown.has(m.id)) continue;
217
+ shown.add(m.id);
218
+ console.log(` ${chalk.cyan(m.id)} ${m.name}`);
219
+ }
220
+ if (details.caseStudies.length > 0) {
221
+ console.log(chalk.gray(` case studies: ${details.caseStudies.map(cs => cs.name).join('; ')}`));
222
+ }
223
+ }
224
+ console.log();
225
+ }
226
+ } catch { /* enrichment is best-effort */ }
227
+ }
228
+
229
+ if (report.totalFindings === 0) {
230
+ console.log(chalk.green(` ✔ No findings tagged with ${standard.title}.`));
231
+ console.log();
232
+ return;
233
+ }
234
+
235
+ console.log(chalk.white.bold(' Findings:'));
236
+ console.log();
237
+ for (const f of report.findings.slice(0, 50)) {
238
+ const ids = (f.standards || {})[standard.name] || [];
239
+ const sev = (f.severity || 'medium').toUpperCase();
240
+ const color = SEV_COLORS[f.severity] || chalk.white;
241
+ const tag = ids.join(', ');
242
+ const file = f.file ? path.relative(process.cwd(), f.file) : '';
243
+ const loc = file ? `${file}:${f.line || 0}` : '';
244
+ console.log(` ${color(`[${sev}]`)} ${chalk.cyan(`[${tag}]`)} ${f.title || f.rule || ''}`);
245
+ if (loc) console.log(chalk.gray(` ${loc}`));
246
+ }
247
+ if (report.findings.length > 50) {
248
+ console.log(chalk.gray(` …and ${report.findings.length - 50} more (use --json for the full list).`));
249
+ }
250
+ console.log();
251
+ }