@quantakrypto/core 0.2.1 → 0.3.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/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +105 -0
- package/dist/dependencies.js.map +1 -1
- package/dist/detect-utils.d.ts +26 -1
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +26 -0
- package/dist/detect-utils.js.map +1 -1
- package/dist/detectors/pem.d.ts +4 -0
- package/dist/detectors/pem.d.ts.map +1 -1
- package/dist/detectors/pem.js +113 -91
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/source.d.ts +9 -2
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +366 -265
- package/dist/detectors/source.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +6 -3
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +11 -6
- package/dist/inventory.js.map +1 -1
- package/dist/parallel.d.ts.map +1 -1
- package/dist/parallel.js +2 -0
- package/dist/parallel.js.map +1 -1
- package/dist/registry.d.ts +16 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +31 -0
- package/dist/registry.js.map +1 -1
- package/dist/report.d.ts +9 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +56 -23
- package/dist/report.js.map +1 -1
- package/dist/scan-worker.js +1 -1
- package/dist/scan-worker.js.map +1 -1
- package/dist/scan.d.ts +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +8 -2
- package/dist/scan.js.map +1 -1
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/dependencies.ts +105 -0
- package/src/detect-utils.ts +57 -1
- package/src/detectors/pem.ts +124 -105
- package/src/detectors/source.ts +466 -343
- package/src/index.ts +2 -1
- package/src/inventory.ts +12 -6
- package/src/parallel.ts +9 -1
- package/src/registry.ts +39 -1
- package/src/report.ts +79 -23
- package/src/scan-worker.ts +12 -5
- package/src/scan.ts +19 -5
- package/src/types.ts +54 -0
- package/src/version.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -25,8 +25,9 @@ export { AbortError, BudgetExceededError } from "./errors.js";
|
|
|
25
25
|
export { scanParallel, mergeChunkResults, chunkByBytes } from "./parallel.js";
|
|
26
26
|
export type { ScanChunk, ChunkResult, SizedFile } from "./parallel.js";
|
|
27
27
|
|
|
28
|
-
// Detector registry (plugin point) + helpers.
|
|
28
|
+
// Detector registry (plugin point) + helpers + the rule catalog.
|
|
29
29
|
export { DetectorRegistry, defaultRegistry, detectorScope } from "./registry.js";
|
|
30
|
+
export type { RuleCatalogEntry } from "./registry.js";
|
|
30
31
|
|
|
31
32
|
// Canonical baseline (shared by qScan + the Action).
|
|
32
33
|
export {
|
package/src/inventory.ts
CHANGED
|
@@ -33,10 +33,16 @@ function penaltyFor(weight: number, occurrence: number): number {
|
|
|
33
33
|
return weight / Math.sqrt(occurrence);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** Decay constant for the readiness score (larger = more forgiving). */
|
|
37
|
+
const SCORE_SCALE = 100;
|
|
38
|
+
|
|
36
39
|
/**
|
|
37
|
-
* Compute a 0–100 readiness score.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
+
* Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was
|
|
41
|
+
* found. Findings accrue a severity-weighted penalty (with per-bucket diminishing
|
|
42
|
+
* returns), then the score is `100 * e^(-penalty/scale)`. Exponential decay keeps
|
|
43
|
+
* the score responsive across the whole range — fixing findings always raises it,
|
|
44
|
+
* and a large legacy repo lands low without pinning flat at 0 (which made progress
|
|
45
|
+
* invisible under the old linear model). Tuned so one low ~97, one critical ~74.
|
|
40
46
|
*/
|
|
41
47
|
export function readinessScore(findings: Finding[]): number {
|
|
42
48
|
if (findings.length === 0) return 100;
|
|
@@ -49,13 +55,13 @@ export function readinessScore(findings: Finding[]): number {
|
|
|
49
55
|
info: 0,
|
|
50
56
|
};
|
|
51
57
|
|
|
52
|
-
let
|
|
58
|
+
let penalty = 0;
|
|
53
59
|
for (const f of findings) {
|
|
54
60
|
seen[f.severity] += 1;
|
|
55
|
-
|
|
61
|
+
penalty += penaltyFor(SEVERITY_WEIGHT[f.severity], seen[f.severity]);
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
return Math.max(0, Math.min(100, Math.round(
|
|
64
|
+
return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
/** Build the full inventory (counts + HNDL + score) from a set of findings. */
|
package/src/parallel.ts
CHANGED
|
@@ -191,6 +191,8 @@ export async function scanParallel(options: ParallelScanOptions): Promise<ScanRe
|
|
|
191
191
|
config: options.config !== false,
|
|
192
192
|
deps: options.dependencies !== false,
|
|
193
193
|
scanMinified: options.scanMinified === true,
|
|
194
|
+
// Plain string array — structured-cloneable, so it crosses the worker boundary.
|
|
195
|
+
disabledRules: options.disabledRules,
|
|
194
196
|
};
|
|
195
197
|
|
|
196
198
|
let results: ChunkResult[];
|
|
@@ -231,7 +233,13 @@ function runPool(
|
|
|
231
233
|
entry: string,
|
|
232
234
|
execArgv: string[] | undefined,
|
|
233
235
|
baseDir: string,
|
|
234
|
-
toggles: {
|
|
236
|
+
toggles: {
|
|
237
|
+
source: boolean;
|
|
238
|
+
config: boolean;
|
|
239
|
+
deps: boolean;
|
|
240
|
+
scanMinified: boolean;
|
|
241
|
+
disabledRules?: string[];
|
|
242
|
+
},
|
|
235
243
|
chunks: ScanChunk[],
|
|
236
244
|
concurrency: number,
|
|
237
245
|
onFile?: (file: string) => void,
|
package/src/registry.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* To add a language or detector, see the "Adding a detector / language" section
|
|
11
11
|
* of the package README.
|
|
12
12
|
*/
|
|
13
|
-
import type { Detector, DetectorScope } from "./types.js";
|
|
13
|
+
import type { Detector, DetectorScope, RuleMeta } from "./types.js";
|
|
14
14
|
import { sourceDetectors } from "./detectors/source.js";
|
|
15
15
|
import { pemDetector } from "./detectors/pem.js";
|
|
16
16
|
|
|
@@ -19,6 +19,12 @@ export function detectorScope(d: Detector): DetectorScope {
|
|
|
19
19
|
return d.scope ?? "source";
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** A rule plus the detector that emits it — the result of {@link DetectorRegistry.forRule}. */
|
|
23
|
+
export interface RuleCatalogEntry {
|
|
24
|
+
rule: RuleMeta;
|
|
25
|
+
detector: Detector;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* An ordered, id-indexed collection of detectors. Registration order is
|
|
24
30
|
* preserved by {@link all} for deterministic scan output. Ids must be unique.
|
|
@@ -57,6 +63,38 @@ export class DetectorRegistry {
|
|
|
57
63
|
return this.order.map((id) => this.byId.get(id)!);
|
|
58
64
|
}
|
|
59
65
|
|
|
66
|
+
/**
|
|
67
|
+
* The flattened rule catalog: every {@link RuleMeta} declared by every
|
|
68
|
+
* registered detector, in detector-registration then in-detector order. This
|
|
69
|
+
* is the single source of truth for rule metadata consumed by SARIF
|
|
70
|
+
* `rules[]`, the MCP `explain_finding` resolver, and per-rule enable/disable.
|
|
71
|
+
* Duplicate rule ids across detectors throw (ids are globally unique).
|
|
72
|
+
*/
|
|
73
|
+
ruleCatalog(): RuleMeta[] {
|
|
74
|
+
const out: RuleMeta[] = [];
|
|
75
|
+
const seen = new Set<string>();
|
|
76
|
+
for (const det of this.all()) {
|
|
77
|
+
for (const rule of det.rules ?? []) {
|
|
78
|
+
if (seen.has(rule.id)) {
|
|
79
|
+
throw new Error(`duplicate rule id in catalog: ${rule.id}`);
|
|
80
|
+
}
|
|
81
|
+
seen.add(rule.id);
|
|
82
|
+
out.push(rule);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Resolve a rule id to its {@link RuleMeta} and the detector that emits it. */
|
|
89
|
+
forRule(ruleId: string): RuleCatalogEntry | undefined {
|
|
90
|
+
for (const det of this.all()) {
|
|
91
|
+
for (const rule of det.rules ?? []) {
|
|
92
|
+
if (rule.id === ruleId) return { rule, detector: det };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
60
98
|
/** A shallow copy of this registry (useful to extend the defaults). */
|
|
61
99
|
clone(): DetectorRegistry {
|
|
62
100
|
return new DetectorRegistry(this.all());
|
package/src/report.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* or a human-readable text summary. No third-party dependencies — ANSI colour
|
|
4
4
|
* is emitted with raw escape codes and is off by default.
|
|
5
5
|
*/
|
|
6
|
-
import type { Finding, ScanResult, Severity } from "./types.js";
|
|
6
|
+
import type { Finding, RuleMeta, ScanResult, Severity } from "./types.js";
|
|
7
7
|
import { VERSION } from "./version.js";
|
|
8
8
|
import { SEVERITY_ORDER, sarifLevel } from "./severity.js";
|
|
9
9
|
|
|
@@ -23,6 +23,14 @@ export interface ReportOptions {
|
|
|
23
23
|
* snippet there IS the sensitive value.
|
|
24
24
|
*/
|
|
25
25
|
redactSnippets?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Full rule catalog to advertise in SARIF `tool.driver.rules[]`, even for
|
|
28
|
+
* rules that produced no finding in this run. Pass
|
|
29
|
+
* `defaultRegistry.ruleCatalog()`. When omitted, only the rules that actually
|
|
30
|
+
* fired are emitted (the historical behaviour). SARIF-only; ignored by
|
|
31
|
+
* {@link toJson}.
|
|
32
|
+
*/
|
|
33
|
+
catalog?: RuleMeta[];
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
const SARIF_SCHEMA =
|
|
@@ -56,40 +64,88 @@ function sarifRank(severity: Severity): number {
|
|
|
56
64
|
}
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
/** Build a SARIF `rules[]` entry from a rule's severity/title/message/etc. */
|
|
68
|
+
function sarifRule(spec: {
|
|
69
|
+
id: string;
|
|
70
|
+
title: string;
|
|
71
|
+
message: string;
|
|
72
|
+
severity: Severity;
|
|
73
|
+
category: string;
|
|
74
|
+
algorithm?: string;
|
|
75
|
+
hndl: boolean;
|
|
76
|
+
cwe?: string;
|
|
77
|
+
remediation?: string;
|
|
78
|
+
}): Record<string, unknown> {
|
|
79
|
+
return {
|
|
80
|
+
id: spec.id,
|
|
81
|
+
name: spec.id,
|
|
82
|
+
shortDescription: { text: spec.title },
|
|
83
|
+
fullDescription: { text: spec.message },
|
|
84
|
+
defaultConfiguration: { level: sarifLevel(spec.severity), rank: sarifRank(spec.severity) },
|
|
85
|
+
...(spec.remediation ? { help: { text: `Remediation: ${spec.remediation}` } } : {}),
|
|
86
|
+
properties: {
|
|
87
|
+
category: spec.category,
|
|
88
|
+
...(spec.algorithm ? { algorithm: spec.algorithm } : {}),
|
|
89
|
+
hndl: spec.hndl,
|
|
90
|
+
...(spec.cwe ? { cwe: spec.cwe, "security-severity": securitySeverity(spec.severity) } : {}),
|
|
91
|
+
...(spec.cwe ? { tags: ["security", spec.cwe] } : {}),
|
|
92
|
+
},
|
|
93
|
+
...(spec.cwe
|
|
94
|
+
? {
|
|
95
|
+
relationships: [
|
|
96
|
+
{ target: { id: spec.cwe, toolComponent: { name: "CWE" } }, kinds: ["relevant"] },
|
|
97
|
+
],
|
|
98
|
+
}
|
|
99
|
+
: {}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
59
103
|
/** Serialize a scan result as SARIF 2.1.0. */
|
|
60
104
|
export function toSarif(result: ScanResult, opts?: ReportOptions): SarifLog {
|
|
61
105
|
const redactSnippets = opts?.redactSnippets ?? false;
|
|
62
|
-
// Build the
|
|
63
|
-
//
|
|
106
|
+
// Build the rule set and collect the CWE taxa referenced by any rule. When a
|
|
107
|
+
// full catalog is supplied, advertise every rule (even ones that didn't fire);
|
|
108
|
+
// otherwise emit one rule per ruleId encountered (the historical behaviour).
|
|
64
109
|
const ruleIndex = new Map<string, number>();
|
|
65
110
|
const rules: Array<Record<string, unknown>> = [];
|
|
66
111
|
const cweTaxa = new Set<string>();
|
|
112
|
+
|
|
113
|
+
for (const r of opts?.catalog ?? []) {
|
|
114
|
+
if (ruleIndex.has(r.id)) continue;
|
|
115
|
+
if (r.cwe) cweTaxa.add(r.cwe);
|
|
116
|
+
ruleIndex.set(r.id, rules.length);
|
|
117
|
+
rules.push(
|
|
118
|
+
sarifRule({
|
|
119
|
+
id: r.id,
|
|
120
|
+
title: r.title,
|
|
121
|
+
message: r.message,
|
|
122
|
+
severity: r.severity,
|
|
123
|
+
category: r.category,
|
|
124
|
+
algorithm: r.algorithm,
|
|
125
|
+
hndl: r.hndl,
|
|
126
|
+
cwe: r.cwe,
|
|
127
|
+
remediation: r.remediation,
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
67
132
|
for (const f of result.findings) {
|
|
68
133
|
if (f.cwe) cweTaxa.add(f.cwe);
|
|
69
134
|
if (ruleIndex.has(f.ruleId)) continue;
|
|
70
135
|
ruleIndex.set(f.ruleId, rules.length);
|
|
71
|
-
rules.push(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
...(f.remediation ? { help: { text: `Remediation: ${f.remediation}` } } : {}),
|
|
78
|
-
properties: {
|
|
136
|
+
rules.push(
|
|
137
|
+
sarifRule({
|
|
138
|
+
id: f.ruleId,
|
|
139
|
+
title: f.title,
|
|
140
|
+
message: f.message,
|
|
141
|
+
severity: f.severity,
|
|
79
142
|
category: f.category,
|
|
80
|
-
|
|
143
|
+
algorithm: f.algorithm,
|
|
81
144
|
hndl: f.hndl,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
? {
|
|
87
|
-
relationships: [
|
|
88
|
-
{ target: { id: f.cwe, toolComponent: { name: "CWE" } }, kinds: ["relevant"] },
|
|
89
|
-
],
|
|
90
|
-
}
|
|
91
|
-
: {}),
|
|
92
|
-
});
|
|
145
|
+
cwe: f.cwe,
|
|
146
|
+
remediation: f.remediation,
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
93
149
|
}
|
|
94
150
|
|
|
95
151
|
const results = result.findings.map((f) => {
|
package/src/scan-worker.ts
CHANGED
|
@@ -23,6 +23,7 @@ interface WorkerToggles {
|
|
|
23
23
|
config: boolean;
|
|
24
24
|
deps: boolean;
|
|
25
25
|
scanMinified: boolean;
|
|
26
|
+
disabledRules?: string[];
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
interface ChunkRequest {
|
|
@@ -57,11 +58,17 @@ if (parentPort) {
|
|
|
57
58
|
filesScanned += 1;
|
|
58
59
|
scannedNames.push(rel);
|
|
59
60
|
findings.push(
|
|
60
|
-
...detectFile(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
...detectFile(
|
|
62
|
+
rel,
|
|
63
|
+
content,
|
|
64
|
+
dets,
|
|
65
|
+
{
|
|
66
|
+
source: toggles.source,
|
|
67
|
+
config: toggles.config,
|
|
68
|
+
deps: toggles.deps,
|
|
69
|
+
},
|
|
70
|
+
toggles.disabledRules,
|
|
71
|
+
),
|
|
65
72
|
);
|
|
66
73
|
}
|
|
67
74
|
|
package/src/scan.ts
CHANGED
|
@@ -52,6 +52,7 @@ export function detectFile(
|
|
|
52
52
|
content: string,
|
|
53
53
|
dets: readonly Detector[],
|
|
54
54
|
toggles: { source: boolean; config: boolean; deps: boolean },
|
|
55
|
+
disabledRules?: readonly string[],
|
|
55
56
|
): Finding[] {
|
|
56
57
|
const out: Finding[] = [];
|
|
57
58
|
|
|
@@ -66,6 +67,13 @@ export function detectFile(
|
|
|
66
67
|
out.push(...scanManifest(file, content));
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
// Per-rule suppression: drop findings whose ruleId was disabled. Applied here
|
|
71
|
+
// so both the serial scan and the worker path honour it identically.
|
|
72
|
+
if (disabledRules && disabledRules.length > 0) {
|
|
73
|
+
const disabled = new Set(disabledRules);
|
|
74
|
+
return out.filter((f) => !disabled.has(f.ruleId));
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
return out;
|
|
70
78
|
}
|
|
71
79
|
|
|
@@ -144,11 +152,17 @@ export async function scan(options: ScanOptions): Promise<ScanResult> {
|
|
|
144
152
|
|
|
145
153
|
filesScanned += 1;
|
|
146
154
|
findings.push(
|
|
147
|
-
...detectFile(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
155
|
+
...detectFile(
|
|
156
|
+
reportedPath,
|
|
157
|
+
content,
|
|
158
|
+
dets,
|
|
159
|
+
{
|
|
160
|
+
source: doSource,
|
|
161
|
+
config: doConfig,
|
|
162
|
+
deps: doDeps,
|
|
163
|
+
},
|
|
164
|
+
options.disabledRules,
|
|
165
|
+
),
|
|
152
166
|
);
|
|
153
167
|
}
|
|
154
168
|
|
package/src/types.ts
CHANGED
|
@@ -101,6 +101,46 @@ export type DetectorScope = "source" | "config";
|
|
|
101
101
|
*/
|
|
102
102
|
export type DetectorLanguage = "js" | "python" | "go" | "java" | "any";
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Declarative metadata for a single rule a detector can emit. This is the
|
|
106
|
+
* catalog entry: the stable, queryable description of a rule keyed by the
|
|
107
|
+
* `ruleId` it stamps onto findings. It is the single source of truth for a
|
|
108
|
+
* rule's title / severity / category / remediation, consumed by the SARIF
|
|
109
|
+
* `rules[]` block, the MCP `explain_finding` resolver, and future per-rule
|
|
110
|
+
* enable/disable + language-pack work.
|
|
111
|
+
*
|
|
112
|
+
* For most rules the metadata is fixed and `detect()` builds findings straight
|
|
113
|
+
* from it (see `findingFromRule`). A few rules are inherently multi-variant
|
|
114
|
+
* (e.g. `node-crypto-keygen` spans RSA/EC/DSA/DH/Ed25519 at different
|
|
115
|
+
* severities); for those the metadata here is a REPRESENTATIVE umbrella and
|
|
116
|
+
* `detect()` refines the per-finding fields at match time. The catalog always
|
|
117
|
+
* enumerates every emittable ruleId regardless.
|
|
118
|
+
*/
|
|
119
|
+
export interface RuleMeta {
|
|
120
|
+
/** Stable rule id — matches {@link Finding.ruleId}. Unique across the catalog. */
|
|
121
|
+
id: string;
|
|
122
|
+
/** Canonical human title. */
|
|
123
|
+
title: string;
|
|
124
|
+
category: FindingCategory;
|
|
125
|
+
severity: Severity;
|
|
126
|
+
/** Default confidence for findings of this rule. */
|
|
127
|
+
confidence: Confidence;
|
|
128
|
+
/** Harvest-now-decrypt-later exposure. */
|
|
129
|
+
hndl: boolean;
|
|
130
|
+
/** Representative classical algorithm family; refined per-finding when it varies. */
|
|
131
|
+
algorithm?: AlgorithmFamily;
|
|
132
|
+
/** Associated CWE identifier (e.g. "CWE-327"). */
|
|
133
|
+
cwe?: string;
|
|
134
|
+
/** Suggested post-quantum remediation. When omitted, derived from {@link algorithm}. */
|
|
135
|
+
remediation?: string;
|
|
136
|
+
/** Canonical one-line human explanation; may be refined per-finding. */
|
|
137
|
+
message: string;
|
|
138
|
+
/** True when this rule's matched snippet IS sensitive key material. */
|
|
139
|
+
sensitive?: boolean;
|
|
140
|
+
/** Short description of what the rule detects (for catalog / MCP surfaces). */
|
|
141
|
+
description?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
104
144
|
/** A pluggable source detector. Detectors are pure and stateless. */
|
|
105
145
|
export interface Detector {
|
|
106
146
|
/** Unique id, used as the Finding.ruleId prefix space. */
|
|
@@ -118,6 +158,13 @@ export interface Detector {
|
|
|
118
158
|
* Defaults to `"js"` when omitted.
|
|
119
159
|
*/
|
|
120
160
|
language?: DetectorLanguage;
|
|
161
|
+
/**
|
|
162
|
+
* The rules this detector can emit, as declarative metadata. Together across
|
|
163
|
+
* all detectors these form the rule catalog ({@link DetectorRegistry.ruleCatalog}).
|
|
164
|
+
* Optional for backward compatibility with externally-defined detectors, but
|
|
165
|
+
* all built-in detectors declare it.
|
|
166
|
+
*/
|
|
167
|
+
rules?: RuleMeta[];
|
|
121
168
|
/** Whether this detector should run against the given file path. */
|
|
122
169
|
appliesTo(filePath: string): boolean;
|
|
123
170
|
/** Inspect a single file's contents and return zero or more findings. */
|
|
@@ -170,6 +217,13 @@ export interface ScanOptions {
|
|
|
170
217
|
* registry's detectors are used.
|
|
171
218
|
*/
|
|
172
219
|
detectors?: Detector[];
|
|
220
|
+
/**
|
|
221
|
+
* Rule ids to suppress. Any finding whose `ruleId` is listed here is dropped
|
|
222
|
+
* after detection. Serializable (a plain string array), so it is honoured on
|
|
223
|
+
* both the serial and the worker-thread (`scanParallel`) paths. See the rule
|
|
224
|
+
* catalog ({@link DetectorRegistry.ruleCatalog}) for the valid ids.
|
|
225
|
+
*/
|
|
226
|
+
disabledRules?: string[];
|
|
173
227
|
/** Optional progress callback. */
|
|
174
228
|
onFile?: (file: string) => void;
|
|
175
229
|
/**
|
package/src/version.ts
CHANGED