@goodandready/dsh-moa 0.2.75 → 0.2.77

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.
@@ -0,0 +1,290 @@
1
+ /**
2
+ * DeepSeek Harness Mixture of Agents (MoA) — Adversarial Security Fuzzing Gate (#302)
3
+ *
4
+ * White-Hat Red Team security gate that audits candidate code proposals for critical
5
+ * vulnerabilities, injection vectors, memory exhaustion, prototype pollution, and CWE patterns
6
+ * before final Judge arbitration.
7
+ */
8
+
9
+ import { MOA_EVENTS, emitEvent } from '../events.js'
10
+
11
+ /**
12
+ * Known vulnerability rule signatures with CWE classifications.
13
+ */
14
+ export const SECURITY_RULES = [
15
+ {
16
+ cwe: 'CWE-89',
17
+ title: 'SQL Injection Risk',
18
+ severity: 'critical',
19
+ regex: /(?:SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s+[^;`'"]*?(\$\{[^}]+\}|['"`]\s*\+\s*[a-zA-Z0-9_]+)/i,
20
+ detail: 'Unsanitized query construction using string interpolation or concatenation instead of parameterized bindings.',
21
+ },
22
+ {
23
+ cwe: 'CWE-78',
24
+ title: 'OS Command Injection',
25
+ severity: 'critical',
26
+ regex: /(?:child_process\.)?(?:exec|execSync)\s*\(\s*(?:`[^`]*\$\{[^}]+\}[^`]*`|['"][^'"]*['"]\s*\+)/i,
27
+ detail: 'Executing shell commands with interpolated or concatenated untrusted input.',
28
+ },
29
+ {
30
+ cwe: 'CWE-78',
31
+ title: 'Shell Invocation with Dynamic Arguments',
32
+ severity: 'critical',
33
+ regex: /spawn\s*\([^,]+,\s*\{[^}]*shell\s*:\s*true/i,
34
+ detail: 'Invoking child_process.spawn with shell: true exposes process to command injection.',
35
+ },
36
+ {
37
+ cwe: 'CWE-22',
38
+ title: 'Path Traversal Vulnerability',
39
+ severity: 'high',
40
+ regex: /(?:readFile|writeFile|createReadStream|createWriteStream|unlink|stat)\s*\([^)]*?(?:\.\.\/|\.\.\\)/i,
41
+ detail: 'File system operation contains unconstrained relative path traversal sequences (../).',
42
+ },
43
+ {
44
+ cwe: 'CWE-79',
45
+ title: 'Cross-Site Scripting (DOM XSS)',
46
+ severity: 'high',
47
+ regex: /(?:\.innerHTML\s*=|document\.write\s*\(|dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(?!DOMPurify|sanitize))/i,
48
+ detail: 'Unescaped HTML or DOM insertion allows arbitrary script execution in browser contexts.',
49
+ },
50
+ {
51
+ cwe: 'CWE-1321',
52
+ title: 'Prototype Pollution',
53
+ severity: 'critical',
54
+ regex: /(?:__proto__|constructor\s*\[\s*['"`]prototype['"`]\s*\]|prototype\s*\[\s*['"`]\w+['"`]\s*\]\s*=)/i,
55
+ detail: 'Direct modification of object prototype chain may lead to remote code execution or privilege escalation.',
56
+ },
57
+ {
58
+ cwe: 'CWE-400',
59
+ title: 'Regular Expression Denial of Service (ReDoS)',
60
+ severity: 'high',
61
+ regex: /\/(?:[^\/\\]|\\.)*(?:\([^\)]*[\+\*]\)[^\)]*[\+\*]|\([^\)]*\|[^\)]*\)[\+\*])(?:[^\/\\]|\\.)*\//,
62
+ detail: 'Regular expression pattern contains nested quantifiers with catastrophic polynomial/exponential backtracking.',
63
+ },
64
+ {
65
+ cwe: 'CWE-798',
66
+ title: 'Hardcoded Cryptographic Secret / Credential',
67
+ severity: 'high',
68
+ regex: /(?:api_?key|auth_?token|secret_?key|private_?key|bearer_?token)\s*[:=]\s*['"`](?:sk_live_[0-9a-zA-Z]{16,}|ghp_[0-9a-zA-Z]{20,}|ey[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,})['"`]/i,
69
+ detail: 'Production-like API token, private key, or credential embedded directly in source code.',
70
+ },
71
+ {
72
+ cwe: 'CWE-362',
73
+ title: 'TOCTOU Concurrency Race Condition',
74
+ severity: 'medium',
75
+ regex: /fs\.existsSync\s*\([^)]+\)[\s\S]{1,80}?fs\.(?:writeFileSync|appendFileSync)\s*\(/i,
76
+ detail: 'Non-atomic check-then-act pattern creates file race condition under concurrent operations.',
77
+ },
78
+ ]
79
+
80
+ /**
81
+ * Audits a code snippet or model response for security vulnerabilities.
82
+ *
83
+ * @param {string} code - Candidate response text or extracted code
84
+ * @param {object} [options]
85
+ * @returns {object} Audit report with score, findings, and veto flag
86
+ */
87
+ export function auditCodeSecurity(code, options = {}) {
88
+ if (!code || typeof code !== 'string') {
89
+ return {
90
+ veto: false,
91
+ score: 100,
92
+ findings: [],
93
+ summary: 'Clean: No executable code provided for security audit.',
94
+ }
95
+ }
96
+
97
+ const findings = []
98
+ const lines = code.split('\n')
99
+
100
+ for (const rule of SECURITY_RULES) {
101
+ if (rule.regex.test(code)) {
102
+ // Pinpoint line number if possible
103
+ let matchedLine = null
104
+ let matchedSnippet = ''
105
+ for (let i = 0; i < lines.length; i++) {
106
+ if (rule.regex.test(lines[i])) {
107
+ matchedLine = i + 1
108
+ matchedSnippet = lines[i].trim().slice(0, 120)
109
+ break
110
+ }
111
+ }
112
+
113
+ findings.push({
114
+ cwe: rule.cwe,
115
+ title: rule.title,
116
+ severity: rule.severity,
117
+ detail: rule.detail,
118
+ line: matchedLine,
119
+ snippet: matchedSnippet || null,
120
+ })
121
+ }
122
+ }
123
+
124
+ let penalty = 0
125
+ let hasCriticalOrHigh = false
126
+ for (const f of findings) {
127
+ if (f.severity === 'critical') {
128
+ penalty += 45
129
+ hasCriticalOrHigh = true
130
+ } else if (f.severity === 'high') {
131
+ penalty += 25
132
+ hasCriticalOrHigh = true
133
+ } else if (f.severity === 'medium') {
134
+ penalty += 15
135
+ } else {
136
+ penalty += 5
137
+ }
138
+ }
139
+
140
+ const score = Math.max(0, Math.min(100, 100 - penalty))
141
+ const strictVeto = options.strictVeto !== false
142
+ const veto = strictVeto ? hasCriticalOrHigh || score < 60 : score < 40
143
+
144
+ let summary = ''
145
+ if (findings.length === 0) {
146
+ summary = '🛡️ Red Team Security Audit: PASSED (Score 100/100). No known CWE vulnerabilities detected.'
147
+ } else if (veto) {
148
+ summary = `⛔ SECURITY_VETO (Score ${score}/100): Found ${findings.length} security violation(s) (${findings.map((f) => f.cwe).join(', ')}).`
149
+ } else {
150
+ summary = `⚠️ Security Warning (Score ${score}/100): ${findings.length} minor/medium issue(s) identified.`
151
+ }
152
+
153
+ return {
154
+ veto,
155
+ score,
156
+ findings,
157
+ summary,
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Executes the Adversarial Security Fuzzing Gate across all candidate outputs.
163
+ *
164
+ * @param {Array<object>} candidates - List of candidate references with output/text
165
+ * @param {object} [options]
166
+ * @returns {object} Gate execution results with directive and veto counters
167
+ */
168
+ export function runSecurityAuditGate(candidates, options = {}) {
169
+ const { ctx, runId, onProgress, strictVeto = true } = options
170
+ const results = []
171
+ let vetoCount = 0
172
+
173
+ if (!Array.isArray(candidates) || candidates.length === 0) {
174
+ return {
175
+ results: [],
176
+ vetoCount: 0,
177
+ cleanCount: 0,
178
+ allPassed: true,
179
+ securityDirective: null,
180
+ }
181
+ }
182
+
183
+ for (let i = 0; i < candidates.length; i++) {
184
+ const cand = candidates[i]
185
+ const text = typeof cand === 'string' ? cand : cand.output || cand.text || cand.code || ''
186
+ const audit = auditCodeSecurity(text, { strictVeto })
187
+
188
+ if (typeof cand === 'object' && cand !== null) {
189
+ cand.securityAudit = audit
190
+ cand.securityVeto = audit.veto
191
+ }
192
+
193
+ if (audit.veto) {
194
+ vetoCount++
195
+ }
196
+
197
+ results.push({
198
+ candidateIndex: i,
199
+ model: cand?.model || `Candidate ${i + 1}`,
200
+ audit,
201
+ veto: audit.veto,
202
+ })
203
+
204
+ if (ctx) {
205
+ emitEvent(ctx, MOA_EVENTS.SECURITY_AUDIT, {
206
+ runId,
207
+ candidateIndex: i,
208
+ score: audit.score,
209
+ veto: audit.veto,
210
+ findingsCount: audit.findings.length,
211
+ cwes: audit.findings.map((f) => f.cwe),
212
+ })
213
+ }
214
+ }
215
+
216
+ const cleanCount = candidates.length - vetoCount
217
+ const allPassed = vetoCount === 0
218
+
219
+ if (typeof onProgress === 'function') {
220
+ if (allPassed) {
221
+ onProgress(`🛡️ *Security Gate Passed*: All ${candidates.length} candidate solutions cleared Red Team audit.\n`)
222
+ } else {
223
+ onProgress(
224
+ `🚨 *Security Gate Alert*: ${vetoCount}/${candidates.length} candidates triggered SECURITY_VETO (${results
225
+ .filter((r) => r.veto)
226
+ .map((r) => `Ref ${r.candidateIndex + 1}`)
227
+ .join(', ')}).\n`
228
+ )
229
+ }
230
+ }
231
+
232
+ const securityDirective = formatSecurityAuditDirective(results, { strictVeto })
233
+
234
+ return {
235
+ results,
236
+ vetoCount,
237
+ cleanCount,
238
+ allPassed,
239
+ securityDirective,
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Formats Red Team audit findings into a high-priority prompt directive for Stage 6/7.
245
+ *
246
+ * @param {Array<object>} results
247
+ * @param {object} [options]
248
+ * @returns {string|null} Directive text
249
+ */
250
+ export function formatSecurityAuditDirective(results, options = {}) {
251
+ if (!Array.isArray(results) || results.length === 0) return null
252
+
253
+ const hasAnyFindings = results.some((r) => r.audit && r.audit.findings.length > 0)
254
+ if (!hasAnyFindings) {
255
+ return '### 🛡️ RED TEAM SECURITY AUDIT: ALL CANDIDATES VERIFIED SECURE\nNo injection, XSS, ReDoS, path traversal, or credential exposure detected.'
256
+ }
257
+
258
+ const lines = [
259
+ '### 🛡️ ADVERSARIAL RED TEAM SECURITY AUDIT DIRECTIVE',
260
+ 'Strict security evaluation of candidate proposals has been completed:',
261
+ ]
262
+
263
+ for (const r of results) {
264
+ const label = `Candidate ${r.candidateIndex + 1}`
265
+ const a = r.audit || {}
266
+ if (a.veto) {
267
+ lines.push(
268
+ `- **${label}**: ⛔ **SECURITY_VETO** (Score ${a.score}/100) — DO NOT adopt this solution without removing critical flaws:`
269
+ )
270
+ for (const f of a.findings || []) {
271
+ lines.push(
272
+ ` * [${f.cwe}] ${f.title} (${f.severity.toUpperCase()}): ${f.detail}${f.line ? ` (at line ${f.line})` : ''}`
273
+ )
274
+ }
275
+ } else if (a.findings && a.findings.length > 0) {
276
+ lines.push(`- **${label}**: ⚠️ Warning (Score ${a.score}/100):`)
277
+ for (const f of a.findings) {
278
+ lines.push(` * [${f.cwe}] ${f.title}: ${f.detail}`)
279
+ }
280
+ } else {
281
+ lines.push(`- **${label}**: ✅ PASSED (Score 100/100) — Free of detectable vulnerabilities.`)
282
+ }
283
+ }
284
+
285
+ lines.push(
286
+ '\n**Judge Mandate**: Solutions marked with SECURITY_VETO must be heavily penalized or rejected. The final synthesized code MUST NOT contain any of the flagged CWE patterns.'
287
+ )
288
+
289
+ return lines.join('\n')
290
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-moa",
3
- "version": "0.2.75",
3
+ "version": "0.2.77",
4
4
  "description": "Mixture of Agents (MoA) plugin for DeepSeek Harness with /moa slash command",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",