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,276 @@
1
+ /**
2
+ * Vibe Check Command
3
+ * ==================
4
+ *
5
+ * Fun, emoji-rich security check with shareable results.
6
+ * Same security scan as `audit`, but with personality.
7
+ *
8
+ * USAGE:
9
+ * npx praxis-sec vibe-check [path] Run a vibe check
10
+ * npx praxis-sec vibe-check . --badge Generate a markdown badge
11
+ *
12
+ * OUTPUT:
13
+ * Big ASCII art grade, emoji severity indicators,
14
+ * "vibes" rating, and a shareable one-liner.
15
+ */
16
+
17
+ import fs from 'fs';
18
+ import path from 'path';
19
+ import chalk from 'chalk';
20
+ import ora from 'ora';
21
+ import { buildOrchestrator } from '../agents/index.js';
22
+ import { ScoringEngine } from '../agents/scoring-engine.js';
23
+ import { runDepsAudit } from './deps.js';
24
+ import {
25
+ SECRET_PATTERNS,
26
+ SKIP_DIRS,
27
+ SKIP_EXTENSIONS,
28
+ SKIP_FILENAMES,
29
+ MAX_FILE_SIZE,
30
+ loadGitignorePatterns
31
+ } from '../utils/patterns.js';
32
+ import { isHighEntropyMatch, getConfidence } from '../utils/entropy.js';
33
+ import fg from 'fast-glob';
34
+
35
+ // =============================================================================
36
+ // VIBES DATA
37
+ // =============================================================================
38
+
39
+ const VIBE_GRADES = {
40
+ A: {
41
+ emoji: '🛡️',
42
+ vibe: 'immaculate',
43
+ ascii: `
44
+ ╔═══╗
45
+ ║ A ║
46
+ ╚═══╝`,
47
+ message: 'Your security vibes are IMMACULATE. Ship it! 🚀',
48
+ color: chalk.green.bold,
49
+ },
50
+ B: {
51
+ emoji: '✅',
52
+ vibe: 'solid',
53
+ ascii: `
54
+ ╔═══╗
55
+ ║ B ║
56
+ ╚═══╝`,
57
+ message: 'Solid vibes. A few things to tighten up, but you\'re in good shape. 💪',
58
+ color: chalk.cyan.bold,
59
+ },
60
+ C: {
61
+ emoji: '⚠️',
62
+ vibe: 'mid',
63
+ ascii: `
64
+ ╔═══╗
65
+ ║ C ║
66
+ ╚═══╝`,
67
+ message: 'Mid vibes. Some security gaps need attention before you ship. 🔧',
68
+ color: chalk.yellow.bold,
69
+ },
70
+ D: {
71
+ emoji: '🚨',
72
+ vibe: 'sketchy',
73
+ ascii: `
74
+ ╔═══╗
75
+ ║ D ║
76
+ ╚═══╝`,
77
+ message: 'Sketchy vibes. Serious issues found — fix these before deploying. 🛑',
78
+ color: chalk.red.bold,
79
+ },
80
+ F: {
81
+ emoji: '💀',
82
+ vibe: 'cooked',
83
+ ascii: `
84
+ ╔═══╗
85
+ ║ F ║
86
+ ╚═══╝`,
87
+ message: 'You are cooked. Critical vulnerabilities everywhere. DO NOT SHIP. 🔥',
88
+ color: chalk.red.bold,
89
+ },
90
+ };
91
+
92
+ const SEV_EMOJI = {
93
+ critical: '💀',
94
+ high: '🔴',
95
+ medium: '🟡',
96
+ low: '🔵',
97
+ };
98
+
99
+ // =============================================================================
100
+ // MAIN COMMAND
101
+ // =============================================================================
102
+
103
+ export async function vibeCheckCommand(targetPath = '.', options = {}) {
104
+ const absolutePath = path.resolve(targetPath);
105
+
106
+ if (!fs.existsSync(absolutePath)) {
107
+ console.error(chalk.red(`Path does not exist: ${absolutePath}`));
108
+ process.exit(1);
109
+ }
110
+
111
+ const projectName = path.basename(absolutePath);
112
+
113
+ console.log();
114
+ console.log(chalk.cyan.bold(' 🎵 VIBE CHECK 🎵'));
115
+ console.log(chalk.gray(` Scanning ${projectName}...`));
116
+ console.log();
117
+
118
+ const startTime = Date.now();
119
+
120
+ // ── Secret Scan ──────────────────────────────────────────────────────────
121
+ const spinner = ora({ text: 'Checking the vibes...', color: 'magenta' }).start();
122
+
123
+ const allFiles = await findFiles(absolutePath);
124
+ const secretFindings = [];
125
+
126
+ for (const file of allFiles) {
127
+ try {
128
+ const content = fs.readFileSync(file, 'utf-8');
129
+ const lines = content.split('\n');
130
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
131
+ const line = lines[lineNum];
132
+ if (/praxis-ignore/i.test(line)) continue;
133
+ for (const pattern of SECRET_PATTERNS) {
134
+ pattern.pattern.lastIndex = 0;
135
+ let match;
136
+ while ((match = pattern.pattern.exec(line)) !== null) {
137
+ if (pattern.requiresEntropyCheck && !isHighEntropyMatch(match[0])) continue;
138
+ secretFindings.push({
139
+ file, line: lineNum + 1, column: match.index + 1,
140
+ matched: match[0], severity: pattern.severity,
141
+ category: pattern.category || 'secrets',
142
+ rule: pattern.name, title: pattern.name.replace(/_/g, ' '),
143
+ description: pattern.description,
144
+ confidence: getConfidence(pattern, match[0]),
145
+ });
146
+ }
147
+ }
148
+ }
149
+ } catch { /* skip */ }
150
+ }
151
+
152
+ // ── Agent Scan ──────────────────────────────────────────────────────────
153
+ const orchestrator = buildOrchestrator();
154
+ const results = await orchestrator.runAll(absolutePath, { quiet: true });
155
+
156
+ // ── Dependency Audit ─────────────────────────────────────────────────────
157
+ let depVulns = [];
158
+ try {
159
+ const depResult = await runDepsAudit(absolutePath);
160
+ depVulns = depResult.vulns || [];
161
+ } catch { /* skip */ }
162
+
163
+ spinner.stop();
164
+
165
+ // ── Merge & Score ─────────────────────────────────────────────────────────
166
+ const seen = new Set();
167
+ const allFindings = [...secretFindings, ...results.findings].filter(f => {
168
+ const key = `${f.file}:${f.line}:${f.rule}`;
169
+ if (seen.has(key)) return false;
170
+ seen.add(key);
171
+ return true;
172
+ });
173
+
174
+ const scoringEngine = new ScoringEngine();
175
+ const scoreResult = scoringEngine.compute(allFindings, depVulns);
176
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
177
+
178
+ // ── Display ──────────────────────────────────────────────────────────────
179
+ const grade = VIBE_GRADES[scoreResult.grade.letter] || VIBE_GRADES.F;
180
+ const score = Math.round(scoreResult.score * 10) / 10;
181
+
182
+ const critical = allFindings.filter(f => f.severity === 'critical').length;
183
+ const high = allFindings.filter(f => f.severity === 'high').length;
184
+ const medium = allFindings.filter(f => f.severity === 'medium').length;
185
+ const low = allFindings.filter(f => f.severity === 'low').length;
186
+
187
+ // Big grade display
188
+ console.log(grade.color(grade.ascii));
189
+ console.log();
190
+ console.log(grade.color(` ${grade.emoji} Score: ${score}/100 | Vibes: ${grade.vibe.toUpperCase()}`));
191
+ console.log();
192
+ console.log(grade.color(` ${grade.message}`));
193
+ console.log();
194
+
195
+ // Severity breakdown
196
+ console.log(chalk.white.bold(' Breakdown:'));
197
+ if (critical > 0) console.log(` ${SEV_EMOJI.critical} Critical: ${critical}`);
198
+ if (high > 0) console.log(` ${SEV_EMOJI.high} High: ${high}`);
199
+ if (medium > 0) console.log(` ${SEV_EMOJI.medium} Medium: ${medium}`);
200
+ if (low > 0) console.log(` ${SEV_EMOJI.low} Low: ${low}`);
201
+ if (depVulns.length > 0) console.log(` 📦 Dep CVEs: ${depVulns.length}`);
202
+ if (allFindings.length === 0 && depVulns.length === 0) {
203
+ console.log(` ✨ Zero issues found!`);
204
+ }
205
+ console.log(chalk.gray(` ⏱️ ${duration}s`));
206
+ console.log();
207
+
208
+ // Top 3 issues
209
+ if (allFindings.length > 0) {
210
+ console.log(chalk.white.bold(' Top issues to fix:'));
211
+ const top = allFindings
212
+ .sort((a, b) => {
213
+ const order = { critical: 0, high: 1, medium: 2, low: 3 };
214
+ return (order[a.severity] ?? 4) - (order[b.severity] ?? 4);
215
+ })
216
+ .slice(0, 3);
217
+ for (const f of top) {
218
+ const rel = path.relative(absolutePath, f.file).replace(/\\/g, '/');
219
+ console.log(` ${SEV_EMOJI[f.severity] || '⚪'} ${f.title || f.rule} ${chalk.gray(`(${rel}:${f.line})`)}`);
220
+ }
221
+ console.log();
222
+ }
223
+
224
+ // ── Shareable one-liner ──────────────────────────────────────────────────
225
+ const shareLine = `${grade.emoji} ${projectName}: ${score}/100 (${scoreResult.grade.letter}) — ${grade.vibe} vibes | ${allFindings.length} findings | Scanned with Praxis`;
226
+ console.log(chalk.gray(' Share your vibes:'));
227
+ console.log(chalk.cyan(` ${shareLine}`));
228
+ console.log();
229
+
230
+ // ── Badge ─────────────────────────────────────────────────────────────────
231
+ if (options.badge) {
232
+ const badgeColor = {
233
+ A: 'brightgreen', B: 'blue', C: 'yellow', D: 'orange', F: 'red',
234
+ }[scoreResult.grade.letter] || 'lightgrey';
235
+ const badgeUrl = `https://img.shields.io/badge/ship--safe-${score}%2F100_${scoreResult.grade.letter}-${badgeColor}`;
236
+ const badgeMd = `[![Praxis Score](${badgeUrl})]()`;
237
+
238
+ console.log(chalk.white.bold(' Markdown badge:'));
239
+ console.log(chalk.cyan(` ${badgeMd}`));
240
+ console.log();
241
+
242
+ // Write badge to README if it exists and doesn't have one already
243
+ const readmePath = path.join(absolutePath, 'README.md');
244
+ if (fs.existsSync(readmePath)) {
245
+ const readme = fs.readFileSync(readmePath, 'utf-8');
246
+ if (!readme.includes('ship--safe')) {
247
+ console.log(chalk.gray(' Add this badge to your README.md to show off your security score!'));
248
+ }
249
+ }
250
+ }
251
+
252
+ process.exit(allFindings.length > 0 || depVulns.length > 0 ? 1 : 0);
253
+ }
254
+
255
+ // =============================================================================
256
+ // FILE FINDER (reused from CI)
257
+ // =============================================================================
258
+
259
+ async function findFiles(rootPath) {
260
+ const globIgnore = Array.from(SKIP_DIRS).map(dir => `**/${dir}/**`);
261
+ const gitignoreGlobs = loadGitignorePatterns(rootPath);
262
+ globIgnore.push(...gitignoreGlobs);
263
+
264
+ const files = await fg('**/*', {
265
+ cwd: rootPath, absolute: true, onlyFiles: true, ignore: globIgnore, dot: true,
266
+ });
267
+
268
+ return files.filter(file => {
269
+ const ext = path.extname(file).toLowerCase();
270
+ if (SKIP_EXTENSIONS.has(ext)) return false;
271
+ if (SKIP_FILENAMES.has(path.basename(file))) return false;
272
+ if (path.basename(file).endsWith('.min.js') || path.basename(file).endsWith('.min.css')) return false;
273
+ try { if (fs.statSync(file).size > MAX_FILE_SIZE) return false; } catch { return false; }
274
+ return true;
275
+ });
276
+ }