@npm-safe/core-dsh 1.0.5
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/LICENSE +204 -0
- package/dist/index.d.ts +513 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +711 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic.d.ts +47 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +161 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/gemini.d.ts +47 -0
- package/dist/llm/gemini.d.ts.map +1 -0
- package/dist/llm/gemini.js +165 -0
- package/dist/llm/gemini.js.map +1 -0
- package/dist/llm/llm-config.d.ts +97 -0
- package/dist/llm/llm-config.d.ts.map +1 -0
- package/dist/llm/llm-config.js +188 -0
- package/dist/llm/llm-config.js.map +1 -0
- package/dist/llm/parse.d.ts +95 -0
- package/dist/llm/parse.d.ts.map +1 -0
- package/dist/llm/parse.js +158 -0
- package/dist/llm/parse.js.map +1 -0
- package/dist/llm/provider.d.ts +122 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +206 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/registry/client.d.ts +164 -0
- package/dist/registry/client.d.ts.map +1 -0
- package/dist/registry/client.js +378 -0
- package/dist/registry/client.js.map +1 -0
- package/dist/registry/types.d.ts +226 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +32 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/registry/validator.d.ts +87 -0
- package/dist/registry/validator.d.ts.map +1 -0
- package/dist/registry/validator.js +214 -0
- package/dist/registry/validator.js.map +1 -0
- package/dist/scanner/ci-scan.d.ts +82 -0
- package/dist/scanner/ci-scan.d.ts.map +1 -0
- package/dist/scanner/ci-scan.js +130 -0
- package/dist/scanner/ci-scan.js.map +1 -0
- package/dist/scanner/rule-config.d.ts +61 -0
- package/dist/scanner/rule-config.d.ts.map +1 -0
- package/dist/scanner/rule-config.js +103 -0
- package/dist/scanner/rule-config.js.map +1 -0
- package/dist/scanner/rule-loader.d.ts +28 -0
- package/dist/scanner/rule-loader.d.ts.map +1 -0
- package/dist/scanner/rule-loader.js +67 -0
- package/dist/scanner/rule-loader.js.map +1 -0
- package/dist/scanner/static-rules.d.ts +88 -0
- package/dist/scanner/static-rules.d.ts.map +1 -0
- package/dist/scanner/static-rules.js +723 -0
- package/dist/scanner/static-rules.js.map +1 -0
- package/dist/scanner/types.d.ts +177 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +53 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scheduler/rate-limiter.d.ts +74 -0
- package/dist/scheduler/rate-limiter.d.ts.map +1 -0
- package/dist/scheduler/rate-limiter.js +182 -0
- package/dist/scheduler/rate-limiter.js.map +1 -0
- package/dist/scheduler/refresh-scheduler.d.ts +201 -0
- package/dist/scheduler/refresh-scheduler.d.ts.map +1 -0
- package/dist/scheduler/refresh-scheduler.js +295 -0
- package/dist/scheduler/refresh-scheduler.js.map +1 -0
- package/dist/store/cache-manager.d.ts +166 -0
- package/dist/store/cache-manager.d.ts.map +1 -0
- package/dist/store/cache-manager.js +356 -0
- package/dist/store/cache-manager.js.map +1 -0
- package/dist/store/database.d.ts +81 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +182 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/schema.d.ts +42 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +126 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/translator/provider.d.ts +152 -0
- package/dist/translator/provider.d.ts.map +1 -0
- package/dist/translator/provider.js +159 -0
- package/dist/translator/provider.js.map +1 -0
- package/dist/translator/types.d.ts +83 -0
- package/dist/translator/types.d.ts.map +1 -0
- package/dist/translator/types.js +58 -0
- package/dist/translator/types.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-rule configuration: enable/disable, severity overrides, and free-form
|
|
3
|
+
* options. Configuration is persisted as JSON (default
|
|
4
|
+
* `~/.npm-safe/rules.json`) and can be managed at runtime through the
|
|
5
|
+
* {@link RuleConfigManager}.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
/** Default location of the rules configuration file. */
|
|
11
|
+
export function getDefaultRulesConfigPath() {
|
|
12
|
+
return path.join(os.homedir(), '.npm-safe', 'rules.json');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Loads, mutates, and persists per-rule configuration. Thread-safe per
|
|
16
|
+
* instance; concurrent instances may race on the file, which is acceptable
|
|
17
|
+
* for a single-user desktop tool.
|
|
18
|
+
*/
|
|
19
|
+
export class RuleConfigManager {
|
|
20
|
+
filePath;
|
|
21
|
+
config;
|
|
22
|
+
/**
|
|
23
|
+
* @param filePath - Path to the JSON config file.
|
|
24
|
+
*/
|
|
25
|
+
constructor(filePath) {
|
|
26
|
+
this.filePath = filePath ?? getDefaultRulesConfigPath();
|
|
27
|
+
this.config = this.load();
|
|
28
|
+
}
|
|
29
|
+
/** Load (or initialize) the config file. */
|
|
30
|
+
load() {
|
|
31
|
+
try {
|
|
32
|
+
const raw = fs.readFileSync(this.filePath, 'utf8');
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
return { rules: parsed.rules ?? {} };
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return { rules: {} };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Persist the current configuration to disk. */
|
|
41
|
+
save() {
|
|
42
|
+
try {
|
|
43
|
+
fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
|
|
44
|
+
fs.writeFileSync(this.filePath, JSON.stringify(this.config, null, 2));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Best-effort persistence; in-memory config remains valid.
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Get the configuration for a single rule, or `undefined` if unset. */
|
|
51
|
+
getRule(ruleId) {
|
|
52
|
+
return this.config.rules[ruleId];
|
|
53
|
+
}
|
|
54
|
+
/** Whether a rule is enabled, honoring config overrides. */
|
|
55
|
+
isEnabled(ruleId, defaultEnabled) {
|
|
56
|
+
const rule = this.config.rules[ruleId];
|
|
57
|
+
return rule?.enabled ?? defaultEnabled;
|
|
58
|
+
}
|
|
59
|
+
/** Severity override for a rule, or `undefined` if not overridden. */
|
|
60
|
+
getSeverityOverride(ruleId) {
|
|
61
|
+
return this.config.rules[ruleId]?.severity;
|
|
62
|
+
}
|
|
63
|
+
/** Options for a rule, or `{}` if none are configured. */
|
|
64
|
+
getOptions(ruleId) {
|
|
65
|
+
return this.config.rules[ruleId]?.options ?? {};
|
|
66
|
+
}
|
|
67
|
+
/** Enable or disable a rule (persisted). */
|
|
68
|
+
setEnabled(ruleId, enabled) {
|
|
69
|
+
const rules = this.mutableRules();
|
|
70
|
+
const existing = rules[ruleId] ?? {};
|
|
71
|
+
rules[ruleId] = { ...existing, enabled };
|
|
72
|
+
this.save();
|
|
73
|
+
}
|
|
74
|
+
/** Override a rule's severity (persisted). `undefined` clears the override. */
|
|
75
|
+
setSeverity(ruleId, severity) {
|
|
76
|
+
const rules = this.mutableRules();
|
|
77
|
+
const existing = rules[ruleId] ?? {};
|
|
78
|
+
if (severity === undefined) {
|
|
79
|
+
const { severity: _removed, ...rest } = existing;
|
|
80
|
+
rules[ruleId] = rest;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
rules[ruleId] = { ...existing, severity };
|
|
84
|
+
}
|
|
85
|
+
this.save();
|
|
86
|
+
}
|
|
87
|
+
/** Set a rule's options (persisted). */
|
|
88
|
+
setOptions(ruleId, options) {
|
|
89
|
+
const rules = this.mutableRules();
|
|
90
|
+
const existing = rules[ruleId] ?? {};
|
|
91
|
+
rules[ruleId] = { ...existing, options };
|
|
92
|
+
this.save();
|
|
93
|
+
}
|
|
94
|
+
/** All configured rule ids. */
|
|
95
|
+
getConfiguredRuleIds() {
|
|
96
|
+
return Object.keys(this.config.rules);
|
|
97
|
+
}
|
|
98
|
+
/** Mutable view of the rules map for writing. */
|
|
99
|
+
mutableRules() {
|
|
100
|
+
return this.config.rules;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=rule-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-config.js","sourceRoot":"","sources":["../../src/scanner/rule-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin rule discovery: loads third-party {@link ScanRule}s from a directory
|
|
3
|
+
* of ES module files. Each `.mjs` (or `.js`) file may export a single rule,
|
|
4
|
+
* an array of rules, or a factory function returning either.
|
|
5
|
+
*/
|
|
6
|
+
import { ScanRule } from './types.js';
|
|
7
|
+
/** Default directory scanned for third-party rule plugins. */
|
|
8
|
+
export declare function getDefaultRulesDir(): string;
|
|
9
|
+
/** A rule exported by a plugin module, or a factory producing one. */
|
|
10
|
+
export type RuleModuleExport = ScanRule | ScanRule[] | (() => ScanRule | ScanRule[]);
|
|
11
|
+
/** Result of loading one plugin file. */
|
|
12
|
+
export interface LoadedRuleFile {
|
|
13
|
+
/** Absolute path of the loaded file. */
|
|
14
|
+
readonly filePath: string;
|
|
15
|
+
/** Rules exported by the file. */
|
|
16
|
+
readonly rules: ScanRule[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load all rule plugin files from a directory.
|
|
20
|
+
*
|
|
21
|
+
* Files are read in lexical order so rule order is deterministic. Invalid
|
|
22
|
+
* files are skipped — a broken plugin must not take down the whole scan.
|
|
23
|
+
*
|
|
24
|
+
* @param dir - Directory to scan for `*.mjs` / `*.js` rule files.
|
|
25
|
+
* @returns Per-file load results for every successfully loaded file.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadRulesFromDirectory(dir?: string): Promise<LoadedRuleFile[]>;
|
|
28
|
+
//# sourceMappingURL=rule-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-loader.d.ts","sourceRoot":"","sources":["../../src/scanner/rule-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,8DAA8D;AAC9D,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GACxB,QAAQ,GACR,QAAQ,EAAE,GACV,CAAC,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,CAAC;AAElC,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;CAC5B;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,EAAE,CAAC,CA8B3B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin rule discovery: loads third-party {@link ScanRule}s from a directory
|
|
3
|
+
* of ES module files. Each `.mjs` (or `.js`) file may export a single rule,
|
|
4
|
+
* an array of rules, or a factory function returning either.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { pathToFileURL } from 'node:url';
|
|
10
|
+
/** Default directory scanned for third-party rule plugins. */
|
|
11
|
+
export function getDefaultRulesDir() {
|
|
12
|
+
return path.join(os.homedir(), '.npm-safe', 'rules');
|
|
13
|
+
}
|
|
14
|
+
/** Normalize a module export into an array of rules. */
|
|
15
|
+
function toRules(exported) {
|
|
16
|
+
if (exported === undefined)
|
|
17
|
+
return [];
|
|
18
|
+
const resolved = typeof exported === 'function' ? exported() : exported;
|
|
19
|
+
if (Array.isArray(resolved)) {
|
|
20
|
+
return resolved.filter((r) => r !== null && typeof r === 'object' && 'id' in r);
|
|
21
|
+
}
|
|
22
|
+
if (resolved !== null && typeof resolved === 'object' && 'id' in resolved) {
|
|
23
|
+
return [resolved];
|
|
24
|
+
}
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load all rule plugin files from a directory.
|
|
29
|
+
*
|
|
30
|
+
* Files are read in lexical order so rule order is deterministic. Invalid
|
|
31
|
+
* files are skipped — a broken plugin must not take down the whole scan.
|
|
32
|
+
*
|
|
33
|
+
* @param dir - Directory to scan for `*.mjs` / `*.js` rule files.
|
|
34
|
+
* @returns Per-file load results for every successfully loaded file.
|
|
35
|
+
*/
|
|
36
|
+
export async function loadRulesFromDirectory(dir) {
|
|
37
|
+
const target = dir ?? getDefaultRulesDir();
|
|
38
|
+
let entries;
|
|
39
|
+
try {
|
|
40
|
+
entries = fs
|
|
41
|
+
.readdirSync(target)
|
|
42
|
+
.filter((f) => f.endsWith('.mjs') || f.endsWith('.js'))
|
|
43
|
+
.sort();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return []; // Directory does not exist — nothing to load.
|
|
47
|
+
}
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const filePath = path.join(target, entry);
|
|
51
|
+
try {
|
|
52
|
+
const mod = (await import(
|
|
53
|
+
/* webpackIgnore: true */ pathToFileURL(filePath).href));
|
|
54
|
+
// Prefer a named `rule` / `rules` export, fall back to `default`.
|
|
55
|
+
const candidate = mod.rule ?? mod.rules ?? mod.default;
|
|
56
|
+
const rules = toRules(candidate);
|
|
57
|
+
if (rules.length > 0) {
|
|
58
|
+
results.push({ filePath, rules });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Skip unparseable plugin files silently.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=rule-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-loader.js","sourceRoot":"","sources":["../../src/scanner/rule-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,8DAA8D;AAC9D,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC;AAgBD,wDAAwD;AACxD,SAAS,OAAO,CAAC,QAAsC;IACrD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,IAAI,IAAI,CAAC,CACvE,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC1E,OAAO,CAAC,QAAoB,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAY;IAEZ,MAAM,MAAM,GAAG,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC3C,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE;aACT,WAAW,CAAC,MAAM,CAAC;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aACtD,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,8CAA8C;IAC3D,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM;YACvB,yBAAyB,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CACvD,CAA4B,CAAC;YAC9B,kEAAkE;YAClE,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC;YACvD,MAAM,KAAK,GAAG,OAAO,CAAC,SAA6B,CAAC,CAAC;YACrD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static analysis rule engine for npm package security scanning.
|
|
3
|
+
*
|
|
4
|
+
* Pure regex/string analysis — no network calls, no LLM. The engine registers
|
|
5
|
+
* a set of {@link ScanRule} implementations and aggregates their findings into
|
|
6
|
+
* a {@link StaticScanReport} with a numeric score and overall security level.
|
|
7
|
+
*/
|
|
8
|
+
import { FindingCategory, ScanRule, Severity, StaticScanReport } from './types.js';
|
|
9
|
+
import { RuleConfigManager } from './rule-config.js';
|
|
10
|
+
/** All built-in static analysis rules, in registration order. */
|
|
11
|
+
export declare const BUILTIN_RULES: readonly ScanRule[];
|
|
12
|
+
/** Ids of the built-in rules, used to label rule provenance. */
|
|
13
|
+
export declare const BUILTIN_RULE_IDS: ReadonlySet<string>;
|
|
14
|
+
/** A rule together with its effective (post-config) status. */
|
|
15
|
+
export interface RuleDescriptor {
|
|
16
|
+
/** Stable unique identifier for the rule. */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
/** Human-readable name of the rule. */
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** Description of what the rule detects. */
|
|
21
|
+
readonly description: string;
|
|
22
|
+
/** Effective severity (after config overrides). */
|
|
23
|
+
readonly severity: Severity;
|
|
24
|
+
/** Category assigned to findings produced by this rule. */
|
|
25
|
+
readonly category: FindingCategory;
|
|
26
|
+
/** Whether the rule is enabled (after config overrides). */
|
|
27
|
+
readonly enabled: boolean;
|
|
28
|
+
/** Whether the rule ships with the engine or was loaded from a plugin. */
|
|
29
|
+
readonly source: 'builtin' | 'plugin';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Static analysis engine that runs a set of {@link ScanRule}s against a
|
|
33
|
+
* package's README and package.json and aggregates the findings into a
|
|
34
|
+
* {@link StaticScanReport}.
|
|
35
|
+
*/
|
|
36
|
+
export declare class StaticAnalyzer {
|
|
37
|
+
private readonly rules;
|
|
38
|
+
private readonly config;
|
|
39
|
+
/**
|
|
40
|
+
* @param rules - Optional custom rule set. Defaults to all built-in rules.
|
|
41
|
+
* @param config - Optional per-rule configuration manager whose overrides
|
|
42
|
+
* (enabled / severity) are applied at analysis time.
|
|
43
|
+
*/
|
|
44
|
+
constructor(rules?: ScanRule[], config?: RuleConfigManager);
|
|
45
|
+
/**
|
|
46
|
+
* Register a rule at runtime. A rule with the same id replaces the existing
|
|
47
|
+
* one (keeping its position in the registration order).
|
|
48
|
+
*
|
|
49
|
+
* @param rule - The rule to register.
|
|
50
|
+
*/
|
|
51
|
+
registerRule(rule: ScanRule): void;
|
|
52
|
+
/**
|
|
53
|
+
* Remove a rule by id.
|
|
54
|
+
*
|
|
55
|
+
* @param ruleId - Id of the rule to remove.
|
|
56
|
+
* @returns `true` if a rule was removed, `false` if no such rule exists.
|
|
57
|
+
*/
|
|
58
|
+
unregisterRule(ruleId: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Describe every registered rule with its effective status.
|
|
61
|
+
*
|
|
62
|
+
* @returns Rule descriptors in registration order.
|
|
63
|
+
*/
|
|
64
|
+
listRules(): RuleDescriptor[];
|
|
65
|
+
/**
|
|
66
|
+
* Run all enabled rules against the given README and package.json, aggregate
|
|
67
|
+
* the findings, and compute a numeric score plus overall security level.
|
|
68
|
+
*
|
|
69
|
+
* Scoring starts at 100 and subtracts a per-finding weight based on severity:
|
|
70
|
+
* critical=-25, high=-15, medium=-8, low=-3. The score is clamped to [0, 100].
|
|
71
|
+
*
|
|
72
|
+
* Overall level: score >= 80 → Safe, >= 50 → Suspicious, >= 20 → Dangerous,
|
|
73
|
+
* else Unknown.
|
|
74
|
+
*
|
|
75
|
+
* @param readme - README content as a string (may be empty).
|
|
76
|
+
* @param packageJson - Parsed package.json, if available.
|
|
77
|
+
* @returns The aggregated static scan report.
|
|
78
|
+
*/
|
|
79
|
+
analyze(readme: string, packageJson?: Record<string, unknown>): StaticScanReport;
|
|
80
|
+
/**
|
|
81
|
+
* Map a numeric score to a {@link SecurityLevel}.
|
|
82
|
+
*
|
|
83
|
+
* @param score - Clamped score in [0, 100].
|
|
84
|
+
* @returns The corresponding security level.
|
|
85
|
+
*/
|
|
86
|
+
private levelFromScore;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=static-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-rules.d.ts","sourceRoot":"","sources":["../../src/scanner/static-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EAEf,QAAQ,EAER,QAAQ,EACR,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAynBrD,iEAAiE;AACjE,eAAO,MAAM,aAAa,EAAE,SAAS,QAAQ,EAW5C,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAEhD,CAAC;AAEF,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;CACvC;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD;;;;OAIG;gBACS,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,iBAAiB;IAO1D;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAIlC;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;OAIG;IACH,SAAS,IAAI,cAAc,EAAE;IAkB7B;;;;;;;;;;;;;OAaG;IACH,OAAO,CACL,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACpC,gBAAgB;IAuCnB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAMvB"}
|