vskill 0.1.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/README.md +49 -0
- package/dist/agents/agents-registry.d.ts +57 -0
- package/dist/agents/agents-registry.js +511 -0
- package/dist/agents/agents-registry.js.map +1 -0
- package/dist/api/client.d.ts +50 -0
- package/dist/api/client.js +50 -0
- package/dist/api/client.js.map +1 -0
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.js +126 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/find.d.ts +1 -0
- package/dist/commands/find.js +42 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +39 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.js +79 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/scan.d.ts +1 -0
- package/dist/commands/scan.js +99 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/submit.d.ts +5 -0
- package/dist/commands/submit.js +34 -0
- package/dist/commands/submit.js.map +1 -0
- package/dist/commands/update.d.ts +5 -0
- package/dist/commands/update.js +114 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/version.d.ts +1 -0
- package/dist/commands/version.js +11 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/lockfile/index.d.ts +2 -0
- package/dist/lockfile/index.js +2 -0
- package/dist/lockfile/index.js.map +1 -0
- package/dist/lockfile/lockfile.d.ts +23 -0
- package/dist/lockfile/lockfile.js +70 -0
- package/dist/lockfile/lockfile.js.map +1 -0
- package/dist/lockfile/types.d.ts +14 -0
- package/dist/lockfile/types.js +5 -0
- package/dist/lockfile/types.js.map +1 -0
- package/dist/scanner/index.d.ts +4 -0
- package/dist/scanner/index.js +3 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/patterns.d.ts +25 -0
- package/dist/scanner/patterns.js +347 -0
- package/dist/scanner/patterns.js.map +1 -0
- package/dist/scanner/pipeline/submission-pipeline.d.ts +100 -0
- package/dist/scanner/pipeline/submission-pipeline.js +173 -0
- package/dist/scanner/pipeline/submission-pipeline.js.map +1 -0
- package/dist/scanner/tier1.d.ts +23 -0
- package/dist/scanner/tier1.js +83 -0
- package/dist/scanner/tier1.js.map +1 -0
- package/dist/utils/output.d.ts +15 -0
- package/dist/utils/output.js +87 -0
- package/dist/utils/output.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Tier 1 Security Scan Patterns
|
|
3
|
+
// 37 regex-based patterns for static analysis of skill content.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// ---- Patterns (37 total) --------------------------------------------------
|
|
6
|
+
export const SCAN_PATTERNS = [
|
|
7
|
+
// --- Command Injection (1-7) ---------------------------------------------
|
|
8
|
+
{
|
|
9
|
+
id: "CI-001",
|
|
10
|
+
name: "exec() call",
|
|
11
|
+
severity: "critical",
|
|
12
|
+
description: "Detects child_process.exec or similar exec calls that run shell commands",
|
|
13
|
+
pattern: /\bexec\s*\(/g,
|
|
14
|
+
category: "command-injection",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "CI-002",
|
|
18
|
+
name: "spawn() call",
|
|
19
|
+
severity: "high",
|
|
20
|
+
description: "Detects child_process.spawn invocations",
|
|
21
|
+
pattern: /\bspawn\s*\(/g,
|
|
22
|
+
category: "command-injection",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "CI-003",
|
|
26
|
+
name: "system() call",
|
|
27
|
+
severity: "critical",
|
|
28
|
+
description: "Detects system-level command execution",
|
|
29
|
+
pattern: /\bsystem\s*\(/g,
|
|
30
|
+
category: "command-injection",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "CI-004",
|
|
34
|
+
name: "Shell command strings",
|
|
35
|
+
severity: "high",
|
|
36
|
+
description: "Detects common shell commands embedded in strings",
|
|
37
|
+
pattern: /(?:"|'|`)\s*(?:\/bin\/(?:sh|bash|zsh)|cmd(?:\.exe)?)\b/g,
|
|
38
|
+
category: "command-injection",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "CI-005",
|
|
42
|
+
name: "Backtick shell execution",
|
|
43
|
+
severity: "high",
|
|
44
|
+
description: "Detects backtick-based command substitution patterns",
|
|
45
|
+
pattern: /child_process|execSync|spawnSync|execFile/g,
|
|
46
|
+
category: "command-injection",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "CI-006",
|
|
50
|
+
name: "Shell pipe operator",
|
|
51
|
+
severity: "medium",
|
|
52
|
+
description: "Detects shell piping within exec-like calls",
|
|
53
|
+
pattern: /exec\s*\([^)]*\|[^)]*\)/g,
|
|
54
|
+
category: "command-injection",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "CI-007",
|
|
58
|
+
name: "Command interpolation",
|
|
59
|
+
severity: "high",
|
|
60
|
+
description: "Detects string interpolation in shell commands",
|
|
61
|
+
pattern: /exec\s*\(\s*`[^`]*\$\{/g,
|
|
62
|
+
category: "command-injection",
|
|
63
|
+
},
|
|
64
|
+
// --- Data Exfiltration (8-12) --------------------------------------------
|
|
65
|
+
{
|
|
66
|
+
id: "DE-001",
|
|
67
|
+
name: "Fetch to external URL",
|
|
68
|
+
severity: "high",
|
|
69
|
+
description: "Detects fetch calls to external/dynamic URLs",
|
|
70
|
+
pattern: /fetch\s*\(\s*(?:`[^`]*\$\{|[a-zA-Z_]\w*\s*[\+,])/g,
|
|
71
|
+
category: "data-exfiltration",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "DE-002",
|
|
75
|
+
name: "XMLHttpRequest usage",
|
|
76
|
+
severity: "high",
|
|
77
|
+
description: "Detects XMLHttpRequest which can send data externally",
|
|
78
|
+
pattern: /new\s+XMLHttpRequest/g,
|
|
79
|
+
category: "data-exfiltration",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "DE-003",
|
|
83
|
+
name: "WebSocket to external host",
|
|
84
|
+
severity: "high",
|
|
85
|
+
description: "Detects WebSocket connections that could exfiltrate data",
|
|
86
|
+
pattern: /new\s+WebSocket\s*\(/g,
|
|
87
|
+
category: "data-exfiltration",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "DE-004",
|
|
91
|
+
name: "DNS exfiltration pattern",
|
|
92
|
+
severity: "medium",
|
|
93
|
+
description: "Detects encoding data into DNS lookups",
|
|
94
|
+
pattern: /dns\.(?:resolve|lookup)\s*\(.*(?:\+|concat|\$\{)/g,
|
|
95
|
+
category: "data-exfiltration",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "DE-005",
|
|
99
|
+
name: "Base64 encode and send",
|
|
100
|
+
severity: "medium",
|
|
101
|
+
description: "Detects base64 encoding followed by network send (exfil pattern)",
|
|
102
|
+
pattern: /btoa\s*\(|Buffer\.from\([^)]*\)\.toString\s*\(\s*['"]base64['"]/g,
|
|
103
|
+
category: "data-exfiltration",
|
|
104
|
+
},
|
|
105
|
+
// --- Privilege Escalation (13-17) ----------------------------------------
|
|
106
|
+
{
|
|
107
|
+
id: "PE-001",
|
|
108
|
+
name: "sudo invocation",
|
|
109
|
+
severity: "critical",
|
|
110
|
+
description: "Detects attempts to run commands with sudo",
|
|
111
|
+
pattern: /\bsudo\s+/g,
|
|
112
|
+
category: "privilege-escalation",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "PE-002",
|
|
116
|
+
name: "chmod modification",
|
|
117
|
+
severity: "high",
|
|
118
|
+
description: "Detects changing file permissions",
|
|
119
|
+
pattern: /\bchmod\s+/g,
|
|
120
|
+
category: "privilege-escalation",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "PE-003",
|
|
124
|
+
name: "chown modification",
|
|
125
|
+
severity: "high",
|
|
126
|
+
description: "Detects changing file ownership",
|
|
127
|
+
pattern: /\bchown\s+/g,
|
|
128
|
+
category: "privilege-escalation",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: "PE-004",
|
|
132
|
+
name: "setuid/setgid",
|
|
133
|
+
severity: "critical",
|
|
134
|
+
description: "Detects setuid/setgid operations",
|
|
135
|
+
pattern: /\bset(?:uid|gid|euid|egid)\s*\(/g,
|
|
136
|
+
category: "privilege-escalation",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "PE-005",
|
|
140
|
+
name: "Process privilege change",
|
|
141
|
+
severity: "high",
|
|
142
|
+
description: "Detects process.setuid or similar privilege modifications",
|
|
143
|
+
pattern: /process\.set(?:uid|gid|groups)\s*\(/g,
|
|
144
|
+
category: "privilege-escalation",
|
|
145
|
+
},
|
|
146
|
+
// --- Credential Theft (18-23) --------------------------------------------
|
|
147
|
+
{
|
|
148
|
+
id: "CT-001",
|
|
149
|
+
name: "Read .env file",
|
|
150
|
+
severity: "critical",
|
|
151
|
+
description: "Detects reading .env files which contain secrets",
|
|
152
|
+
pattern: /readFile(?:Sync)?\s*\([^)]*\.env\b/g,
|
|
153
|
+
category: "credential-theft",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "CT-002",
|
|
157
|
+
name: "Read SSH keys",
|
|
158
|
+
severity: "critical",
|
|
159
|
+
description: "Detects accessing .ssh directory or key files",
|
|
160
|
+
pattern: /\.ssh[/\\]|id_rsa|id_ed25519|authorized_keys/g,
|
|
161
|
+
category: "credential-theft",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: "CT-003",
|
|
165
|
+
name: "Read AWS credentials",
|
|
166
|
+
severity: "critical",
|
|
167
|
+
description: "Detects accessing AWS credential files",
|
|
168
|
+
pattern: /\.aws[/\\]credentials|AWS_SECRET_ACCESS_KEY|AWS_ACCESS_KEY_ID/g,
|
|
169
|
+
category: "credential-theft",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: "CT-004",
|
|
173
|
+
name: "Keychain access",
|
|
174
|
+
severity: "critical",
|
|
175
|
+
description: "Detects macOS keychain or system credential store access",
|
|
176
|
+
pattern: /security\s+find-(?:generic|internet)-password|keychain|credential-store/g,
|
|
177
|
+
category: "credential-theft",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: "CT-005",
|
|
181
|
+
name: "Secrets in environment",
|
|
182
|
+
severity: "high",
|
|
183
|
+
description: "Detects broad process.env access patterns",
|
|
184
|
+
pattern: /process\.env\[(?:[^'"\]]*\+|[a-zA-Z_]\w*\])/g,
|
|
185
|
+
category: "credential-theft",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "CT-006",
|
|
189
|
+
name: "Token/secret variable patterns",
|
|
190
|
+
severity: "medium",
|
|
191
|
+
description: "Detects variables likely holding secrets being sent externally",
|
|
192
|
+
pattern: /(?:token|secret|password|api_key|apiKey)\s*[:=]\s*(?:process\.env|readFile)/gi,
|
|
193
|
+
category: "credential-theft",
|
|
194
|
+
},
|
|
195
|
+
// --- Prompt Injection (24-27) --------------------------------------------
|
|
196
|
+
{
|
|
197
|
+
id: "PI-001",
|
|
198
|
+
name: "System prompt override",
|
|
199
|
+
severity: "critical",
|
|
200
|
+
description: "Detects attempts to override or replace system prompts",
|
|
201
|
+
pattern: /(?:system\s*prompt|system\s*message|system\s*instruction)\s*[:=]/gi,
|
|
202
|
+
category: "prompt-injection",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: "PI-002",
|
|
206
|
+
name: "Ignore previous instructions",
|
|
207
|
+
severity: "critical",
|
|
208
|
+
description: "Detects classic prompt injection phrase",
|
|
209
|
+
pattern: /ignore\s+(?:all\s+)?(?:previous|prior|above)\s+instructions/gi,
|
|
210
|
+
category: "prompt-injection",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: "PI-003",
|
|
214
|
+
name: "Role impersonation",
|
|
215
|
+
severity: "high",
|
|
216
|
+
description: "Detects attempts to assume a different AI role",
|
|
217
|
+
pattern: /you\s+are\s+now\s+(?:a|an)\s+|act\s+as\s+(?:a|an)\s+|pretend\s+(?:to\s+be|you\s+are)/gi,
|
|
218
|
+
category: "prompt-injection",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "PI-004",
|
|
222
|
+
name: "Instruction boundary escape",
|
|
223
|
+
severity: "high",
|
|
224
|
+
description: "Detects delimiter injection patterns",
|
|
225
|
+
pattern: /\[\/INST\]|\[INST\]|<\|im_end\|>|<\|im_start\|>|<\|system\|>/g,
|
|
226
|
+
category: "prompt-injection",
|
|
227
|
+
},
|
|
228
|
+
// --- Filesystem Access (28-31) -------------------------------------------
|
|
229
|
+
{
|
|
230
|
+
id: "FS-001",
|
|
231
|
+
name: "Recursive delete",
|
|
232
|
+
severity: "critical",
|
|
233
|
+
description: "Detects rm -rf or recursive deletion commands",
|
|
234
|
+
pattern: /rm\s+-[a-zA-Z]*r[a-zA-Z]*f|rm\s+-[a-zA-Z]*f[a-zA-Z]*r|rimraf\s*\(/g,
|
|
235
|
+
category: "filesystem-access",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "FS-002",
|
|
239
|
+
name: "Write to system paths",
|
|
240
|
+
severity: "critical",
|
|
241
|
+
description: "Detects writing to system-critical paths",
|
|
242
|
+
pattern: /writeFile(?:Sync)?\s*\([^)]*(?:\/etc\/|\/usr\/|\/var\/|\/System\/|C:\\Windows)/g,
|
|
243
|
+
category: "filesystem-access",
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
id: "FS-003",
|
|
247
|
+
name: "Path traversal",
|
|
248
|
+
severity: "high",
|
|
249
|
+
description: "Detects directory traversal attempts",
|
|
250
|
+
pattern: /\.\.[/\\]\.\.[/\\]|\.\.(?:[/\\]){2,}/g,
|
|
251
|
+
category: "filesystem-access",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: "FS-004",
|
|
255
|
+
name: "Symlink manipulation",
|
|
256
|
+
severity: "medium",
|
|
257
|
+
description: "Detects symlink creation that could be used for path hijacking",
|
|
258
|
+
pattern: /symlink(?:Sync)?\s*\(|ln\s+-s\s+/g,
|
|
259
|
+
category: "filesystem-access",
|
|
260
|
+
},
|
|
261
|
+
// --- Network Access (32-34) ----------------------------------------------
|
|
262
|
+
{
|
|
263
|
+
id: "NA-001",
|
|
264
|
+
name: "Curl/wget to unknown host",
|
|
265
|
+
severity: "high",
|
|
266
|
+
description: "Detects curl or wget commands that download from external hosts",
|
|
267
|
+
pattern: /\b(?:curl|wget)\s+(?:-[a-zA-Z]*\s+)*(?:https?:\/\/|[`"'])/g,
|
|
268
|
+
category: "network-access",
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: "NA-002",
|
|
272
|
+
name: "Reverse shell pattern",
|
|
273
|
+
severity: "critical",
|
|
274
|
+
description: "Detects reverse shell connection patterns",
|
|
275
|
+
pattern: /(?:\/dev\/tcp\/|nc\s+-[a-z]*e|ncat\s|bash\s+-i\s+>&|mkfifo|0<&\d+)/g,
|
|
276
|
+
category: "network-access",
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
id: "NA-003",
|
|
280
|
+
name: "Dynamic URL construction",
|
|
281
|
+
severity: "medium",
|
|
282
|
+
description: "Detects building URLs from variables (potential C2 communication)",
|
|
283
|
+
pattern: /(?:http|https):\/\/\$\{|(?:http|https):\/\/['"]\s*\+/g,
|
|
284
|
+
category: "network-access",
|
|
285
|
+
},
|
|
286
|
+
// --- Code Execution (35-37) ----------------------------------------------
|
|
287
|
+
{
|
|
288
|
+
id: "CE-001",
|
|
289
|
+
name: "eval() usage",
|
|
290
|
+
severity: "critical",
|
|
291
|
+
description: "Detects eval() which executes arbitrary code",
|
|
292
|
+
pattern: /\beval\s*\(/g,
|
|
293
|
+
category: "code-execution",
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
id: "CE-002",
|
|
297
|
+
name: "Function() constructor",
|
|
298
|
+
severity: "critical",
|
|
299
|
+
description: "Detects new Function() which compiles and runs arbitrary code",
|
|
300
|
+
pattern: /new\s+Function\s*\(/g,
|
|
301
|
+
category: "code-execution",
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: "CE-003",
|
|
305
|
+
name: "Dynamic remote import",
|
|
306
|
+
severity: "high",
|
|
307
|
+
description: "Detects dynamic import of remote/variable modules",
|
|
308
|
+
pattern: /import\s*\(\s*(?:`[^`]*\$\{|[a-zA-Z_]\w*\s*[\+)])/g,
|
|
309
|
+
category: "code-execution",
|
|
310
|
+
},
|
|
311
|
+
];
|
|
312
|
+
// ---- Scanner function -----------------------------------------------------
|
|
313
|
+
/**
|
|
314
|
+
* Scan content against all 37 patterns, returning every match found.
|
|
315
|
+
*/
|
|
316
|
+
export function scanContent(content) {
|
|
317
|
+
const lines = content.split("\n");
|
|
318
|
+
const findings = [];
|
|
319
|
+
for (const pattern of SCAN_PATTERNS) {
|
|
320
|
+
// Reset the regex lastIndex for each pattern (they use /g flag)
|
|
321
|
+
const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
|
|
322
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
323
|
+
const line = lines[lineIdx];
|
|
324
|
+
let match;
|
|
325
|
+
while ((match = regex.exec(line)) !== null) {
|
|
326
|
+
// Build context: up to 1 line before and after
|
|
327
|
+
const contextLines = [];
|
|
328
|
+
if (lineIdx > 0)
|
|
329
|
+
contextLines.push(lines[lineIdx - 1]);
|
|
330
|
+
contextLines.push(line);
|
|
331
|
+
if (lineIdx < lines.length - 1)
|
|
332
|
+
contextLines.push(lines[lineIdx + 1]);
|
|
333
|
+
findings.push({
|
|
334
|
+
patternId: pattern.id,
|
|
335
|
+
patternName: pattern.name,
|
|
336
|
+
severity: pattern.severity,
|
|
337
|
+
category: pattern.category,
|
|
338
|
+
match: match[0],
|
|
339
|
+
lineNumber: lineIdx + 1,
|
|
340
|
+
context: contextLines.join("\n"),
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return findings;
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/scanner/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Submission Pipeline State Machine
|
|
3
|
+
*
|
|
4
|
+
* Deterministic state machine for processing skill verification requests.
|
|
5
|
+
* Every state transition is logged for audit trail compliance.
|
|
6
|
+
*
|
|
7
|
+
* @see research/submission-state-machine.md for full design
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* All possible states in the submission pipeline.
|
|
11
|
+
* Terminal states: TIER1_FAILED, REJECTED, PUBLISHED
|
|
12
|
+
*/
|
|
13
|
+
export declare enum SubmissionState {
|
|
14
|
+
/** Initial state — submission received via API or web form */
|
|
15
|
+
RECEIVED = "RECEIVED",
|
|
16
|
+
/** Tier 1 deterministic scan running */
|
|
17
|
+
TIER1_SCANNING = "TIER1_SCANNING",
|
|
18
|
+
/** Tier 1 failed — terminal state */
|
|
19
|
+
TIER1_FAILED = "TIER1_FAILED",
|
|
20
|
+
/** Tier 2 LLM judge analysis running */
|
|
21
|
+
TIER2_SCANNING = "TIER2_SCANNING",
|
|
22
|
+
/** Both tiers passed with score >= 80 — auto-approved */
|
|
23
|
+
AUTO_APPROVED = "AUTO_APPROVED",
|
|
24
|
+
/** Tier 2 returned CONCERNS (60-79) or high-privilege skill — needs human review */
|
|
25
|
+
NEEDS_REVIEW = "NEEDS_REVIEW",
|
|
26
|
+
/** Tier 3 manual review in progress */
|
|
27
|
+
TIER3_REVIEW = "TIER3_REVIEW",
|
|
28
|
+
/** Approved and published to registry */
|
|
29
|
+
PUBLISHED = "PUBLISHED",
|
|
30
|
+
/** Rejected at any stage — terminal state */
|
|
31
|
+
REJECTED = "REJECTED",
|
|
32
|
+
/** Vendor auto-verified — bypassed scanning */
|
|
33
|
+
VENDOR_APPROVED = "VENDOR_APPROVED"
|
|
34
|
+
}
|
|
35
|
+
/** Actor types that can trigger state transitions */
|
|
36
|
+
export type TransitionActor = 'system' | 'worker' | 'admin';
|
|
37
|
+
/** A state transition event for the audit trail */
|
|
38
|
+
export interface StateTransitionEvent {
|
|
39
|
+
/** Unique event ID */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Submission this event belongs to */
|
|
42
|
+
submissionId: string;
|
|
43
|
+
/** State before the transition (null for initial RECEIVED) */
|
|
44
|
+
fromState: SubmissionState | null;
|
|
45
|
+
/** State after the transition */
|
|
46
|
+
toState: SubmissionState;
|
|
47
|
+
/** What triggered this transition */
|
|
48
|
+
trigger: string;
|
|
49
|
+
/** Who triggered the transition */
|
|
50
|
+
actor: string;
|
|
51
|
+
/** Actor type classification */
|
|
52
|
+
actorType: TransitionActor;
|
|
53
|
+
/** Context-specific metadata (scan results, scores, etc.) */
|
|
54
|
+
metadata: Record<string, unknown>;
|
|
55
|
+
/** ISO timestamp when the transition occurred */
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
/** States from which no further transitions are possible */
|
|
59
|
+
export declare const TERMINAL_STATES: ReadonlySet<SubmissionState>;
|
|
60
|
+
/**
|
|
61
|
+
* Validate whether a state transition is allowed.
|
|
62
|
+
*
|
|
63
|
+
* @param current - The current state of the submission
|
|
64
|
+
* @param next - The proposed next state
|
|
65
|
+
* @returns true if the transition is valid
|
|
66
|
+
*/
|
|
67
|
+
export declare function validateTransition(current: SubmissionState, next: SubmissionState): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Attempt a state transition. Returns the new state if valid,
|
|
70
|
+
* throws an error if the transition is not allowed.
|
|
71
|
+
*
|
|
72
|
+
* @param current - The current state
|
|
73
|
+
* @param next - The desired next state
|
|
74
|
+
* @param trigger - What caused the transition
|
|
75
|
+
* @param actor - Who triggered the transition
|
|
76
|
+
* @returns The new state (same as `next`)
|
|
77
|
+
* @throws Error if the transition is invalid
|
|
78
|
+
*/
|
|
79
|
+
export declare function transition(current: SubmissionState, next: SubmissionState, trigger: string, actor: TransitionActor): SubmissionState;
|
|
80
|
+
/** GitHub organizations whose skills are auto-verified */
|
|
81
|
+
export declare const TRUSTED_ORGS: readonly string[];
|
|
82
|
+
/**
|
|
83
|
+
* Check if a GitHub repo owner is a trusted vendor organization.
|
|
84
|
+
*
|
|
85
|
+
* @param owner - GitHub organization or user name
|
|
86
|
+
* @returns true if the owner is in the trusted orgs list
|
|
87
|
+
*/
|
|
88
|
+
export declare function isVendorOrg(owner: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Check if a state is terminal (no further transitions possible).
|
|
91
|
+
*/
|
|
92
|
+
export declare function isTerminalState(state: SubmissionState): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Get all valid next states from the current state.
|
|
95
|
+
*/
|
|
96
|
+
export declare function getNextStates(state: SubmissionState): SubmissionState[];
|
|
97
|
+
/**
|
|
98
|
+
* Create a state transition audit event.
|
|
99
|
+
*/
|
|
100
|
+
export declare function createTransitionEvent(submissionId: string, fromState: SubmissionState | null, toState: SubmissionState, trigger: string, actor: string, actorType: TransitionActor, metadata?: Record<string, unknown>): StateTransitionEvent;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Submission Pipeline State Machine
|
|
3
|
+
*
|
|
4
|
+
* Deterministic state machine for processing skill verification requests.
|
|
5
|
+
* Every state transition is logged for audit trail compliance.
|
|
6
|
+
*
|
|
7
|
+
* @see research/submission-state-machine.md for full design
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// State Enum
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* All possible states in the submission pipeline.
|
|
14
|
+
* Terminal states: TIER1_FAILED, REJECTED, PUBLISHED
|
|
15
|
+
*/
|
|
16
|
+
export var SubmissionState;
|
|
17
|
+
(function (SubmissionState) {
|
|
18
|
+
/** Initial state — submission received via API or web form */
|
|
19
|
+
SubmissionState["RECEIVED"] = "RECEIVED";
|
|
20
|
+
/** Tier 1 deterministic scan running */
|
|
21
|
+
SubmissionState["TIER1_SCANNING"] = "TIER1_SCANNING";
|
|
22
|
+
/** Tier 1 failed — terminal state */
|
|
23
|
+
SubmissionState["TIER1_FAILED"] = "TIER1_FAILED";
|
|
24
|
+
/** Tier 2 LLM judge analysis running */
|
|
25
|
+
SubmissionState["TIER2_SCANNING"] = "TIER2_SCANNING";
|
|
26
|
+
/** Both tiers passed with score >= 80 — auto-approved */
|
|
27
|
+
SubmissionState["AUTO_APPROVED"] = "AUTO_APPROVED";
|
|
28
|
+
/** Tier 2 returned CONCERNS (60-79) or high-privilege skill — needs human review */
|
|
29
|
+
SubmissionState["NEEDS_REVIEW"] = "NEEDS_REVIEW";
|
|
30
|
+
/** Tier 3 manual review in progress */
|
|
31
|
+
SubmissionState["TIER3_REVIEW"] = "TIER3_REVIEW";
|
|
32
|
+
/** Approved and published to registry */
|
|
33
|
+
SubmissionState["PUBLISHED"] = "PUBLISHED";
|
|
34
|
+
/** Rejected at any stage — terminal state */
|
|
35
|
+
SubmissionState["REJECTED"] = "REJECTED";
|
|
36
|
+
/** Vendor auto-verified — bypassed scanning */
|
|
37
|
+
SubmissionState["VENDOR_APPROVED"] = "VENDOR_APPROVED";
|
|
38
|
+
})(SubmissionState || (SubmissionState = {}));
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Valid Transitions Map
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Defines all valid state transitions.
|
|
44
|
+
* Any transition not in this map is invalid and will be rejected.
|
|
45
|
+
*/
|
|
46
|
+
const VALID_TRANSITIONS = {
|
|
47
|
+
[SubmissionState.RECEIVED]: [
|
|
48
|
+
SubmissionState.VENDOR_APPROVED,
|
|
49
|
+
SubmissionState.TIER1_SCANNING,
|
|
50
|
+
],
|
|
51
|
+
[SubmissionState.TIER1_SCANNING]: [
|
|
52
|
+
SubmissionState.TIER2_SCANNING,
|
|
53
|
+
SubmissionState.TIER1_FAILED,
|
|
54
|
+
],
|
|
55
|
+
[SubmissionState.TIER1_FAILED]: [],
|
|
56
|
+
[SubmissionState.TIER2_SCANNING]: [
|
|
57
|
+
SubmissionState.AUTO_APPROVED,
|
|
58
|
+
SubmissionState.NEEDS_REVIEW,
|
|
59
|
+
SubmissionState.REJECTED,
|
|
60
|
+
],
|
|
61
|
+
[SubmissionState.AUTO_APPROVED]: [
|
|
62
|
+
SubmissionState.PUBLISHED,
|
|
63
|
+
],
|
|
64
|
+
[SubmissionState.NEEDS_REVIEW]: [
|
|
65
|
+
SubmissionState.TIER3_REVIEW,
|
|
66
|
+
SubmissionState.REJECTED,
|
|
67
|
+
],
|
|
68
|
+
[SubmissionState.TIER3_REVIEW]: [
|
|
69
|
+
SubmissionState.PUBLISHED,
|
|
70
|
+
SubmissionState.REJECTED,
|
|
71
|
+
],
|
|
72
|
+
[SubmissionState.PUBLISHED]: [],
|
|
73
|
+
[SubmissionState.REJECTED]: [],
|
|
74
|
+
[SubmissionState.VENDOR_APPROVED]: [
|
|
75
|
+
SubmissionState.PUBLISHED,
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Terminal States
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/** States from which no further transitions are possible */
|
|
82
|
+
export const TERMINAL_STATES = new Set([
|
|
83
|
+
SubmissionState.TIER1_FAILED,
|
|
84
|
+
SubmissionState.PUBLISHED,
|
|
85
|
+
SubmissionState.REJECTED,
|
|
86
|
+
]);
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Transition Function
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
/**
|
|
91
|
+
* Validate whether a state transition is allowed.
|
|
92
|
+
*
|
|
93
|
+
* @param current - The current state of the submission
|
|
94
|
+
* @param next - The proposed next state
|
|
95
|
+
* @returns true if the transition is valid
|
|
96
|
+
*/
|
|
97
|
+
export function validateTransition(current, next) {
|
|
98
|
+
const allowed = VALID_TRANSITIONS[current];
|
|
99
|
+
if (!allowed)
|
|
100
|
+
return false;
|
|
101
|
+
return allowed.includes(next);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Attempt a state transition. Returns the new state if valid,
|
|
105
|
+
* throws an error if the transition is not allowed.
|
|
106
|
+
*
|
|
107
|
+
* @param current - The current state
|
|
108
|
+
* @param next - The desired next state
|
|
109
|
+
* @param trigger - What caused the transition
|
|
110
|
+
* @param actor - Who triggered the transition
|
|
111
|
+
* @returns The new state (same as `next`)
|
|
112
|
+
* @throws Error if the transition is invalid
|
|
113
|
+
*/
|
|
114
|
+
export function transition(current, next, trigger, actor) {
|
|
115
|
+
if (!validateTransition(current, next)) {
|
|
116
|
+
throw new Error(`Invalid state transition: ${current} → ${next} (trigger: ${trigger}, actor: ${actor})`);
|
|
117
|
+
}
|
|
118
|
+
return next;
|
|
119
|
+
}
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Vendor Fast-Path
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
/** GitHub organizations whose skills are auto-verified */
|
|
124
|
+
export const TRUSTED_ORGS = [
|
|
125
|
+
'anthropics',
|
|
126
|
+
'openai',
|
|
127
|
+
'google',
|
|
128
|
+
'google-gemini',
|
|
129
|
+
'vercel-labs',
|
|
130
|
+
'supabase',
|
|
131
|
+
'microsoft',
|
|
132
|
+
];
|
|
133
|
+
/**
|
|
134
|
+
* Check if a GitHub repo owner is a trusted vendor organization.
|
|
135
|
+
*
|
|
136
|
+
* @param owner - GitHub organization or user name
|
|
137
|
+
* @returns true if the owner is in the trusted orgs list
|
|
138
|
+
*/
|
|
139
|
+
export function isVendorOrg(owner) {
|
|
140
|
+
return TRUSTED_ORGS.includes(owner.toLowerCase());
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Utility Functions
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
/**
|
|
146
|
+
* Check if a state is terminal (no further transitions possible).
|
|
147
|
+
*/
|
|
148
|
+
export function isTerminalState(state) {
|
|
149
|
+
return TERMINAL_STATES.has(state);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get all valid next states from the current state.
|
|
153
|
+
*/
|
|
154
|
+
export function getNextStates(state) {
|
|
155
|
+
return VALID_TRANSITIONS[state] ?? [];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create a state transition audit event.
|
|
159
|
+
*/
|
|
160
|
+
export function createTransitionEvent(submissionId, fromState, toState, trigger, actor, actorType, metadata = {}) {
|
|
161
|
+
return {
|
|
162
|
+
id: crypto.randomUUID(),
|
|
163
|
+
submissionId,
|
|
164
|
+
fromState,
|
|
165
|
+
toState,
|
|
166
|
+
trigger,
|
|
167
|
+
actor,
|
|
168
|
+
actorType,
|
|
169
|
+
metadata,
|
|
170
|
+
createdAt: new Date().toISOString(),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=submission-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission-pipeline.js","sourceRoot":"","sources":["../../../src/scanner/pipeline/submission-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ScanFinding, type ScanVerdict } from "./patterns.js";
|
|
2
|
+
export interface Tier1Result {
|
|
3
|
+
verdict: ScanVerdict;
|
|
4
|
+
findings: ScanFinding[];
|
|
5
|
+
score: number;
|
|
6
|
+
patternsChecked: number;
|
|
7
|
+
criticalCount: number;
|
|
8
|
+
highCount: number;
|
|
9
|
+
mediumCount: number;
|
|
10
|
+
lowCount: number;
|
|
11
|
+
infoCount: number;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Run the Tier 1 static scan against the provided skill content.
|
|
16
|
+
*
|
|
17
|
+
* Scoring starts at 100 and deducts points per finding based on severity.
|
|
18
|
+
* Verdict thresholds:
|
|
19
|
+
* >= 80 PASS
|
|
20
|
+
* 50-79 CONCERNS
|
|
21
|
+
* < 50 FAIL
|
|
22
|
+
*/
|
|
23
|
+
export declare function runTier1Scan(content: string): Tier1Result;
|