@kevinrabun/judges 3.47.0 → 3.49.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/CHANGELOG.md +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/audit-trail.d.ts +18 -0
- package/dist/commands/audit-trail.d.ts.map +1 -0
- package/dist/commands/audit-trail.js +155 -0
- package/dist/commands/audit-trail.js.map +1 -0
- package/dist/commands/auto-fix.d.ts +18 -0
- package/dist/commands/auto-fix.d.ts.map +1 -0
- package/dist/commands/auto-fix.js +241 -0
- package/dist/commands/auto-fix.js.map +1 -0
- package/dist/commands/dep-correlate.d.ts +9 -0
- package/dist/commands/dep-correlate.d.ts.map +1 -0
- package/dist/commands/dep-correlate.js +208 -0
- package/dist/commands/dep-correlate.js.map +1 -0
- package/dist/commands/doc-gen.d.ts +8 -0
- package/dist/commands/doc-gen.d.ts.map +1 -0
- package/dist/commands/doc-gen.js +209 -0
- package/dist/commands/doc-gen.js.map +1 -0
- package/dist/commands/incident-response.d.ts +8 -0
- package/dist/commands/incident-response.d.ts.map +1 -0
- package/dist/commands/incident-response.js +255 -0
- package/dist/commands/incident-response.js.map +1 -0
- package/dist/commands/judge-author.d.ts +8 -0
- package/dist/commands/judge-author.d.ts.map +1 -0
- package/dist/commands/judge-author.js +261 -0
- package/dist/commands/judge-author.js.map +1 -0
- package/dist/commands/learning-path.d.ts +9 -0
- package/dist/commands/learning-path.d.ts.map +1 -0
- package/dist/commands/learning-path.js +326 -0
- package/dist/commands/learning-path.js.map +1 -0
- package/dist/commands/license-scan.d.ts +9 -0
- package/dist/commands/license-scan.d.ts.map +1 -0
- package/dist/commands/license-scan.js +180 -0
- package/dist/commands/license-scan.js.map +1 -0
- package/dist/commands/org-policy.d.ts +8 -0
- package/dist/commands/org-policy.d.ts.map +1 -0
- package/dist/commands/org-policy.js +208 -0
- package/dist/commands/org-policy.js.map +1 -0
- package/dist/commands/pattern-registry.d.ts +23 -0
- package/dist/commands/pattern-registry.d.ts.map +1 -0
- package/dist/commands/pattern-registry.js +227 -0
- package/dist/commands/pattern-registry.js.map +1 -0
- package/dist/commands/perf-hotspot.d.ts +8 -0
- package/dist/commands/perf-hotspot.d.ts.map +1 -0
- package/dist/commands/perf-hotspot.js +274 -0
- package/dist/commands/perf-hotspot.js.map +1 -0
- package/dist/commands/predict.d.ts +8 -0
- package/dist/commands/predict.d.ts.map +1 -0
- package/dist/commands/predict.js +219 -0
- package/dist/commands/predict.js.map +1 -0
- package/dist/commands/risk-heatmap.d.ts +8 -0
- package/dist/commands/risk-heatmap.d.ts.map +1 -0
- package/dist/commands/risk-heatmap.js +224 -0
- package/dist/commands/risk-heatmap.js.map +1 -0
- package/dist/commands/sbom-export.d.ts +8 -0
- package/dist/commands/sbom-export.d.ts.map +1 -0
- package/dist/commands/sbom-export.js +162 -0
- package/dist/commands/sbom-export.js.map +1 -0
- package/dist/commands/security-maturity.d.ts +8 -0
- package/dist/commands/security-maturity.d.ts.map +1 -0
- package/dist/commands/security-maturity.js +313 -0
- package/dist/commands/security-maturity.js.map +1 -0
- package/dist/commands/test-correlate.d.ts +8 -0
- package/dist/commands/test-correlate.d.ts.map +1 -0
- package/dist/commands/test-correlate.js +222 -0
- package/dist/commands/test-correlate.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom judge authoring toolkit — scaffolds, validates,
|
|
3
|
+
* and tests new judge definitions.
|
|
4
|
+
*
|
|
5
|
+
* All data stored locally.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { defaultRegistry } from "../judge-registry.js";
|
|
10
|
+
// ─── Scaffold ───────────────────────────────────────────────────────────────
|
|
11
|
+
function scaffoldJudge(id, opts) {
|
|
12
|
+
return {
|
|
13
|
+
id,
|
|
14
|
+
name: opts.name || id.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
15
|
+
description: `Custom judge: ${id}`,
|
|
16
|
+
category: opts.category || "custom",
|
|
17
|
+
severity: opts.severity || "medium",
|
|
18
|
+
rules: [
|
|
19
|
+
{
|
|
20
|
+
id: `${id}-001`,
|
|
21
|
+
pattern: "TODO: define pattern",
|
|
22
|
+
message: "TODO: describe what this rule detects",
|
|
23
|
+
severity: opts.severity || "medium",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function generateJudgeFile(scaffold) {
|
|
29
|
+
return `/**
|
|
30
|
+
* ${scaffold.name}
|
|
31
|
+
*
|
|
32
|
+
* ${scaffold.description}
|
|
33
|
+
* Category: ${scaffold.category}
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import type { Finding } from "../types.js";
|
|
37
|
+
|
|
38
|
+
export const judgeId = "${scaffold.id}";
|
|
39
|
+
export const judgeName = "${scaffold.name}";
|
|
40
|
+
export const judgeDescription = "${scaffold.description}";
|
|
41
|
+
export const judgeCategory = "${scaffold.category}";
|
|
42
|
+
|
|
43
|
+
interface Rule {
|
|
44
|
+
id: string;
|
|
45
|
+
pattern: RegExp;
|
|
46
|
+
message: string;
|
|
47
|
+
severity: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const rules: Rule[] = [
|
|
51
|
+
${scaffold.rules
|
|
52
|
+
.map((r) => ` {
|
|
53
|
+
id: "${r.id}",
|
|
54
|
+
pattern: /${r.pattern.replace(/\//g, "\\/")}/g,
|
|
55
|
+
message: "${r.message}",
|
|
56
|
+
severity: "${r.severity}",
|
|
57
|
+
},`)
|
|
58
|
+
.join("\n")}
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
export function evaluate(code: string, _filename: string): Finding[] {
|
|
62
|
+
const findings: Finding[] = [];
|
|
63
|
+
const lines = code.split("\\n");
|
|
64
|
+
|
|
65
|
+
for (const rule of rules) {
|
|
66
|
+
for (let i = 0; i < lines.length; i++) {
|
|
67
|
+
if (rule.pattern.test(lines[i])) {
|
|
68
|
+
findings.push({
|
|
69
|
+
ruleId: rule.id,
|
|
70
|
+
severity: rule.severity as Finding["severity"],
|
|
71
|
+
title: rule.message,
|
|
72
|
+
description: \`Detected by custom judge \${judgeId} at line \${i + 1}\`,
|
|
73
|
+
lineNumbers: [i + 1],
|
|
74
|
+
recommendation: "Review and fix the detected pattern",
|
|
75
|
+
});
|
|
76
|
+
rule.pattern.lastIndex = 0; // reset global regex
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return findings;
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
// ─── Validation ─────────────────────────────────────────────────────────────
|
|
86
|
+
function validateJudge(path) {
|
|
87
|
+
const errors = [];
|
|
88
|
+
const warnings = [];
|
|
89
|
+
if (!existsSync(path)) {
|
|
90
|
+
return { valid: false, errors: [`File not found: ${path}`], warnings: [] };
|
|
91
|
+
}
|
|
92
|
+
let content;
|
|
93
|
+
try {
|
|
94
|
+
content = readFileSync(path, "utf-8");
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { valid: false, errors: [`Cannot read file: ${path}`], warnings: [] };
|
|
98
|
+
}
|
|
99
|
+
// Check for required exports
|
|
100
|
+
if (!content.includes("export const judgeId"))
|
|
101
|
+
errors.push("Missing 'export const judgeId'");
|
|
102
|
+
if (!content.includes("export const judgeName"))
|
|
103
|
+
errors.push("Missing 'export const judgeName'");
|
|
104
|
+
if (!content.includes("export function evaluate"))
|
|
105
|
+
errors.push("Missing 'export function evaluate'");
|
|
106
|
+
// Check for Finding type
|
|
107
|
+
if (!content.includes("Finding"))
|
|
108
|
+
warnings.push("No reference to Finding type — ensure findings match expected shape");
|
|
109
|
+
// Check for severity values
|
|
110
|
+
const validSeverities = ["critical", "high", "medium", "low", "info"];
|
|
111
|
+
const sevMatches = content.match(/severity:\s*["'](\w+)["']/g) || [];
|
|
112
|
+
for (const m of sevMatches) {
|
|
113
|
+
const val = m.match(/["'](\w+)["']/)?.[1];
|
|
114
|
+
if (val && !validSeverities.includes(val)) {
|
|
115
|
+
errors.push(`Invalid severity '${val}' — must be: ${validSeverities.join(", ")}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Check for rule IDs
|
|
119
|
+
const ruleIds = content.match(/id:\s*["']([^"']+)["']/g) || [];
|
|
120
|
+
if (ruleIds.length === 0)
|
|
121
|
+
warnings.push("No rule IDs found — each rule should have a unique id");
|
|
122
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
123
|
+
}
|
|
124
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
125
|
+
const STORE = ".judges-custom";
|
|
126
|
+
export function runJudgeAuthor(argv) {
|
|
127
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
128
|
+
console.log(`
|
|
129
|
+
judges judge-author — Custom judge authoring toolkit
|
|
130
|
+
|
|
131
|
+
Usage:
|
|
132
|
+
judges judge-author --scaffold <id>
|
|
133
|
+
judges judge-author --validate <file>
|
|
134
|
+
judges judge-author --list
|
|
135
|
+
judges judge-author --test <file> --code <sample>
|
|
136
|
+
|
|
137
|
+
Options:
|
|
138
|
+
--scaffold <id> Generate a new judge scaffold
|
|
139
|
+
--name <name> Judge display name
|
|
140
|
+
--category <cat> Category (default: custom)
|
|
141
|
+
--severity <sev> Default severity (default: medium)
|
|
142
|
+
--validate <file> Validate judge file structure
|
|
143
|
+
--list List existing custom judges
|
|
144
|
+
--test <file> Test a judge against sample code
|
|
145
|
+
--code <sample> Sample code file to test against
|
|
146
|
+
--output <dir> Output directory (default: .judges-custom)
|
|
147
|
+
--format json JSON output
|
|
148
|
+
--help, -h Show this help
|
|
149
|
+
`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
153
|
+
// List existing judges
|
|
154
|
+
if (argv.includes("--list")) {
|
|
155
|
+
const builtin = defaultRegistry.getJudges();
|
|
156
|
+
const customDir = STORE;
|
|
157
|
+
let customCount = 0;
|
|
158
|
+
if (existsSync(customDir)) {
|
|
159
|
+
try {
|
|
160
|
+
const { readdirSync } = require("fs");
|
|
161
|
+
customCount = readdirSync(customDir).filter((f) => f.endsWith(".ts") || f.endsWith(".json")).length;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* skip */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (format === "json") {
|
|
168
|
+
console.log(JSON.stringify({ builtin: builtin.length, custom: customCount, judges: builtin.map((j) => j.id) }, null, 2));
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
console.log(`\n Judges Registry\n ──────────────────────────`);
|
|
172
|
+
console.log(` Built-in: ${builtin.length}`);
|
|
173
|
+
console.log(` Custom: ${customCount}`);
|
|
174
|
+
console.log(`\n Built-in judges:`);
|
|
175
|
+
for (const j of builtin) {
|
|
176
|
+
console.log(` ${j.id}`);
|
|
177
|
+
}
|
|
178
|
+
console.log("");
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Scaffold
|
|
183
|
+
const scaffoldId = argv.find((_a, i) => argv[i - 1] === "--scaffold");
|
|
184
|
+
if (scaffoldId) {
|
|
185
|
+
const name = argv.find((_a, i) => argv[i - 1] === "--name");
|
|
186
|
+
const category = argv.find((_a, i) => argv[i - 1] === "--category");
|
|
187
|
+
const severity = argv.find((_a, i) => argv[i - 1] === "--severity");
|
|
188
|
+
const outputDir = argv.find((_a, i) => argv[i - 1] === "--output") || STORE;
|
|
189
|
+
const scaffold = scaffoldJudge(scaffoldId, {
|
|
190
|
+
name: name || undefined,
|
|
191
|
+
category: category || undefined,
|
|
192
|
+
severity: severity || undefined,
|
|
193
|
+
});
|
|
194
|
+
const code = generateJudgeFile(scaffold);
|
|
195
|
+
if (!existsSync(outputDir))
|
|
196
|
+
mkdirSync(outputDir, { recursive: true });
|
|
197
|
+
const outPath = join(outputDir, `${scaffoldId}.ts`);
|
|
198
|
+
writeFileSync(outPath, code);
|
|
199
|
+
// Also write the JSON definition
|
|
200
|
+
const jsonPath = join(outputDir, `${scaffoldId}.json`);
|
|
201
|
+
writeFileSync(jsonPath, JSON.stringify(scaffold, null, 2));
|
|
202
|
+
if (format === "json") {
|
|
203
|
+
console.log(JSON.stringify({ scaffold, files: [outPath, jsonPath] }, null, 2));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
console.log(`\n Judge Scaffolded: ${scaffoldId}\n ──────────────────────────`);
|
|
207
|
+
console.log(` TypeScript: ${outPath}`);
|
|
208
|
+
console.log(` Definition: ${jsonPath}`);
|
|
209
|
+
console.log(`\n Next steps:`);
|
|
210
|
+
console.log(` 1. Edit ${outPath} to add detection patterns`);
|
|
211
|
+
console.log(` 2. Validate with: judges judge-author --validate ${outPath}`);
|
|
212
|
+
console.log(` 3. Test with: judges judge-author --test ${outPath} --code sample.ts\n`);
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// Validate
|
|
217
|
+
const validatePath = argv.find((_a, i) => argv[i - 1] === "--validate");
|
|
218
|
+
if (validatePath) {
|
|
219
|
+
const result = validateJudge(validatePath);
|
|
220
|
+
if (format === "json") {
|
|
221
|
+
console.log(JSON.stringify(result, null, 2));
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
console.log(`\n Validation: ${validatePath}`);
|
|
225
|
+
console.log(` Status: ${result.valid ? "✅ Valid" : "❌ Invalid"}\n ──────────────────────────`);
|
|
226
|
+
for (const e of result.errors)
|
|
227
|
+
console.log(` ❌ ${e}`);
|
|
228
|
+
for (const w of result.warnings)
|
|
229
|
+
console.log(` ⚠️ ${w}`);
|
|
230
|
+
if (result.valid && result.warnings.length === 0)
|
|
231
|
+
console.log(` All checks passed`);
|
|
232
|
+
console.log("");
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
// Test
|
|
237
|
+
const testPath = argv.find((_a, i) => argv[i - 1] === "--test");
|
|
238
|
+
const codePath = argv.find((_a, i) => argv[i - 1] === "--code");
|
|
239
|
+
if (testPath) {
|
|
240
|
+
if (!codePath || !existsSync(codePath)) {
|
|
241
|
+
console.error(" Provide --code <file> with a sample code file to test against.");
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// Validate first
|
|
245
|
+
const validation = validateJudge(testPath);
|
|
246
|
+
if (!validation.valid) {
|
|
247
|
+
console.error(" Judge file has validation errors. Fix errors before testing.");
|
|
248
|
+
for (const e of validation.errors)
|
|
249
|
+
console.error(` ❌ ${e}`);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
console.log(`\n Testing ${testPath} against ${codePath}`);
|
|
253
|
+
console.log(` (Note: full testing requires loading the judge module at runtime)\n`);
|
|
254
|
+
console.log(` Validation: ✅ Passed`);
|
|
255
|
+
console.log(` Structure: ✅ Valid`);
|
|
256
|
+
console.log(`\n To run a full test, import and call the evaluate() function directly.\n`);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
console.log(" Use --scaffold, --validate, --list, or --test. Run --help for details.");
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=judge-author.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge-author.js","sourceRoot":"","sources":["../../src/commands/judge-author.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning path — generates personalized developer learning
|
|
3
|
+
* modules from recurring finding patterns, tracking skill
|
|
4
|
+
* progression over time.
|
|
5
|
+
*
|
|
6
|
+
* All data stored locally.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runLearningPath(argv: string[]): void;
|
|
9
|
+
//# sourceMappingURL=learning-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learning-path.d.ts","sourceRoot":"","sources":["../../src/commands/learning-path.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgNH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA4JpD"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning path — generates personalized developer learning
|
|
3
|
+
* modules from recurring finding patterns, tracking skill
|
|
4
|
+
* progression over time.
|
|
5
|
+
*
|
|
6
|
+
* All data stored locally.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
// ─── Module Library ─────────────────────────────────────────────────────────
|
|
11
|
+
const MODULES = [
|
|
12
|
+
{
|
|
13
|
+
id: "sql-injection-101",
|
|
14
|
+
topic: "SQL Injection Prevention",
|
|
15
|
+
difficulty: "beginner",
|
|
16
|
+
description: "Learn to identify and prevent SQL injection vulnerabilities",
|
|
17
|
+
resources: [
|
|
18
|
+
"OWASP SQL Injection Prevention Cheat Sheet",
|
|
19
|
+
"Use parameterized queries instead of string concatenation",
|
|
20
|
+
"Apply input validation at system boundaries",
|
|
21
|
+
],
|
|
22
|
+
exercises: [
|
|
23
|
+
"Refactor a string-concatenated query to use parameterized statements",
|
|
24
|
+
"Identify SQL injection vectors in a sample CRUD controller",
|
|
25
|
+
"Implement an ORM-based data access layer",
|
|
26
|
+
],
|
|
27
|
+
prerequisites: [],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "xss-prevention",
|
|
31
|
+
topic: "Cross-Site Scripting (XSS) Prevention",
|
|
32
|
+
difficulty: "beginner",
|
|
33
|
+
description: "Understand and prevent XSS vulnerabilities in web applications",
|
|
34
|
+
resources: [
|
|
35
|
+
"OWASP XSS Prevention Cheat Sheet",
|
|
36
|
+
"Content Security Policy (CSP) headers",
|
|
37
|
+
"Output encoding for different contexts (HTML, JS, URL, CSS)",
|
|
38
|
+
],
|
|
39
|
+
exercises: [
|
|
40
|
+
"Add output encoding to a template rendering user input",
|
|
41
|
+
"Configure CSP headers for a web application",
|
|
42
|
+
"Test for DOM-based XSS in a client-side application",
|
|
43
|
+
],
|
|
44
|
+
prerequisites: [],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "auth-security",
|
|
48
|
+
topic: "Authentication & Authorization",
|
|
49
|
+
difficulty: "intermediate",
|
|
50
|
+
description: "Implement secure authentication and authorization patterns",
|
|
51
|
+
resources: [
|
|
52
|
+
"OWASP Authentication Cheat Sheet",
|
|
53
|
+
"JWT best practices and pitfalls",
|
|
54
|
+
"OAuth 2.0 and OpenID Connect fundamentals",
|
|
55
|
+
],
|
|
56
|
+
exercises: [
|
|
57
|
+
"Implement rate limiting on login endpoints",
|
|
58
|
+
"Add proper JWT validation with signature verification",
|
|
59
|
+
"Design role-based access control for an API",
|
|
60
|
+
],
|
|
61
|
+
prerequisites: ["sql-injection-101"],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "crypto-basics",
|
|
65
|
+
topic: "Cryptography Fundamentals",
|
|
66
|
+
difficulty: "intermediate",
|
|
67
|
+
description: "Use cryptographic primitives correctly",
|
|
68
|
+
resources: [
|
|
69
|
+
"OWASP Cryptographic Storage Cheat Sheet",
|
|
70
|
+
"Modern cipher suites and key management",
|
|
71
|
+
"Password hashing: bcrypt, scrypt, Argon2",
|
|
72
|
+
],
|
|
73
|
+
exercises: [
|
|
74
|
+
"Replace MD5/SHA-1 with SHA-256 or better",
|
|
75
|
+
"Implement proper password hashing with Argon2",
|
|
76
|
+
"Set up encrypted-at-rest storage for sensitive data",
|
|
77
|
+
],
|
|
78
|
+
prerequisites: [],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "ssrf-prevention",
|
|
82
|
+
topic: "Server-Side Request Forgery (SSRF)",
|
|
83
|
+
difficulty: "advanced",
|
|
84
|
+
description: "Prevent SSRF attacks in web applications",
|
|
85
|
+
resources: [
|
|
86
|
+
"OWASP SSRF Prevention Cheat Sheet",
|
|
87
|
+
"URL validation and allowlisting strategies",
|
|
88
|
+
"Network segmentation for defense in depth",
|
|
89
|
+
],
|
|
90
|
+
exercises: [
|
|
91
|
+
"Implement URL validation with an allowlist",
|
|
92
|
+
"Block internal IP ranges in outbound requests",
|
|
93
|
+
"Design a secure proxy service for external API calls",
|
|
94
|
+
],
|
|
95
|
+
prerequisites: ["auth-security"],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "supply-chain",
|
|
99
|
+
topic: "Supply Chain Security",
|
|
100
|
+
difficulty: "advanced",
|
|
101
|
+
description: "Secure the software supply chain",
|
|
102
|
+
resources: [
|
|
103
|
+
"SLSA framework for supply chain integrity",
|
|
104
|
+
"Dependency pinning and lock file management",
|
|
105
|
+
"SBOM generation and consumption",
|
|
106
|
+
],
|
|
107
|
+
exercises: [
|
|
108
|
+
"Generate an SBOM with `judges sbom-export`",
|
|
109
|
+
"Audit dependencies with `judges dep-correlate`",
|
|
110
|
+
"Set up automated dependency update policies",
|
|
111
|
+
],
|
|
112
|
+
prerequisites: ["crypto-basics"],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "secure-code-review",
|
|
116
|
+
topic: "Secure Code Review Practices",
|
|
117
|
+
difficulty: "intermediate",
|
|
118
|
+
description: "Conduct effective security-focused code reviews",
|
|
119
|
+
resources: [
|
|
120
|
+
"OWASP Code Review Guide",
|
|
121
|
+
"Common vulnerability patterns by language",
|
|
122
|
+
"Using Judges for automated security review",
|
|
123
|
+
],
|
|
124
|
+
exercises: [
|
|
125
|
+
"Review a sample PR for security issues using Judges",
|
|
126
|
+
"Create a custom judge with `judges judge-author`",
|
|
127
|
+
"Build a team pattern library with `judges pattern-registry`",
|
|
128
|
+
],
|
|
129
|
+
prerequisites: ["sql-injection-101", "xss-prevention"],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "incident-handling",
|
|
133
|
+
topic: "Security Incident Handling",
|
|
134
|
+
difficulty: "advanced",
|
|
135
|
+
description: "Respond to and manage security incidents",
|
|
136
|
+
resources: [
|
|
137
|
+
"NIST Incident Response Guide",
|
|
138
|
+
"Post-incident review best practices",
|
|
139
|
+
"Using `judges incident-response` for playbook generation",
|
|
140
|
+
],
|
|
141
|
+
exercises: [
|
|
142
|
+
"Create an incident response playbook for a critical finding",
|
|
143
|
+
"Conduct a tabletop exercise with the team",
|
|
144
|
+
"Set up SLA tracking with `judges sla-track`",
|
|
145
|
+
],
|
|
146
|
+
prerequisites: ["secure-code-review", "auth-security"],
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
150
|
+
const TOPIC_PATTERNS = {
|
|
151
|
+
"SQL Injection Prevention": ["sql", "injection", "query", "database"],
|
|
152
|
+
"Cross-Site Scripting (XSS) Prevention": ["xss", "cross-site", "script", "sanitize", "encode"],
|
|
153
|
+
"Authentication & Authorization": ["auth", "login", "password", "token", "jwt", "session", "rbac"],
|
|
154
|
+
"Cryptography Fundamentals": ["crypto", "cipher", "hash", "encrypt", "md5", "sha1", "key"],
|
|
155
|
+
"Server-Side Request Forgery (SSRF)": ["ssrf", "request-forgery", "url", "redirect"],
|
|
156
|
+
"Supply Chain Security": ["dependency", "package", "npm", "supply-chain", "sbom"],
|
|
157
|
+
"Secure Code Review Practices": ["review", "code-quality", "pattern"],
|
|
158
|
+
"Security Incident Handling": ["incident", "breach", "response", "escalation"],
|
|
159
|
+
};
|
|
160
|
+
function analyzeWeaknesses(findings) {
|
|
161
|
+
const topicCounts = new Map();
|
|
162
|
+
for (const f of findings) {
|
|
163
|
+
const text = `${f.ruleId} ${f.title}`.toLowerCase();
|
|
164
|
+
for (const [topic, patterns] of Object.entries(TOPIC_PATTERNS)) {
|
|
165
|
+
if (patterns.some((p) => text.includes(p))) {
|
|
166
|
+
topicCounts.set(topic, (topicCounts.get(topic) || 0) + 1);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return [...topicCounts.entries()]
|
|
171
|
+
.map(([topic, count]) => ({ topic, findingCount: count }))
|
|
172
|
+
.sort((a, b) => b.findingCount - a.findingCount);
|
|
173
|
+
}
|
|
174
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
175
|
+
const STORE = ".judges-learning";
|
|
176
|
+
export function runLearningPath(argv) {
|
|
177
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
178
|
+
console.log(`
|
|
179
|
+
judges learning-path — Personalized security learning recommendations
|
|
180
|
+
|
|
181
|
+
Usage:
|
|
182
|
+
judges learning-path
|
|
183
|
+
judges learning-path --developer "alice"
|
|
184
|
+
judges learning-path --modules
|
|
185
|
+
judges learning-path --complete <module-id>
|
|
186
|
+
|
|
187
|
+
Options:
|
|
188
|
+
--developer <name> Developer name for personalized path
|
|
189
|
+
--modules List all available learning modules
|
|
190
|
+
--complete <id> Mark a module as completed
|
|
191
|
+
--reset Reset progress for developer
|
|
192
|
+
--format json JSON output
|
|
193
|
+
--help, -h Show this help
|
|
194
|
+
`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
198
|
+
// List modules
|
|
199
|
+
if (argv.includes("--modules")) {
|
|
200
|
+
if (format === "json") {
|
|
201
|
+
console.log(JSON.stringify(MODULES, null, 2));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(`\n Learning Modules (${MODULES.length})\n ──────────────────────────`);
|
|
205
|
+
for (const m of MODULES) {
|
|
206
|
+
console.log(` [${m.difficulty.padEnd(12)}] ${m.id.padEnd(25)} ${m.topic}`);
|
|
207
|
+
}
|
|
208
|
+
console.log("");
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (!existsSync(STORE))
|
|
213
|
+
mkdirSync(STORE, { recursive: true });
|
|
214
|
+
const devName = argv.find((_a, i) => argv[i - 1] === "--developer") || "default";
|
|
215
|
+
const progressPath = join(STORE, `${devName}-progress.json`);
|
|
216
|
+
let progress = existsSync(progressPath)
|
|
217
|
+
? JSON.parse(readFileSync(progressPath, "utf-8"))
|
|
218
|
+
: { developer: devName, completedModules: [], weakAreas: [], skillLevel: 1, lastUpdated: new Date().toISOString() };
|
|
219
|
+
// Reset
|
|
220
|
+
if (argv.includes("--reset")) {
|
|
221
|
+
progress = {
|
|
222
|
+
developer: devName,
|
|
223
|
+
completedModules: [],
|
|
224
|
+
weakAreas: [],
|
|
225
|
+
skillLevel: 1,
|
|
226
|
+
lastUpdated: new Date().toISOString(),
|
|
227
|
+
};
|
|
228
|
+
writeFileSync(progressPath, JSON.stringify(progress, null, 2));
|
|
229
|
+
console.log(` Reset progress for ${devName}`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Complete module
|
|
233
|
+
const completeId = argv.find((_a, i) => argv[i - 1] === "--complete");
|
|
234
|
+
if (completeId) {
|
|
235
|
+
const mod = MODULES.find((m) => m.id === completeId);
|
|
236
|
+
if (!mod) {
|
|
237
|
+
console.error(` Module ${completeId} not found.`);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (!progress.completedModules.includes(completeId)) {
|
|
241
|
+
progress.completedModules.push(completeId);
|
|
242
|
+
progress.skillLevel = Math.min(10, Math.round((progress.completedModules.length / MODULES.length) * 10));
|
|
243
|
+
progress.lastUpdated = new Date().toISOString();
|
|
244
|
+
writeFileSync(progressPath, JSON.stringify(progress, null, 2));
|
|
245
|
+
}
|
|
246
|
+
console.log(` Completed: ${mod.topic} — Skill level: ${progress.skillLevel}/10`);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// Analyze and recommend
|
|
250
|
+
const findings = [];
|
|
251
|
+
const paths = [".judges-findings.json", "judges-report.json"];
|
|
252
|
+
for (const p of paths) {
|
|
253
|
+
if (!existsSync(p))
|
|
254
|
+
continue;
|
|
255
|
+
try {
|
|
256
|
+
const data = JSON.parse(readFileSync(p, "utf-8"));
|
|
257
|
+
if (Array.isArray(data))
|
|
258
|
+
findings.push(...data);
|
|
259
|
+
else if (data.findings)
|
|
260
|
+
findings.push(...data.findings);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
/* skip */
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const weakAreas = analyzeWeaknesses(findings);
|
|
267
|
+
progress.weakAreas = weakAreas;
|
|
268
|
+
progress.lastUpdated = new Date().toISOString();
|
|
269
|
+
writeFileSync(progressPath, JSON.stringify(progress, null, 2));
|
|
270
|
+
// Find recommended modules (not completed, prerequisites met)
|
|
271
|
+
const recommended = MODULES.filter((m) => {
|
|
272
|
+
if (progress.completedModules.includes(m.id))
|
|
273
|
+
return false;
|
|
274
|
+
const prereqsMet = m.prerequisites.every((p) => progress.completedModules.includes(p));
|
|
275
|
+
if (!prereqsMet)
|
|
276
|
+
return false;
|
|
277
|
+
// Prioritize modules matching weak areas
|
|
278
|
+
return true;
|
|
279
|
+
});
|
|
280
|
+
// Sort by relevance to weak areas
|
|
281
|
+
const sortedRecs = recommended.sort((a, b) => {
|
|
282
|
+
const aRelevance = weakAreas.find((w) => w.topic === a.topic)?.findingCount || 0;
|
|
283
|
+
const bRelevance = weakAreas.find((w) => w.topic === b.topic)?.findingCount || 0;
|
|
284
|
+
return bRelevance - aRelevance;
|
|
285
|
+
});
|
|
286
|
+
const report = {
|
|
287
|
+
recommendedModules: sortedRecs,
|
|
288
|
+
progress,
|
|
289
|
+
timestamp: new Date().toISOString(),
|
|
290
|
+
};
|
|
291
|
+
if (format === "json") {
|
|
292
|
+
console.log(JSON.stringify(report, null, 2));
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
console.log(`\n Learning Path — ${devName}`);
|
|
296
|
+
console.log(` Skill Level: ${progress.skillLevel}/10 Completed: ${progress.completedModules.length}/${MODULES.length}`);
|
|
297
|
+
console.log(` ──────────────────────────`);
|
|
298
|
+
if (weakAreas.length > 0) {
|
|
299
|
+
console.log(`\n Weak Areas (from findings):`);
|
|
300
|
+
for (const w of weakAreas.slice(0, 5)) {
|
|
301
|
+
console.log(` ${w.topic.padEnd(35)} ${w.findingCount} findings`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
console.log(`\n Recommended Modules:`);
|
|
305
|
+
if (sortedRecs.length === 0) {
|
|
306
|
+
console.log(` 🎉 All available modules completed!`);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
for (const m of sortedRecs.slice(0, 5)) {
|
|
310
|
+
const relevant = weakAreas.find((w) => w.topic === m.topic);
|
|
311
|
+
const tag = relevant ? ` (${relevant.findingCount} findings)` : "";
|
|
312
|
+
console.log(` [${m.difficulty.padEnd(12)}] ${m.id}${tag}`);
|
|
313
|
+
console.log(` ${m.topic}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (progress.completedModules.length > 0) {
|
|
317
|
+
console.log(`\n Completed:`);
|
|
318
|
+
for (const id of progress.completedModules) {
|
|
319
|
+
const mod = MODULES.find((m) => m.id === id);
|
|
320
|
+
console.log(` ✅ ${mod?.topic || id}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
console.log("");
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=learning-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learning-path.js","sourceRoot":"","sources":["../../src/commands/learning-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License scan — scans project dependencies for license
|
|
3
|
+
* compatibility, flags copyleft/unknown licenses, and
|
|
4
|
+
* generates a license obligations report.
|
|
5
|
+
*
|
|
6
|
+
* All data from local files.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runLicenseScan(argv: string[]): void;
|
|
9
|
+
//# sourceMappingURL=license-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"license-scan.d.ts","sourceRoot":"","sources":["../../src/commands/license-scan.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiIH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkFnD"}
|