@kevinrabun/judges 3.117.1 → 3.117.3
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/dist/ast/taint-tracker.js +2 -29
- package/dist/evaluators/index.js +14 -10
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -11,25 +11,8 @@
|
|
|
11
11
|
// - Same-file inter-procedural taint (function parameter → return tracking)
|
|
12
12
|
// - Guard clause sensitivity (validation guards reduce taint confidence)
|
|
13
13
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
-
import
|
|
14
|
+
import ts from "typescript";
|
|
15
15
|
import { normalizeLanguage } from "../language-patterns.js";
|
|
16
|
-
// Lazy-load the TypeScript compiler API so that modules which transitively
|
|
17
|
-
// import this file (e.g. the VS Code extension bundle) do not crash at load
|
|
18
|
-
// time when the `typescript` package is not available at runtime.
|
|
19
|
-
//
|
|
20
|
-
// In CJS bundles (esbuild for VS Code extension), `import.meta.url` is empty
|
|
21
|
-
// but the bundler emits a CJS `require` for externals — so `require` just
|
|
22
|
-
// works. In native ESM (tests, CLI), we use `createRequire` from the real
|
|
23
|
-
// `import.meta.url`.
|
|
24
|
-
let _ts;
|
|
25
|
-
function getTS() {
|
|
26
|
-
if (!_ts) {
|
|
27
|
-
const metaUrl = typeof import.meta?.url === "string" ? import.meta.url : undefined;
|
|
28
|
-
const req = metaUrl ? createRequire(metaUrl) : require;
|
|
29
|
-
_ts = req("typescript");
|
|
30
|
-
}
|
|
31
|
-
return _ts;
|
|
32
|
-
}
|
|
33
16
|
// ─── Source / Sink Definitions ───────────────────────────────────────────────
|
|
34
17
|
const SOURCE_PATTERNS = [
|
|
35
18
|
{ pattern: /\breq(?:uest)?\.(?:body|query|params|headers|cookies)\b/i, kind: "http-param" },
|
|
@@ -164,7 +147,6 @@ function containsWordBoundary(text, varName) {
|
|
|
164
147
|
* Tracks which function parameters flow to return values.
|
|
165
148
|
*/
|
|
166
149
|
function buildFunctionTaintMap(sourceFile, _taintMap) {
|
|
167
|
-
const ts = getTS();
|
|
168
150
|
const result = new Map();
|
|
169
151
|
ts.forEachChild(sourceFile, function walk(node) {
|
|
170
152
|
if (ts.isFunctionDeclaration(node) ||
|
|
@@ -213,7 +195,6 @@ function buildFunctionTaintMap(sourceFile, _taintMap) {
|
|
|
213
195
|
return result;
|
|
214
196
|
}
|
|
215
197
|
function getFnName(node) {
|
|
216
|
-
const ts = getTS();
|
|
217
198
|
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
|
|
218
199
|
return node.name?.getText();
|
|
219
200
|
}
|
|
@@ -707,14 +688,7 @@ export function analyzeTaintFlows(code, language) {
|
|
|
707
688
|
switch (lang) {
|
|
708
689
|
case "javascript":
|
|
709
690
|
case "typescript":
|
|
710
|
-
|
|
711
|
-
return analyzeTypeScriptTaint(code, lang);
|
|
712
|
-
}
|
|
713
|
-
catch {
|
|
714
|
-
// typescript package unavailable (e.g. VS Code extension bundle) —
|
|
715
|
-
// fall through to regex-based analysis
|
|
716
|
-
return analyzeRegexTaint(code, LANGUAGE_PATTERN_MAP[lang]);
|
|
717
|
-
}
|
|
691
|
+
return analyzeTypeScriptTaint(code, lang);
|
|
718
692
|
default: {
|
|
719
693
|
const langPatterns = LANGUAGE_PATTERN_MAP[lang];
|
|
720
694
|
return analyzeRegexTaint(code, langPatterns);
|
|
@@ -723,7 +697,6 @@ export function analyzeTaintFlows(code, language) {
|
|
|
723
697
|
}
|
|
724
698
|
// ─── TypeScript / JavaScript Taint Analysis ──────────────────────────────────
|
|
725
699
|
function analyzeTypeScriptTaint(code, language) {
|
|
726
|
-
const ts = getTS();
|
|
727
700
|
const scriptKind = language === "typescript" ? ts.ScriptKind.TS : ts.ScriptKind.JS;
|
|
728
701
|
const sourceFile = ts.createSourceFile("input." + (language === "typescript" ? "ts" : "js"), code, ts.ScriptTarget.Latest, true, scriptKind);
|
|
729
702
|
const flows = [];
|
package/dist/evaluators/index.js
CHANGED
|
@@ -435,16 +435,8 @@ export function evaluateWithJudge(judge, code, language, context, options) {
|
|
|
435
435
|
: undefined;
|
|
436
436
|
findings.push(...judge.analyze(code, language, analyzeCtx));
|
|
437
437
|
}
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
if (boostResult.findings.length > 0) {
|
|
441
|
-
// Deduplicate: only add boost findings whose ruleId isn't already present
|
|
442
|
-
for (const bf of boostResult.findings) {
|
|
443
|
-
if (!findings.some((f) => f.ruleId === bf.ruleId)) {
|
|
444
|
-
findings.push(bf);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
438
|
+
// NOTE: Recall boost (applyRecallBoost) is applied once in evaluateWithTribunal()
|
|
439
|
+
// rather than per-judge, to avoid generating N duplicate boost findings.
|
|
448
440
|
// ── Absence gating ──
|
|
449
441
|
// Absence-based findings ("no rate limiting", "no monitoring", etc.) are
|
|
450
442
|
// project-level concerns that cannot be accurately assessed from a single
|
|
@@ -706,6 +698,18 @@ export function evaluateWithTribunal(code, language, context, options) {
|
|
|
706
698
|
? "warning"
|
|
707
699
|
: "pass";
|
|
708
700
|
const rawFindings = evaluations.flatMap((e) => e.findings);
|
|
701
|
+
// ── Recall boost (once, not per-judge) ──
|
|
702
|
+
// Apply supplementary recall-boost patterns a single time and merge into
|
|
703
|
+
// the raw findings before cross-evaluator dedup. Previously this ran
|
|
704
|
+
// inside evaluateWithJudge(), producing N identical copies per judge.
|
|
705
|
+
const boostResult = applyRecallBoost(code, language);
|
|
706
|
+
if (boostResult.findings.length > 0) {
|
|
707
|
+
for (const bf of boostResult.findings) {
|
|
708
|
+
if (!rawFindings.some((f) => f.ruleId === bf.ruleId)) {
|
|
709
|
+
rawFindings.push(bf);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
709
713
|
const dedupedFindings = crossEvaluatorDedup(rawFindings);
|
|
710
714
|
const { filtered: fpFiltered } = filterFalsePositiveHeuristics(dedupedFindings, code, language, enrichedOptions?.filePath);
|
|
711
715
|
const configFiltered = applyConfig(fpFiltered, options?.config);
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/kevinrabun/judges",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "3.117.
|
|
10
|
+
"version": "3.117.3",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@kevinrabun/judges",
|
|
15
|
-
"version": "3.117.
|
|
15
|
+
"version": "3.117.3",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|