praxis-sec 1.2.1 → 1.2.4
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/README.md +84 -115
- package/ai-defense/cost-protection.md +6 -0
- package/ai-defense/llm-security-checklist.md +6 -0
- package/ai-defense/system-prompt-armor.md +7 -1
- package/assets/praxis-architecture.svg +304 -0
- package/assets/praxis-logo.svg +38 -0
- package/checklists/launch-day.md +6 -7
- package/cli/agents/agent-telemetry-agent.js +2 -0
- package/cli/agents/api-fuzzer.js +2 -2
- package/cli/agents/git-history-scanner.js +14 -15
- package/cli/agents/html-reporter.js +9 -8
- package/cli/agents/mcp-security-agent.js +600 -594
- package/cli/agents/memory-poisoning-agent.js +1 -5
- package/cli/agents/orchestrator.js +375 -360
- package/cli/commands/agent-fix.js +3 -1
- package/cli/commands/audit.js +1272 -1228
- package/cli/commands/autofix.js +32 -13
- package/cli/commands/baseline.js +4 -2
- package/cli/commands/benchmark.js +2 -1
- package/cli/commands/ci.js +12 -8
- package/cli/commands/diff.js +2 -1
- package/cli/commands/env-audit.js +4 -2
- package/cli/commands/fix.js +2 -1
- package/cli/commands/legal.js +2 -1
- package/cli/commands/mcp.js +54 -51
- package/cli/commands/openclaw.js +3 -6
- package/cli/commands/red-team.js +2 -1
- package/cli/commands/remediate.js +2 -1
- package/cli/commands/rotate.js +2 -1
- package/cli/commands/scan-mcp.js +20 -9
- package/cli/commands/scan-standard.js +3 -6
- package/cli/commands/scan.js +15 -7
- package/cli/commands/score.js +2 -1
- package/cli/commands/vibe-check.js +4 -2
- package/cli/commands/watch.js +8 -6
- package/cli/core/glob.js +7 -5
- package/cli/core/output/json.js +56 -48
- package/cli/core/paths.js +91 -0
- package/cli/core/web/jobs.js +2 -0
- package/cli/data/documented-secret-examples.json +14 -0
- package/cli/utils/cache-manager.js +2 -1
- package/cli/utils/entropy.js +19 -0
- package/cli/utils/hermes-tool-registry.js +11 -9
- package/configs/firebase/security-checklist.md +3 -3
- package/configs/supabase/security-checklist.md +19 -21
- package/docs/RELEASE-1.2.4.md +85 -0
- package/docs/RELEASING.md +51 -0
- package/docs/THIRD_PARTY_NOTICES.md +8 -0
- package/docs/THREAT_INTEL.md +4 -2
- package/docs/USAGE.md +97 -76
- package/package.json +6 -4
- package/snippets/README.md +6 -0
- package/snippets/auth/jwt-checklist.md +14 -13
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="1340" viewBox="0 0 960 1340" role="img" aria-label="Praxis AI Security Architecture and Autonomous Fix Loop Flow">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Background Canvas Gradient -->
|
|
4
|
+
<linearGradient id="bgGrad" x1="0" y1="0" x2="0" y2="1">
|
|
5
|
+
<stop offset="0%" stop-color="#120726"/>
|
|
6
|
+
<stop offset="40%" stop-color="#090314"/>
|
|
7
|
+
<stop offset="100%" stop-color="#030108"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
|
|
10
|
+
<!-- Ambient Top Purple Glow -->
|
|
11
|
+
<radialGradient id="topGlow" cx="50%" cy="0%" r="50%">
|
|
12
|
+
<stop offset="0%" stop-color="#8b5cf6" stop-opacity="0.32"/>
|
|
13
|
+
<stop offset="100%" stop-color="#8b5cf6" stop-opacity="0"/>
|
|
14
|
+
</radialGradient>
|
|
15
|
+
|
|
16
|
+
<!-- Card Backgrounds -->
|
|
17
|
+
<linearGradient id="cardScan" x1="0" y1="0" x2="1" y2="0">
|
|
18
|
+
<stop offset="0%" stop-color="#1f0e38"/>
|
|
19
|
+
<stop offset="100%" stop-color="#130824"/>
|
|
20
|
+
</linearGradient>
|
|
21
|
+
|
|
22
|
+
<linearGradient id="cardNorm" x1="0" y1="0" x2="1" y2="0">
|
|
23
|
+
<stop offset="0%" stop-color="#241042"/>
|
|
24
|
+
<stop offset="100%" stop-color="#140926"/>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
|
|
27
|
+
<linearGradient id="cardLlm" x1="0" y1="0" x2="1" y2="0">
|
|
28
|
+
<stop offset="0%" stop-color="#2a0d4a"/>
|
|
29
|
+
<stop offset="100%" stop-color="#18072c"/>
|
|
30
|
+
</linearGradient>
|
|
31
|
+
|
|
32
|
+
<linearGradient id="cardVerify" x1="0" y1="0" x2="1" y2="0">
|
|
33
|
+
<stop offset="0%" stop-color="#0e2a22"/>
|
|
34
|
+
<stop offset="100%" stop-color="#081813"/>
|
|
35
|
+
</linearGradient>
|
|
36
|
+
|
|
37
|
+
<linearGradient id="cardHitl" x1="0" y1="0" x2="1" y2="0">
|
|
38
|
+
<stop offset="0%" stop-color="#241403"/>
|
|
39
|
+
<stop offset="100%" stop-color="#140a02"/>
|
|
40
|
+
</linearGradient>
|
|
41
|
+
|
|
42
|
+
<linearGradient id="cardSurfaces" x1="0" y1="0" x2="1" y2="0">
|
|
43
|
+
<stop offset="0%" stop-color="#082f49"/>
|
|
44
|
+
<stop offset="100%" stop-color="#04141f"/>
|
|
45
|
+
</linearGradient>
|
|
46
|
+
|
|
47
|
+
<!-- Brand Color Gradients -->
|
|
48
|
+
<linearGradient id="praxisGrad" x1="0" y1="0" x2="1" y2="0">
|
|
49
|
+
<stop offset="0%" stop-color="#c084fc"/>
|
|
50
|
+
<stop offset="50%" stop-color="#8b5cf6"/>
|
|
51
|
+
<stop offset="100%" stop-color="#6d28d9"/>
|
|
52
|
+
</linearGradient>
|
|
53
|
+
|
|
54
|
+
<linearGradient id="emeraldGrad" x1="0" y1="0" x2="1" y2="0">
|
|
55
|
+
<stop offset="0%" stop-color="#6ee7b7"/>
|
|
56
|
+
<stop offset="100%" stop-color="#10b981"/>
|
|
57
|
+
</linearGradient>
|
|
58
|
+
|
|
59
|
+
<linearGradient id="goldGrad" x1="0" y1="0" x2="1" y2="0">
|
|
60
|
+
<stop offset="0%" stop-color="#fde047"/>
|
|
61
|
+
<stop offset="100%" stop-color="#f59e0b"/>
|
|
62
|
+
</linearGradient>
|
|
63
|
+
|
|
64
|
+
<linearGradient id="cyanGrad" x1="0" y1="0" x2="1" y2="0">
|
|
65
|
+
<stop offset="0%" stop-color="#38bdf8"/>
|
|
66
|
+
<stop offset="100%" stop-color="#0284c7"/>
|
|
67
|
+
</linearGradient>
|
|
68
|
+
|
|
69
|
+
<!-- Glowing Filters -->
|
|
70
|
+
<filter id="shadow" x="-10%" y="-10%" width="120%" height="120%">
|
|
71
|
+
<feDropShadow dx="0" dy="6" stdDeviation="6" flood-color="#000000" flood-opacity="0.8"/>
|
|
72
|
+
</filter>
|
|
73
|
+
<filter id="glowPurple" x="-20%" y="-20%" width="140%" height="140%">
|
|
74
|
+
<feDropShadow dx="0" dy="0" stdDeviation="6" flood-color="#c084fc" flood-opacity="0.5"/>
|
|
75
|
+
</filter>
|
|
76
|
+
<filter id="glowGreen" x="-20%" y="-20%" width="140%" height="140%">
|
|
77
|
+
<feDropShadow dx="0" dy="0" stdDeviation="6" flood-color="#10b981" flood-opacity="0.5"/>
|
|
78
|
+
</filter>
|
|
79
|
+
|
|
80
|
+
<!-- Arrow Markers -->
|
|
81
|
+
<marker id="arrDownPurple" markerWidth="10" markerHeight="10" refX="5" refY="7" orient="auto">
|
|
82
|
+
<polygon points="0 0, 10 0, 5 8" fill="#c084fc"/>
|
|
83
|
+
</marker>
|
|
84
|
+
<marker id="arrDownCyan" markerWidth="10" markerHeight="10" refX="5" refY="7" orient="auto">
|
|
85
|
+
<polygon points="0 0, 10 0, 5 8" fill="#38bdf8"/>
|
|
86
|
+
</marker>
|
|
87
|
+
<marker id="arrDownGreen" markerWidth="10" markerHeight="10" refX="5" refY="7" orient="auto">
|
|
88
|
+
<polygon points="0 0, 10 0, 5 8" fill="#34d399"/>
|
|
89
|
+
</marker>
|
|
90
|
+
<marker id="arrDownGold" markerWidth="10" markerHeight="10" refX="5" refY="7" orient="auto">
|
|
91
|
+
<polygon points="0 0, 10 0, 5 8" fill="#f59e0b"/>
|
|
92
|
+
</marker>
|
|
93
|
+
</defs>
|
|
94
|
+
|
|
95
|
+
<!-- Base Canvas Background -->
|
|
96
|
+
<rect width="960" height="1340" fill="url(#bgGrad)"/>
|
|
97
|
+
<rect width="960" height="420" fill="url(#topGlow)"/>
|
|
98
|
+
|
|
99
|
+
<!-- ========================================================================= -->
|
|
100
|
+
<!-- HEADER & LOGO -->
|
|
101
|
+
<!-- ========================================================================= -->
|
|
102
|
+
<g transform="translate(480, 48)">
|
|
103
|
+
<!-- Shield Logo Icon -->
|
|
104
|
+
<g transform="translate(-295, -26) scale(0.38)">
|
|
105
|
+
<path d="M55 0 L110 18 V62 C110 100 86 128 55 145 C24 128 0 100 0 62 V18 Z" fill="url(#praxisGrad)" stroke="#4c1d95" stroke-width="3"/>
|
|
106
|
+
<path d="M55 24 L82 40 V66 C82 92 68 110 55 120 C42 110 28 92 28 66 V40 Z" fill="#ffffff" opacity="0.95"/>
|
|
107
|
+
</g>
|
|
108
|
+
<text x="24" y="8" text-anchor="middle" font-family="'Segoe UI', -apple-system, sans-serif" font-size="32" font-weight="900" letter-spacing="0.5">
|
|
109
|
+
<tspan fill="url(#praxisGrad)">PRAXIS</tspan>
|
|
110
|
+
<tspan fill="#ffffff" font-weight="800"> | ARCHITECTURE FLOW</tspan>
|
|
111
|
+
</text>
|
|
112
|
+
<text x="0" y="38" text-anchor="middle" font-family="'Segoe UI', -apple-system, sans-serif" font-size="15" font-weight="600" fill="#e9d5ff">
|
|
113
|
+
28-Agent Parallel Audit · AST Taint · Remote Git Scanning · 4-Tier Verification · Autonomous Fix
|
|
114
|
+
</text>
|
|
115
|
+
</g>
|
|
116
|
+
|
|
117
|
+
<!-- ========================================================================= -->
|
|
118
|
+
<!-- STEP 1: 28-AGENT CONCURRENT STATIC & AST AUDIT (y=110, h=155) -->
|
|
119
|
+
<!-- ========================================================================= -->
|
|
120
|
+
<g transform="translate(90, 110)" filter="url(#shadow)">
|
|
121
|
+
<rect x="0" y="0" width="780" height="155" rx="14" fill="url(#cardScan)" stroke="#7c3aed" stroke-width="2" filter="url(#glowPurple)"/>
|
|
122
|
+
|
|
123
|
+
<!-- Stage Header Badge -->
|
|
124
|
+
<circle cx="28" cy="28" r="16" fill="#7c3aed"/>
|
|
125
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#ffffff">1</text>
|
|
126
|
+
|
|
127
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">28-AGENT PARALLEL AUDIT & AST TAINT CORE</text>
|
|
128
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#2e1065" stroke="#a855f7" stroke-width="1.2"/>
|
|
129
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="800" fill="#c084fc">DETERMINISTIC</text>
|
|
130
|
+
|
|
131
|
+
<!-- Sub-bullets -->
|
|
132
|
+
<g transform="translate(24, 60)">
|
|
133
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">28 Concurrent Agents:</tspan> Prompt Injection · MCP Abuse · Memory Poisoning · RAG · Pickles · Auth</text>
|
|
134
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">AST & Taint Engine:</tspan> Pure ESM Babel (JS/TS) & Python CST with ScopeTree & Source-to-Sink Taint</text>
|
|
135
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#34d399">• <tspan font-weight="700">100% Offline & Free:</tspan> 0 token cost, 125 secret & code patterns, 7 cached Threat Intel feeds</text>
|
|
136
|
+
</g>
|
|
137
|
+
</g>
|
|
138
|
+
|
|
139
|
+
<!-- Connector 1 -> 2 -->
|
|
140
|
+
<g transform="translate(480, 265)">
|
|
141
|
+
<line x1="0" y1="0" x2="0" y2="35" stroke="#c084fc" stroke-width="3.5" marker-end="url(#arrDownPurple)"/>
|
|
142
|
+
<rect x="-140" y="8" width="280" height="22" rx="4" fill="#241042" stroke="#7c3aed" stroke-width="1"/>
|
|
143
|
+
<text x="0" y="24" text-anchor="middle" font-family="sans-serif" font-size="11.5" font-weight="800" fill="#e9d5ff">Raw Findings & AST Taint Graphs</text>
|
|
144
|
+
</g>
|
|
145
|
+
|
|
146
|
+
<!-- ========================================================================= -->
|
|
147
|
+
<!-- STEP 2: ACCURACY, STANDARDS & ABOM MATRIX (y=305, h=145) -->
|
|
148
|
+
<!-- ========================================================================= -->
|
|
149
|
+
<g transform="translate(90, 305)" filter="url(#shadow)">
|
|
150
|
+
<rect x="0" y="0" width="780" height="145" rx="14" fill="url(#cardNorm)" stroke="#9333ea" stroke-width="2"/>
|
|
151
|
+
|
|
152
|
+
<!-- Stage Header Badge -->
|
|
153
|
+
<circle cx="28" cy="28" r="16" fill="#9333ea"/>
|
|
154
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#ffffff">2</text>
|
|
155
|
+
|
|
156
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">8-FRAMEWORK STANDARDS MAPPING & ABOM</text>
|
|
157
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#3b0764" stroke="#c084fc" stroke-width="1.2"/>
|
|
158
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="800" fill="#e9d5ff">COMPLIANCE</text>
|
|
159
|
+
|
|
160
|
+
<!-- Sub-bullets -->
|
|
161
|
+
<g transform="translate(24, 60)">
|
|
162
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">8 Security Standards:</tspan> OWASP LLM 2025 · MITRE ATLAS · NIST AI 600-1 · EU AI Act (Art 12/14) · ISO 42001</text>
|
|
163
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">CycloneDX 1.5 ABOM:</tspan> Full Agent Bill of Materials (Prompts, Tools, Models, Skills & MCP Trust)</text>
|
|
164
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#38bdf8">• <tspan font-weight="700">Scoring Engine:</tspan> Computes 0–100 Health Score & Letter Grade (A–F) with Category Deductions</text>
|
|
165
|
+
</g>
|
|
166
|
+
</g>
|
|
167
|
+
|
|
168
|
+
<!-- Connector 2 -> 3 -->
|
|
169
|
+
<g transform="translate(480, 450)">
|
|
170
|
+
<line x1="0" y1="0" x2="0" y2="35" stroke="#38bdf8" stroke-width="3.5" marker-end="url(#arrDownCyan)"/>
|
|
171
|
+
<rect x="-140" y="8" width="280" height="22" rx="4" fill="#082230" stroke="#0284c7" stroke-width="1"/>
|
|
172
|
+
<text x="0" y="24" text-anchor="middle" font-family="sans-serif" font-size="11.5" font-weight="800" fill="#38bdf8">Deep Analysis / `praxis fix` Trigger</text>
|
|
173
|
+
</g>
|
|
174
|
+
|
|
175
|
+
<!-- ========================================================================= -->
|
|
176
|
+
<!-- STEP 3: COGNITIVE LLM REASONING & REMEDIATION (y=490, h=155) -->
|
|
177
|
+
<!-- ========================================================================= -->
|
|
178
|
+
<g transform="translate(90, 490)" filter="url(#shadow)">
|
|
179
|
+
<rect x="0" y="0" width="780" height="155" rx="14" fill="url(#cardLlm)" stroke="#c084fc" stroke-width="2.2" filter="url(#glowPurple)"/>
|
|
180
|
+
|
|
181
|
+
<!-- Stage Header Badge -->
|
|
182
|
+
<circle cx="28" cy="28" r="16" fill="url(#praxisGrad)"/>
|
|
183
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#ffffff">3</text>
|
|
184
|
+
|
|
185
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">COGNITIVE LLM REASONING & PATCH DRAFTING</text>
|
|
186
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#3b0764" stroke="#c084fc" stroke-width="1.2"/>
|
|
187
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="900" fill="#e9d5ff">AGENTIC AI</text>
|
|
188
|
+
|
|
189
|
+
<!-- Sub-bullets -->
|
|
190
|
+
<g transform="translate(24, 60)">
|
|
191
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">Multi-LLM Router:</tspan> Anthropic Claude · OpenAI · DeepSeek · Google Gemini · Local Ollama (`--local`)</text>
|
|
192
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#f3e8ff">• <tspan font-weight="700">Exploitability Triage:</tspan> Evaluates call-site reachability & attack vectors to eliminate false alarms</text>
|
|
193
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#34d399">• <tspan font-weight="700">Autonomous Code Fix:</tspan> Drafts contextual, multi-file code patches & unit regression tests</text>
|
|
194
|
+
</g>
|
|
195
|
+
</g>
|
|
196
|
+
|
|
197
|
+
<!-- Connector 3 -> 4 -->
|
|
198
|
+
<g transform="translate(480, 645)">
|
|
199
|
+
<line x1="0" y1="0" x2="0" y2="35" stroke="#34d399" stroke-width="3.5" marker-end="url(#arrDownGreen)"/>
|
|
200
|
+
<rect x="-145" y="8" width="290" height="22" rx="4" fill="#09281a" stroke="#10b981" stroke-width="1"/>
|
|
201
|
+
<text x="0" y="24" text-anchor="middle" font-family="sans-serif" font-size="11.5" font-weight="800" fill="#34d399">Draft Diffs to Verification Oracles</text>
|
|
202
|
+
</g>
|
|
203
|
+
|
|
204
|
+
<!-- ========================================================================= -->
|
|
205
|
+
<!-- STEP 4: 4-TIER EXECUTABLE VERIFICATION LADDER (y=685, h=165) -->
|
|
206
|
+
<!-- ========================================================================= -->
|
|
207
|
+
<g transform="translate(90, 685)" filter="url(#shadow)">
|
|
208
|
+
<rect x="0" y="0" width="780" height="165" rx="14" fill="url(#cardVerify)" stroke="#10b981" stroke-width="2.2" filter="url(#glowGreen)"/>
|
|
209
|
+
|
|
210
|
+
<!-- Stage Header Badge -->
|
|
211
|
+
<circle cx="28" cy="28" r="16" fill="url(#emeraldGrad)"/>
|
|
212
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#042316">4</text>
|
|
213
|
+
|
|
214
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">4-TIER EXECUTABLE VERIFICATION LADDER</text>
|
|
215
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#0c2b1e" stroke="#10b981" stroke-width="1.2"/>
|
|
216
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="900" fill="#34d399">ORACLES</text>
|
|
217
|
+
|
|
218
|
+
<!-- Sub-bullets -->
|
|
219
|
+
<g transform="translate(24, 60)">
|
|
220
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#a7f3d0">• <tspan font-weight="700">Tier 1 (AST Syntax Oracle):</tspan> Validates AST node integrity before any file is touched</text>
|
|
221
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#a7f3d0">• <tspan font-weight="700">Tier 2 (Build Oracle):</tspan> Executes project build (`npm run build` / `tsc`) to ensure 0 compiler errors</text>
|
|
222
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#a7f3d0">• <tspan font-weight="700">Tier 3 (Test Suite Oracle):</tspan> Runs unit test suite to guarantee zero functionality regressions</text>
|
|
223
|
+
<text x="0" y="92" font-family="sans-serif" font-size="14.5" font-weight="800" fill="#34d399">• <tspan font-weight="700">Tier 4 (Re-scan Oracle):</tspan> Confirms finding resolution — <tspan font-weight="700">Auto-reverts on any oracle failure</tspan></text>
|
|
224
|
+
</g>
|
|
225
|
+
</g>
|
|
226
|
+
|
|
227
|
+
<!-- Connector 4 -> 5 -->
|
|
228
|
+
<g transform="translate(480, 850)">
|
|
229
|
+
<line x1="0" y1="0" x2="0" y2="35" stroke="#f59e0b" stroke-width="3.5" marker-end="url(#arrDownGold)"/>
|
|
230
|
+
<rect x="-140" y="8" width="280" height="22" rx="4" fill="#241403" stroke="#f59e0b" stroke-width="1"/>
|
|
231
|
+
<text x="0" y="24" text-anchor="middle" font-family="sans-serif" font-size="11.5" font-weight="800" fill="#fde047">Verified Diffs to Operator Review</text>
|
|
232
|
+
</g>
|
|
233
|
+
|
|
234
|
+
<!-- ========================================================================= -->
|
|
235
|
+
<!-- STEP 5: HITL APPROVAL & ATOMIC APPLY (y=890, h=165) -->
|
|
236
|
+
<!-- ========================================================================= -->
|
|
237
|
+
<g transform="translate(90, 890)" filter="url(#shadow)">
|
|
238
|
+
<rect x="0" y="0" width="780" height="165" rx="14" fill="url(#cardHitl)" stroke="#f59e0b" stroke-width="2.2"/>
|
|
239
|
+
|
|
240
|
+
<!-- Stage Header Badge -->
|
|
241
|
+
<circle cx="28" cy="28" r="16" fill="url(#goldGrad)"/>
|
|
242
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#0c0701">5</text>
|
|
243
|
+
|
|
244
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">HUMAN APPROVAL, ATOMIC APPLY & REPORT SUITE</text>
|
|
245
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#382006" stroke="#f59e0b" stroke-width="1.2"/>
|
|
246
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="900" fill="#fde047">HUMAN-IN-LOOP</text>
|
|
247
|
+
|
|
248
|
+
<!-- Sub-bullets -->
|
|
249
|
+
<g transform="translate(24, 60)">
|
|
250
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#fef08a">• <tspan font-weight="700">Interactive Diff Review:</tspan> Developer inspects verified patch before any disk write</text>
|
|
251
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#fef08a">• <tspan font-weight="700">Atomic Apply:</tspan> boundary + symlink checks, all-or-nothing rollback, hash-based `praxis undo`</text>
|
|
252
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#38bdf8">• <tspan font-weight="700">Assessment Report:</tspan> single-file tabbed HTML — agent coverage, AST taint, ledger, trend</text>
|
|
253
|
+
<text x="0" y="92" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#34d399">• CI/CD Native: Net-new PR gating, SARIF export to GitHub Code Scanning & PR annotations</text>
|
|
254
|
+
</g>
|
|
255
|
+
</g>
|
|
256
|
+
|
|
257
|
+
<!-- ========================================================================= -->
|
|
258
|
+
<!-- LEFT RETURN CONDUIT (Closed Autopilot Loop: Step 5 -> Step 1) -->
|
|
259
|
+
<!-- ========================================================================= -->
|
|
260
|
+
<path d="M 90 975 L 35 975 L 35 185 L 85 185" fill="none" stroke="#8b5cf6" stroke-width="3.5" stroke-dasharray="10 5"/>
|
|
261
|
+
<polygon points="85,185 70,175 70,195" fill="#c084fc"/>
|
|
262
|
+
|
|
263
|
+
<!-- Vertical Feedback Tag -->
|
|
264
|
+
<g transform="translate(25, 580) rotate(-90)">
|
|
265
|
+
<rect x="-160" y="-12" width="320" height="24" rx="4" fill="#1f0e38" stroke="#8b5cf6" stroke-width="1.2"/>
|
|
266
|
+
<text x="0" y="4" text-anchor="middle" font-family="sans-serif" font-size="11.5" font-weight="800" fill="#e9d5ff" letter-spacing="0.5">
|
|
267
|
+
↻ AUTONOMOUS FIX → VERIFY LOOP
|
|
268
|
+
</text>
|
|
269
|
+
</g>
|
|
270
|
+
|
|
271
|
+
<!-- ========================================================================= -->
|
|
272
|
+
<!-- STAGE 6 : OUTPUT SURFACES, PORTABILITY & REPRODUCIBILITY -->
|
|
273
|
+
<!-- ========================================================================= -->
|
|
274
|
+
<path d="M 480 1055 L 480 1087" fill="none" stroke="#38bdf8" stroke-width="3.5" marker-end="url(#arrDownCyan)"/>
|
|
275
|
+
|
|
276
|
+
<g transform="translate(90, 1095)" filter="url(#shadow)">
|
|
277
|
+
<rect x="0" y="0" width="780" height="165" rx="14" fill="url(#cardSurfaces)" stroke="#38bdf8" stroke-width="2.2"/>
|
|
278
|
+
|
|
279
|
+
<!-- Stage Header Badge -->
|
|
280
|
+
<circle cx="28" cy="28" r="16" fill="url(#cyanGrad)"/>
|
|
281
|
+
<text x="28" y="34" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="900" fill="#04141f">6</text>
|
|
282
|
+
|
|
283
|
+
<text x="56" y="34" font-family="sans-serif" font-size="18.5" font-weight="900" fill="#ffffff">OUTPUT SURFACES & REPRODUCIBILITY</text>
|
|
284
|
+
<rect x="635" y="14" width="130" height="28" rx="6" fill="#082f49" stroke="#38bdf8" stroke-width="1.2"/>
|
|
285
|
+
<text x="700" y="32" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="900" fill="#7dd3fc">READ-ONLY</text>
|
|
286
|
+
|
|
287
|
+
<!-- Sub-bullets -->
|
|
288
|
+
<g transform="translate(24, 60)">
|
|
289
|
+
<text x="0" y="16" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#bae6fd">• <tspan font-weight="700">Web UI:</tspan> <tspan fill="#7dd3fc">`praxis web`</tspan> — Security Studio, live SSE, loopback-only, secrets redacted</text>
|
|
290
|
+
<text x="0" y="42" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#bae6fd">• <tspan font-weight="700">Portable Rules:</tspan> <tspan fill="#7dd3fc">`praxis rules export`</tspan> — 411 pattern rules as Semgrep YAML</text>
|
|
291
|
+
<text x="0" y="68" font-family="sans-serif" font-size="14.5" font-weight="600" fill="#bae6fd">• <tspan font-weight="700">Code Scanning:</tspan> SARIF carries numeric <tspan fill="#7dd3fc">`security-severity`</tspan> so alerts rank properly</text>
|
|
292
|
+
<text x="0" y="92" font-family="sans-serif" font-size="14.5" font-weight="700" fill="#34d399">• Reproducible: scan fingerprint + CI determinism gate over <tspan fill="#a7f3d0">`file::rule`</tspan> identities</text>
|
|
293
|
+
</g>
|
|
294
|
+
</g>
|
|
295
|
+
|
|
296
|
+
<!-- ========================================================================= -->
|
|
297
|
+
<!-- FOOTER -->
|
|
298
|
+
<!-- ========================================================================= -->
|
|
299
|
+
<g transform="translate(480, 1300)">
|
|
300
|
+
<text text-anchor="middle" font-family="'Segoe UI', sans-serif" font-size="13.5" font-weight="600" fill="#c084fc">
|
|
301
|
+
Node.js ≥ 18 · Pure ESM · 28 Security Agents · 4-Tier Verification Ladder · Multi-LLM Autopilot
|
|
302
|
+
</text>
|
|
303
|
+
</g>
|
|
304
|
+
</svg>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="620" height="180" viewBox="0 0 620 180" role="img" aria-label="Praxis logo">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Base Shield Gradient (Vibrant purple to deep violet) -->
|
|
4
|
+
<linearGradient id="purpleGrad" x1="0" y1="0" x2="1" y2="1">
|
|
5
|
+
<stop offset="0%" stop-color="#c084fc"/>
|
|
6
|
+
<stop offset="55%" stop-color="#7c3aed"/>
|
|
7
|
+
<stop offset="100%" stop-color="#4c1d95"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
<!-- Wordmark Gradient (Fuchsia to violet) -->
|
|
10
|
+
<linearGradient id="wordGrad" x1="0" y1="0" x2="1" y2="0">
|
|
11
|
+
<stop offset="0%" stop-color="#e879f9"/>
|
|
12
|
+
<stop offset="100%" stop-color="#7c3aed"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
</defs>
|
|
15
|
+
|
|
16
|
+
<!-- Shield icon with find-fix-verify loop and AI sparkle -->
|
|
17
|
+
<g transform="translate(24,28)">
|
|
18
|
+
<!-- Sleek outer shield path -->
|
|
19
|
+
<path d="M55 0 L110 18 V62 C110 100 86 128 55 145 C24 128 0 100 0 62 V18 Z"
|
|
20
|
+
fill="url(#purpleGrad)" stroke="#3b0764" stroke-width="2"/>
|
|
21
|
+
|
|
22
|
+
<!-- Clockwise reload/loop arrow (the "remediation loop") -->
|
|
23
|
+
<path d="M55 35 A35 35 0 1 1 20 70 H32 A23 23 0 1 0 55 47 V60 L75 41 L55 22 V35 Z"
|
|
24
|
+
fill="#ffffff" opacity="0.95"/>
|
|
25
|
+
|
|
26
|
+
<!-- 4-point AI sparkle star (representing autopilot / agent intelligence) -->
|
|
27
|
+
<path d="M55 52 Q55 70 73 70 Q55 70 55 88 Q55 70 37 70 Q55 70 55 52 Z"
|
|
28
|
+
fill="#ffffff" opacity="0.95"/>
|
|
29
|
+
</g>
|
|
30
|
+
|
|
31
|
+
<!-- Wordmark -->
|
|
32
|
+
<text x="160" y="86" font-family="Segoe UI, Helvetica, Arial, sans-serif"
|
|
33
|
+
font-size="56" font-weight="800" fill="url(#wordGrad)" letter-spacing="-1">Praxis</text>
|
|
34
|
+
|
|
35
|
+
<!-- Tagline under the wordmark -->
|
|
36
|
+
<text x="162" y="120" font-family="Segoe UI, Helvetica, Arial, sans-serif"
|
|
37
|
+
font-size="19" font-weight="600" fill="#6b7280" letter-spacing="0.4">Autonomous AI-Security Audit Framework</text>
|
|
38
|
+
</svg>
|
package/checklists/launch-day.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Launch Day Security Checklist
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use this checklist to plan release verification. The checks are starting points; their effort and required evidence depend on the application.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
```bash
|
|
14
14
|
curl -I https://yoursite.com/.git/config
|
|
15
15
|
```
|
|
16
|
-
|
|
16
|
+
Inspect the response body: a 200 response alone may be a generic application page. Confirm that Git metadata is inaccessible.
|
|
17
17
|
|
|
18
18
|
**Fix:** Configure your web server to deny access to `.git`:
|
|
19
19
|
- Nginx: `location ~ /\.git { deny all; }`
|
|
20
|
-
-
|
|
20
|
+
- Hosted platforms: verify the deployed behavior rather than assuming a default
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -136,7 +136,6 @@ Try accessing:
|
|
|
136
136
|
- `/admin`
|
|
137
137
|
- `/api/admin`
|
|
138
138
|
- `/dashboard`
|
|
139
|
-
- `/_next` (for Next.js internal routes)
|
|
140
139
|
|
|
141
140
|
**Fix:**
|
|
142
141
|
- Add authentication middleware to all admin routes
|
|
@@ -151,7 +150,7 @@ Try accessing:
|
|
|
151
150
|
- [ ] **CORS configured:** Not set to `*` in production
|
|
152
151
|
- [ ] **Cookies secured:** `HttpOnly`, `Secure`, `SameSite` flags set
|
|
153
152
|
- [ ] **File uploads validated:** Check file types, not just extensions
|
|
154
|
-
- [ ] **SQL/NoSQL injection tested:**
|
|
153
|
+
- [ ] **SQL/NoSQL injection tested:** Use harmless probes in an authorized test environment and verify parameterized queries
|
|
155
154
|
|
|
156
155
|
---
|
|
157
156
|
|
|
@@ -161,8 +160,8 @@ Security is ongoing. Schedule monthly reviews:
|
|
|
161
160
|
1. Re-run this checklist
|
|
162
161
|
2. Check for dependency updates
|
|
163
162
|
3. Review access logs for suspicious activity
|
|
164
|
-
4.
|
|
163
|
+
4. Review credential exposure and rotate keys according to provider guidance and incident requirements
|
|
165
164
|
|
|
166
165
|
---
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
Record the evidence, unresolved findings, and the owner of each release decision.
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import fs from 'fs';
|
|
26
26
|
import { BaseAgent, createFinding, ruleTableLineMask } from './base-agent.js';
|
|
27
|
+
import { isDocumentedSecretExample } from '../utils/entropy.js';
|
|
27
28
|
|
|
28
29
|
// =============================================================================
|
|
29
30
|
// PATTERNS & REGEXES
|
|
@@ -304,6 +305,7 @@ export class AgentTelemetryAgent extends BaseAgent {
|
|
|
304
305
|
pattern.regex.lastIndex = 0;
|
|
305
306
|
let match;
|
|
306
307
|
while ((match = pattern.regex.exec(lines[i])) !== null) {
|
|
308
|
+
if (isDocumentedSecretExample(pattern.rule, match[0])) continue;
|
|
307
309
|
// Skip placeholder credential values (docs/examples) for the
|
|
308
310
|
// generic secret-kv rule only.
|
|
309
311
|
if (pattern.rule === 'AGENT_LOG_SECRET_KV' && PLACEHOLDER_VALUE.test(match[1] || '')) break;
|
package/cli/agents/api-fuzzer.js
CHANGED
|
@@ -88,7 +88,7 @@ export const PATTERNS = [
|
|
|
88
88
|
{
|
|
89
89
|
rule: 'API_UPLOAD_NO_TYPE_CHECK',
|
|
90
90
|
title: 'API: File Upload Without Type Validation',
|
|
91
|
-
regex:
|
|
91
|
+
regex: /\b(?:file|upload|uploadedFile|req\.file|request\.file)\.originalname\s*(?:\)|;)/g,
|
|
92
92
|
severity: 'high',
|
|
93
93
|
cwe: 'CWE-434',
|
|
94
94
|
owasp: 'A04:2021',
|
|
@@ -99,7 +99,7 @@ export const PATTERNS = [
|
|
|
99
99
|
{
|
|
100
100
|
rule: 'API_PATH_IN_FILENAME',
|
|
101
101
|
title: 'API: Path Traversal in File Upload',
|
|
102
|
-
regex: /path\.join\s*\([^)]*(?:
|
|
102
|
+
regex: /path\.join\s*\([^)]*(?:\b(?:req|request)\.(?:files?|body|query|params)\b|\b[\w$]+\.originalname\b)/g,
|
|
103
103
|
severity: 'critical',
|
|
104
104
|
cwe: 'CWE-22',
|
|
105
105
|
owasp: 'A01:2021',
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
import { execSync, execFileSync } from 'child_process';
|
|
12
12
|
import path from 'path';
|
|
13
|
+
import { createHash } from 'crypto';
|
|
13
14
|
import { BaseAgent, createFinding } from './base-agent.js';
|
|
14
15
|
import { SECRET_PATTERNS } from '../utils/patterns.js';
|
|
16
|
+
import { isDocumentedSecretExample } from '../utils/entropy.js';
|
|
15
17
|
|
|
16
18
|
// Compile a fast combined regex from all secret patterns
|
|
17
19
|
const FAST_SECRET_PATTERNS = SECRET_PATTERNS.map(p => ({
|
|
@@ -28,6 +30,7 @@ export class GitHistoryScanner extends BaseAgent {
|
|
|
28
30
|
async analyze(context) {
|
|
29
31
|
const { rootPath, options } = context;
|
|
30
32
|
const findings = [];
|
|
33
|
+
const seen = new Set();
|
|
31
34
|
|
|
32
35
|
// Check if this is a git repository
|
|
33
36
|
if (!this.isGitRepo(rootPath)) return [];
|
|
@@ -50,9 +53,8 @@ export class GitHistoryScanner extends BaseAgent {
|
|
|
50
53
|
maxBuffer: 50 * 1024 * 1024, // 50MB buffer
|
|
51
54
|
timeout: 60000, // 60s timeout
|
|
52
55
|
});
|
|
53
|
-
} catch {
|
|
54
|
-
|
|
55
|
-
return [];
|
|
56
|
+
} catch (err) {
|
|
57
|
+
throw new Error(`Git history scan failed: ${err.message}`);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
if (!diffOutput) return [];
|
|
@@ -88,8 +90,12 @@ export class GitHistoryScanner extends BaseAgent {
|
|
|
88
90
|
// Check against all secret patterns
|
|
89
91
|
for (const p of FAST_SECRET_PATTERNS) {
|
|
90
92
|
p.pattern.lastIndex = 0;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
let match;
|
|
94
|
+
while ((match = p.pattern.exec(addedLine)) !== null) {
|
|
95
|
+
if (isDocumentedSecretExample(p.name, match[0])) continue;
|
|
96
|
+
const key = `${p.name}:${createHash('sha256').update(match[0]).digest('hex')}`;
|
|
97
|
+
if (seen.has(key)) continue;
|
|
98
|
+
seen.add(key);
|
|
93
99
|
// Check if this secret still exists in current working tree
|
|
94
100
|
const stillExists = this.existsInWorkingTree(rootPath, match[0]);
|
|
95
101
|
|
|
@@ -113,18 +119,11 @@ export class GitHistoryScanner extends BaseAgent {
|
|
|
113
119
|
}
|
|
114
120
|
}
|
|
115
121
|
|
|
116
|
-
|
|
117
|
-
const seen = new Set();
|
|
118
|
-
return findings.filter(f => {
|
|
119
|
-
const key = `${f.matched}:${f.title}`;
|
|
120
|
-
if (seen.has(key)) return false;
|
|
121
|
-
seen.add(key);
|
|
122
|
-
return true;
|
|
123
|
-
});
|
|
122
|
+
return findings;
|
|
124
123
|
|
|
125
124
|
} catch (err) {
|
|
126
|
-
//
|
|
127
|
-
|
|
125
|
+
// Let the orchestrator mark this scanner incomplete instead of clean.
|
|
126
|
+
throw new Error(`GitHistoryScanner incomplete: ${err.message}`, { cause: err });
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
129
|
|
|
@@ -33,6 +33,7 @@ import { buildScanFingerprint, fingerprintLine } from '../utils/scan-fingerprint
|
|
|
33
33
|
import { readFixLedger, summarizeFixLedger, isReversible } from '../utils/fix-ledger.js';
|
|
34
34
|
import { readScoreHistory, summarizeHistory } from '../utils/score-history.js';
|
|
35
35
|
import { toolVersion } from '../core/version.js';
|
|
36
|
+
import { displayPath } from '../core/paths.js';
|
|
36
37
|
|
|
37
38
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
38
39
|
const PKG_VERSION = toolVersion();
|
|
@@ -44,13 +45,12 @@ export class HTMLReporter {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
normalizePath(filePath, rootPath) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return norm.replace(/^[a-zA-Z]:\/+/, '').replace(/^.*\/Praxis\/showcase-target\//, '').replace(/^.*\/showcase-target\//, '');
|
|
48
|
+
// Paths reach the reporter already normalised by the orchestrator, so this only
|
|
49
|
+
// has to fall back for callers that build findings themselves. The strippers
|
|
50
|
+
// that used to live here leaked the username into every HTML report and
|
|
51
|
+
// truncated any real path containing a directory called `Praxis` — see
|
|
52
|
+
// cli/core/paths.js.
|
|
53
|
+
return displayPath(filePath, rootPath);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -177,6 +177,7 @@ export class HTMLReporter {
|
|
|
177
177
|
</div>
|
|
178
178
|
</div>
|
|
179
179
|
</header>
|
|
180
|
+
${scoreResult.scanComplete === false ? '<p role="alert" class="sev-badge sev-high">SCAN INCOMPLETE — score reflects only available results. Review scan errors before trusting this report.</p>' : ''}
|
|
180
181
|
`;
|
|
181
182
|
}
|
|
182
183
|
|
|
@@ -1122,4 +1123,4 @@ function toggleDetail(id) {
|
|
|
1122
1123
|
}
|
|
1123
1124
|
}
|
|
1124
1125
|
|
|
1125
|
-
export default HTMLReporter;
|
|
1126
|
+
export default HTMLReporter;
|