@obfuscan/core 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/LICENSE +201 -0
- package/README.md +224 -0
- package/dist/allowlist.d.ts +25 -0
- package/dist/allowlist.d.ts.map +1 -0
- package/dist/allowlist.js +138 -0
- package/dist/allowlist.js.map +1 -0
- package/dist/detectors/bidi-control.d.ts +14 -0
- package/dist/detectors/bidi-control.d.ts.map +1 -0
- package/dist/detectors/bidi-control.js +67 -0
- package/dist/detectors/bidi-control.js.map +1 -0
- package/dist/detectors/cargo-build-rs-network.d.ts +12 -0
- package/dist/detectors/cargo-build-rs-network.d.ts.map +1 -0
- package/dist/detectors/cargo-build-rs-network.js +54 -0
- package/dist/detectors/cargo-build-rs-network.js.map +1 -0
- package/dist/detectors/decode-then-exec.d.ts +20 -0
- package/dist/detectors/decode-then-exec.d.ts.map +1 -0
- package/dist/detectors/decode-then-exec.js +189 -0
- package/dist/detectors/decode-then-exec.js.map +1 -0
- package/dist/detectors/deserializer-untrusted.d.ts +15 -0
- package/dist/detectors/deserializer-untrusted.d.ts.map +1 -0
- package/dist/detectors/deserializer-untrusted.js +99 -0
- package/dist/detectors/deserializer-untrusted.js.map +1 -0
- package/dist/detectors/dockerfile-curl-pipe-shell.d.ts +10 -0
- package/dist/detectors/dockerfile-curl-pipe-shell.d.ts.map +1 -0
- package/dist/detectors/dockerfile-curl-pipe-shell.js +42 -0
- package/dist/detectors/dockerfile-curl-pipe-shell.js.map +1 -0
- package/dist/detectors/dynamic-exec-non-literal.d.ts +17 -0
- package/dist/detectors/dynamic-exec-non-literal.d.ts.map +1 -0
- package/dist/detectors/dynamic-exec-non-literal.js +104 -0
- package/dist/detectors/dynamic-exec-non-literal.js.map +1 -0
- package/dist/detectors/encoded-array-fingerprint.d.ts +11 -0
- package/dist/detectors/encoded-array-fingerprint.d.ts.map +1 -0
- package/dist/detectors/encoded-array-fingerprint.js +60 -0
- package/dist/detectors/encoded-array-fingerprint.js.map +1 -0
- package/dist/detectors/gha-curl-pipe-shell.d.ts +11 -0
- package/dist/detectors/gha-curl-pipe-shell.d.ts.map +1 -0
- package/dist/detectors/gha-curl-pipe-shell.js +42 -0
- package/dist/detectors/gha-curl-pipe-shell.js.map +1 -0
- package/dist/detectors/high-entropy-literal.d.ts +19 -0
- package/dist/detectors/high-entropy-literal.d.ts.map +1 -0
- package/dist/detectors/high-entropy-literal.js +90 -0
- package/dist/detectors/high-entropy-literal.js.map +1 -0
- package/dist/detectors/homoglyph-identifier.d.ts +16 -0
- package/dist/detectors/homoglyph-identifier.d.ts.map +1 -0
- package/dist/detectors/homoglyph-identifier.js +76 -0
- package/dist/detectors/homoglyph-identifier.js.map +1 -0
- package/dist/detectors/index.d.ts +31 -0
- package/dist/detectors/index.d.ts.map +1 -0
- package/dist/detectors/index.js +60 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/library-load-non-literal.d.ts +10 -0
- package/dist/detectors/library-load-non-literal.d.ts.map +1 -0
- package/dist/detectors/library-load-non-literal.js +72 -0
- package/dist/detectors/library-load-non-literal.js.map +1 -0
- package/dist/detectors/long-line.d.ts +12 -0
- package/dist/detectors/long-line.d.ts.map +1 -0
- package/dist/detectors/long-line.js +53 -0
- package/dist/detectors/long-line.js.map +1 -0
- package/dist/detectors/manifest-install-script.d.ts +54 -0
- package/dist/detectors/manifest-install-script.d.ts.map +1 -0
- package/dist/detectors/manifest-install-script.js +272 -0
- package/dist/detectors/manifest-install-script.js.map +1 -0
- package/dist/detectors/network-then-exec.d.ts +17 -0
- package/dist/detectors/network-then-exec.d.ts.map +1 -0
- package/dist/detectors/network-then-exec.js +140 -0
- package/dist/detectors/network-then-exec.js.map +1 -0
- package/dist/detectors/perl-makefile-side-effect.d.ts +17 -0
- package/dist/detectors/perl-makefile-side-effect.d.ts.map +1 -0
- package/dist/detectors/perl-makefile-side-effect.js +72 -0
- package/dist/detectors/perl-makefile-side-effect.js.map +1 -0
- package/dist/detectors/python-setup-side-effect.d.ts +10 -0
- package/dist/detectors/python-setup-side-effect.d.ts.map +1 -0
- package/dist/detectors/python-setup-side-effect.js +87 -0
- package/dist/detectors/python-setup-side-effect.js.map +1 -0
- package/dist/detectors/shell-untrusted-input.d.ts +10 -0
- package/dist/detectors/shell-untrusted-input.d.ts.map +1 -0
- package/dist/detectors/shell-untrusted-input.js +76 -0
- package/dist/detectors/shell-untrusted-input.js.map +1 -0
- package/dist/detectors/string-array-decoder.d.ts +15 -0
- package/dist/detectors/string-array-decoder.d.ts.map +1 -0
- package/dist/detectors/string-array-decoder.js +70 -0
- package/dist/detectors/string-array-decoder.js.map +1 -0
- package/dist/detectors/suspicious-io-cluster.d.ts +11 -0
- package/dist/detectors/suspicious-io-cluster.d.ts.map +1 -0
- package/dist/detectors/suspicious-io-cluster.js +86 -0
- package/dist/detectors/suspicious-io-cluster.js.map +1 -0
- package/dist/diff.d.ts +23 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +144 -0
- package/dist/diff.js.map +1 -0
- package/dist/directives.d.ts +33 -0
- package/dist/directives.d.ts.map +1 -0
- package/dist/directives.js +60 -0
- package/dist/directives.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +16 -0
- package/dist/errors.js.map +1 -0
- package/dist/grammar/query.d.ts +44 -0
- package/dist/grammar/query.d.ts.map +1 -0
- package/dist/grammar/query.js +24 -0
- package/dist/grammar/query.js.map +1 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/patterns.d.ts +48 -0
- package/dist/internal/patterns.d.ts.map +1 -0
- package/dist/internal/patterns.js +95 -0
- package/dist/internal/patterns.js.map +1 -0
- package/dist/internal/text.d.ts +14 -0
- package/dist/internal/text.d.ts.map +1 -0
- package/dist/internal/text.js +20 -0
- package/dist/internal/text.js.map +1 -0
- package/dist/rules.d.ts +25 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +195 -0
- package/dist/rules.js.map +1 -0
- package/dist/scan.d.ts +26 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +287 -0
- package/dist/scan.js.map +1 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +50 -0
- package/dist/version.js.map +1 -0
- package/package.json +74 -0
package/dist/scan.js
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scan() — the orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline:
|
|
5
|
+
* 1. Validate ScanInput (exactly one of diff/paths/dir).
|
|
6
|
+
* 2. Resolve target file list:
|
|
7
|
+
* diff → parseDiffToFiles → addedRanges per file
|
|
8
|
+
* paths → use as-is, no addedRanges
|
|
9
|
+
* dir → host enumerates; we just respect the resolver's nulls
|
|
10
|
+
* 3. For each file (concurrency-limited):
|
|
11
|
+
* a. Resolve content via fileResolver (catch errors; log+skip)
|
|
12
|
+
* b. Build FileContext (path, source, languageId, config, addedRanges)
|
|
13
|
+
* c. For each enabled detector where applies(ctx) is true:
|
|
14
|
+
* - run() with per-file timeout + try/catch
|
|
15
|
+
* - collect findings
|
|
16
|
+
* d. Apply diff-range filter (drop findings outside addedRanges)
|
|
17
|
+
* e. Apply in-source disable directives
|
|
18
|
+
* f. Apply allowlist (paths + snippets)
|
|
19
|
+
* g. Apply minSeverity
|
|
20
|
+
* h. Truncate snippets to 200 chars defensively
|
|
21
|
+
* 4. Sort findings by (severity desc, score desc, file asc, line asc).
|
|
22
|
+
* 5. Return ScanResult.
|
|
23
|
+
*/
|
|
24
|
+
import { parseDiffToFiles, lineInRanges } from "./diff.js";
|
|
25
|
+
import { extractDisableDirectives, isSuppressedByDirectives } from "./directives.js";
|
|
26
|
+
import { matchesAllowlist } from "./allowlist.js";
|
|
27
|
+
import { defaultRuleSet } from "./rules.js";
|
|
28
|
+
import { defaultDetectors } from "./detectors/index.js";
|
|
29
|
+
import { InvalidScanInputError } from "./errors.js";
|
|
30
|
+
import { ENGINE_VERSION } from "./version.js";
|
|
31
|
+
const SEVERITY_RANK = { info: 0, warn: 1, block: 2 };
|
|
32
|
+
const DEFAULT_FILE_TIMEOUT_MS = 5000;
|
|
33
|
+
const SNIPPET_CAP = 200;
|
|
34
|
+
export async function scan(input, options) {
|
|
35
|
+
validateInput(input);
|
|
36
|
+
const t0 = Date.now();
|
|
37
|
+
const logger = options.logger ?? consoleLogger();
|
|
38
|
+
const ruleSet = options.rules ?? (await defaultRuleSet());
|
|
39
|
+
const detectors = (options.detectors ?? defaultDetectors()).filter(d => !(options.disabledDetectors ?? []).includes(d.id));
|
|
40
|
+
// Build the file work list.
|
|
41
|
+
const targets = await prepareTargets(input);
|
|
42
|
+
const results = [];
|
|
43
|
+
const findings = [];
|
|
44
|
+
const failedDetectors = new Set();
|
|
45
|
+
const minRank = SEVERITY_RANK[options.minSeverity ?? "info"];
|
|
46
|
+
const fileTimeout = options.fileTimeoutMs ?? DEFAULT_FILE_TIMEOUT_MS;
|
|
47
|
+
// Concurrency limiter
|
|
48
|
+
const concurrency = Math.max(1, options.concurrency ?? Math.max(2, defaultConcurrency()));
|
|
49
|
+
let filesDone = 0;
|
|
50
|
+
const total = targets.length;
|
|
51
|
+
const reportProgress = (currentFile) => {
|
|
52
|
+
if (!options.onProgress)
|
|
53
|
+
return;
|
|
54
|
+
const progress = currentFile
|
|
55
|
+
? { filesTotal: total, filesDone, currentFile }
|
|
56
|
+
: { filesTotal: total, filesDone };
|
|
57
|
+
options.onProgress(progress);
|
|
58
|
+
};
|
|
59
|
+
await runWithConcurrency(targets, concurrency, async (target) => {
|
|
60
|
+
reportProgress(target.path);
|
|
61
|
+
let source = null;
|
|
62
|
+
try {
|
|
63
|
+
source = await options.fileResolver(target.path);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
logger.warn(`fileResolver threw for ${target.path}`, e);
|
|
67
|
+
}
|
|
68
|
+
let languageId = null;
|
|
69
|
+
if (source !== null) {
|
|
70
|
+
languageId = ruleSet.detectLanguage(target.path);
|
|
71
|
+
}
|
|
72
|
+
results.push({ path: target.path, languageId });
|
|
73
|
+
if (source === null) {
|
|
74
|
+
filesDone++;
|
|
75
|
+
reportProgress();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const config = languageId ? ruleSet.configFor(languageId) : null;
|
|
79
|
+
let cachedGrammar = null;
|
|
80
|
+
let cachedTree = null;
|
|
81
|
+
let treeResolved = false;
|
|
82
|
+
const ctx = {
|
|
83
|
+
path: target.path,
|
|
84
|
+
languageId,
|
|
85
|
+
config,
|
|
86
|
+
source,
|
|
87
|
+
addedRanges: target.addedRanges,
|
|
88
|
+
grammar: null, // populated lazily if a detector accesses it
|
|
89
|
+
tree: async () => {
|
|
90
|
+
if (treeResolved)
|
|
91
|
+
return cachedTree;
|
|
92
|
+
treeResolved = true;
|
|
93
|
+
if (!languageId)
|
|
94
|
+
return null;
|
|
95
|
+
try {
|
|
96
|
+
cachedGrammar = await ruleSet.loadGrammar(languageId);
|
|
97
|
+
// If the host-supplied grammar exposes a parser, use it. The default
|
|
98
|
+
// RuleSet returns a stub handle with no `parse` — the bundled
|
|
99
|
+
// detectors are regex-driven and never call tree(). See
|
|
100
|
+
// `docs/tree-sitter.md` for the host-override contract.
|
|
101
|
+
if (cachedGrammar && typeof cachedGrammar.parse === "function") {
|
|
102
|
+
cachedTree = await cachedGrammar.parse(source);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
cachedTree = null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
cachedTree = null;
|
|
110
|
+
}
|
|
111
|
+
return cachedTree;
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
// Bind grammar lazily on first use; default detectors don't read this.
|
|
115
|
+
Object.defineProperty(ctx, "grammar", {
|
|
116
|
+
get() {
|
|
117
|
+
return cachedGrammar;
|
|
118
|
+
},
|
|
119
|
+
enumerable: true,
|
|
120
|
+
});
|
|
121
|
+
const directives = extractDisableDirectives(source);
|
|
122
|
+
const fileFindings = [];
|
|
123
|
+
for (const det of detectors) {
|
|
124
|
+
let applies = false;
|
|
125
|
+
try {
|
|
126
|
+
applies = det.applies(ctx);
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
logger.warn(`detector ${det.id} threw in applies()`, e);
|
|
130
|
+
failedDetectors.add(det.id);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (!applies)
|
|
134
|
+
continue;
|
|
135
|
+
let detFindings = [];
|
|
136
|
+
try {
|
|
137
|
+
const out = await runWithTimeout(det, ctx, fileTimeout);
|
|
138
|
+
detFindings = out;
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
logger.warn(`detector ${det.id} failed on ${target.path}`, e);
|
|
142
|
+
failedDetectors.add(det.id);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
for (const f of detFindings) {
|
|
146
|
+
const normalized = normalizeFinding(f);
|
|
147
|
+
if (target.diffMode && !lineInRanges(normalized.line, target.addedRanges)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (isSuppressedByDirectives(normalized.line, normalized.ruleId, directives)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (options.allowlist && matchesAllowlist(normalized, options.allowlist, target.path)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (SEVERITY_RANK[normalized.severity] < minRank)
|
|
157
|
+
continue;
|
|
158
|
+
fileFindings.push(normalized);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (options.symbolResolver) {
|
|
162
|
+
// Best-effort enclosing symbol enrichment.
|
|
163
|
+
for (let i = 0; i < fileFindings.length; i++) {
|
|
164
|
+
const f = fileFindings[i];
|
|
165
|
+
try {
|
|
166
|
+
const sym = await options.symbolResolver(target.path, f.line);
|
|
167
|
+
if (sym)
|
|
168
|
+
fileFindings[i] = { ...f, enclosingSymbol: sym };
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// ignore
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
findings.push(...fileFindings);
|
|
176
|
+
filesDone++;
|
|
177
|
+
reportProgress();
|
|
178
|
+
});
|
|
179
|
+
// Final progress emit (ensures filesDone === total even when no resolver work).
|
|
180
|
+
if (options.onProgress && total === 0) {
|
|
181
|
+
options.onProgress({ filesTotal: 0, filesDone: 0 });
|
|
182
|
+
}
|
|
183
|
+
findings.sort(compareFindings);
|
|
184
|
+
return {
|
|
185
|
+
findings: Object.freeze(findings.slice()),
|
|
186
|
+
files: Object.freeze(results.slice()),
|
|
187
|
+
durationMs: Math.max(0, Date.now() - t0),
|
|
188
|
+
failedDetectors: Object.freeze([...failedDetectors].sort()),
|
|
189
|
+
rulesVersion: ruleSet.version(),
|
|
190
|
+
engineVersion: ENGINE_VERSION,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
194
|
+
function validateInput(input) {
|
|
195
|
+
const set = [
|
|
196
|
+
input.diff !== undefined,
|
|
197
|
+
input.paths !== undefined,
|
|
198
|
+
input.dir !== undefined,
|
|
199
|
+
].filter(Boolean).length;
|
|
200
|
+
if (set !== 1) {
|
|
201
|
+
throw new InvalidScanInputError(`ScanInput must set exactly one of {diff, paths, dir}; got ${set}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async function prepareTargets(input) {
|
|
205
|
+
if (input.diff !== undefined) {
|
|
206
|
+
const files = parseDiffToFiles(input.diff);
|
|
207
|
+
return files
|
|
208
|
+
.filter(f => f.status !== "deleted")
|
|
209
|
+
.map(f => ({ path: f.path, addedRanges: f.addedRanges, diffMode: true }));
|
|
210
|
+
}
|
|
211
|
+
if (input.paths !== undefined) {
|
|
212
|
+
return input.paths.map(p => ({ path: p, addedRanges: [], diffMode: false }));
|
|
213
|
+
}
|
|
214
|
+
// dir: the host is responsible for enumerating via fileResolver. We have
|
|
215
|
+
// no portable directory walker (the engine is host-agnostic), so dir-mode
|
|
216
|
+
// returns an empty target list — same shape the contract test expects.
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
async function runWithConcurrency(items, limit, worker) {
|
|
220
|
+
if (items.length === 0)
|
|
221
|
+
return;
|
|
222
|
+
let cursor = 0;
|
|
223
|
+
const runners = [];
|
|
224
|
+
const runOne = async () => {
|
|
225
|
+
while (cursor < items.length) {
|
|
226
|
+
const idx = cursor++;
|
|
227
|
+
const item = items[idx];
|
|
228
|
+
if (item === undefined)
|
|
229
|
+
continue;
|
|
230
|
+
await worker(item);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
for (let i = 0; i < Math.min(limit, items.length); i++) {
|
|
234
|
+
runners.push(runOne());
|
|
235
|
+
}
|
|
236
|
+
await Promise.all(runners);
|
|
237
|
+
}
|
|
238
|
+
async function runWithTimeout(det, ctx, timeoutMs) {
|
|
239
|
+
const out = det.run(ctx);
|
|
240
|
+
if (Array.isArray(out))
|
|
241
|
+
return out;
|
|
242
|
+
return new Promise((resolve, reject) => {
|
|
243
|
+
const timer = setTimeout(() => reject(new Error(`detector ${det.id} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
244
|
+
Promise.resolve(out).then((v) => { clearTimeout(timer); resolve(v); }, (e) => { clearTimeout(timer); reject(e); });
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function normalizeFinding(f) {
|
|
248
|
+
// Defensive truncation.
|
|
249
|
+
let snippet = f.snippet;
|
|
250
|
+
if (snippet.length > SNIPPET_CAP) {
|
|
251
|
+
snippet = snippet.slice(0, SNIPPET_CAP - 3) + "...";
|
|
252
|
+
}
|
|
253
|
+
return snippet === f.snippet ? f : { ...f, snippet };
|
|
254
|
+
}
|
|
255
|
+
function compareFindings(a, b) {
|
|
256
|
+
const ra = SEVERITY_RANK[a.severity];
|
|
257
|
+
const rb = SEVERITY_RANK[b.severity];
|
|
258
|
+
if (ra !== rb)
|
|
259
|
+
return rb - ra; // higher severity first
|
|
260
|
+
if (a.score !== b.score)
|
|
261
|
+
return b.score - a.score;
|
|
262
|
+
if (a.file !== b.file)
|
|
263
|
+
return a.file < b.file ? -1 : 1;
|
|
264
|
+
return a.line - b.line;
|
|
265
|
+
}
|
|
266
|
+
function defaultConcurrency() {
|
|
267
|
+
// Avoid `os.cpus()` import when the env is constrained.
|
|
268
|
+
try {
|
|
269
|
+
// dynamic require so this still works in non-Node runtimes
|
|
270
|
+
const n = globalThis.navigator?.hardwareConcurrency;
|
|
271
|
+
if (typeof n === "number" && n > 0)
|
|
272
|
+
return n;
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// ignore
|
|
276
|
+
}
|
|
277
|
+
return 4;
|
|
278
|
+
}
|
|
279
|
+
function consoleLogger() {
|
|
280
|
+
return {
|
|
281
|
+
debug: () => { },
|
|
282
|
+
info: () => { },
|
|
283
|
+
warn: (msg, meta) => console.warn(msg, meta ?? ""),
|
|
284
|
+
error: (msg, meta) => console.error(msg, meta ?? ""),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=scan.js.map
|
package/dist/scan.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public type surface of @obfuscan/core.
|
|
3
|
+
*
|
|
4
|
+
* Anything exported from this file is part of the SemVer-stable API.
|
|
5
|
+
* Internal types live in src/internal/* and may change without notice.
|
|
6
|
+
*/
|
|
7
|
+
export type Severity = "info" | "warn" | "block";
|
|
8
|
+
export interface Finding {
|
|
9
|
+
/** Stable rule id, e.g. "obf.decode-then-exec.python". */
|
|
10
|
+
ruleId: string;
|
|
11
|
+
/** Aggregated severity after scoring. */
|
|
12
|
+
severity: Severity;
|
|
13
|
+
/** 0..10. Aggregator clamps to 10. */
|
|
14
|
+
score: number;
|
|
15
|
+
/** Workspace-relative path. */
|
|
16
|
+
file: string;
|
|
17
|
+
/** 1-based line number where the finding starts. */
|
|
18
|
+
line: number;
|
|
19
|
+
/** 1-based line number where the finding ends. Optional; defaults to `line`. */
|
|
20
|
+
endLine?: number;
|
|
21
|
+
/** Up to 200 chars of the matched source. Truncated with ellipsis if longer. */
|
|
22
|
+
snippet: string;
|
|
23
|
+
/** Human-readable explanation suitable for direct display in a code review UI. */
|
|
24
|
+
reason: string;
|
|
25
|
+
/** Optional fully-qualified function name(s) the finding lives inside. Populated when the host provides a symbol resolver. */
|
|
26
|
+
enclosingSymbol?: string;
|
|
27
|
+
/** Detector-specific structured data. Stable per ruleId. */
|
|
28
|
+
evidence?: Readonly<Record<string, unknown>>;
|
|
29
|
+
}
|
|
30
|
+
/** Per-language config loaded from rules/languages/*.json. */
|
|
31
|
+
export interface LanguageConfig {
|
|
32
|
+
readonly id: string;
|
|
33
|
+
readonly aliases?: readonly string[];
|
|
34
|
+
readonly extensions: readonly string[];
|
|
35
|
+
readonly filenames?: readonly string[];
|
|
36
|
+
readonly dynamic_exec_sinks: readonly string[];
|
|
37
|
+
readonly decoders: readonly string[];
|
|
38
|
+
readonly deserializers?: readonly string[];
|
|
39
|
+
readonly network_io?: readonly string[];
|
|
40
|
+
readonly secrets_io?: readonly string[];
|
|
41
|
+
readonly shell_exec?: readonly string[];
|
|
42
|
+
readonly library_load?: readonly string[];
|
|
43
|
+
readonly obfuscator_id_patterns?: readonly string[];
|
|
44
|
+
readonly min_mean_identifier_length?: number;
|
|
45
|
+
readonly obfuscator_id_min_ratio?: number;
|
|
46
|
+
readonly string_concat_operators?: readonly string[];
|
|
47
|
+
readonly language_specific_detectors?: readonly string[];
|
|
48
|
+
readonly manifests?: readonly string[];
|
|
49
|
+
readonly notes?: string;
|
|
50
|
+
}
|
|
51
|
+
/** Provider for language configs and tree-sitter grammars/queries. */
|
|
52
|
+
export interface RuleSet {
|
|
53
|
+
/** Language ids this ruleset supports. */
|
|
54
|
+
languages(): readonly string[];
|
|
55
|
+
/** Look up a config by language id. Returns null if unsupported. */
|
|
56
|
+
configFor(languageId: string): LanguageConfig | null;
|
|
57
|
+
/** Map a file path to a language id, or null if unknown. */
|
|
58
|
+
detectLanguage(path: string): string | null;
|
|
59
|
+
/** Load the parser+queries for a language. Implementations may cache. */
|
|
60
|
+
loadGrammar(languageId: string): Promise<GrammarHandle>;
|
|
61
|
+
/** Calver version of the rule pack (e.g. "2026.04.0"). */
|
|
62
|
+
version(): string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Opaque handle to a loaded tree-sitter parser and (optionally) its compiled
|
|
66
|
+
* queries. The default `RuleSet` returns a stub handle with no `parse` and no
|
|
67
|
+
* `_internal` because the bundled detectors are regex-driven — see
|
|
68
|
+
* `docs/tree-sitter.md` for how hosts plug in a real parser.
|
|
69
|
+
*/
|
|
70
|
+
export interface GrammarHandle {
|
|
71
|
+
/** The tree-sitter grammar id (e.g. "javascript", "python"). */
|
|
72
|
+
readonly id: string;
|
|
73
|
+
/**
|
|
74
|
+
* Internal field reserved for the engine. Hosts that wrap a real
|
|
75
|
+
* tree-sitter `Language` typically stash it here.
|
|
76
|
+
*/
|
|
77
|
+
readonly _internal: unknown;
|
|
78
|
+
/**
|
|
79
|
+
* Optional source -> tree parser. When present, `FileContext.tree()` calls
|
|
80
|
+
* this on first access and caches the result. The returned value is
|
|
81
|
+
* `unknown` to keep the engine parser-agnostic; hosts and host-supplied
|
|
82
|
+
* detectors agree on its shape (typically a `Tree` from `web-tree-sitter`
|
|
83
|
+
* or `tree-sitter`).
|
|
84
|
+
*/
|
|
85
|
+
parse?: (source: string) => unknown | Promise<unknown>;
|
|
86
|
+
}
|
|
87
|
+
/** Path-pattern-based suppression. Matched against POSIX-style relative paths. */
|
|
88
|
+
export interface PathAllowlistEntry {
|
|
89
|
+
/** Glob in minimatch syntax. */
|
|
90
|
+
pattern: string;
|
|
91
|
+
/** Severity ceiling: findings below this severity are suppressed entirely on matching files. */
|
|
92
|
+
maxSeverity?: Severity;
|
|
93
|
+
/** Optional rule id filter; if omitted, applies to all rules. */
|
|
94
|
+
ruleId?: string;
|
|
95
|
+
/** Optional reviewer-visible reason. */
|
|
96
|
+
reason?: string;
|
|
97
|
+
}
|
|
98
|
+
/** Per-finding suppression keyed by `(ruleId, sha256(snippet))`. */
|
|
99
|
+
export interface SnippetAllowlistEntry {
|
|
100
|
+
ruleId: string;
|
|
101
|
+
/** sha256 hex of the matched snippet. */
|
|
102
|
+
snippetHash: string;
|
|
103
|
+
reason?: string;
|
|
104
|
+
/** ISO-8601 timestamp set by the CLI when added. */
|
|
105
|
+
added?: string;
|
|
106
|
+
/** Optional GitHub login or email of the user who added it. */
|
|
107
|
+
addedBy?: string;
|
|
108
|
+
}
|
|
109
|
+
export interface Allowlist {
|
|
110
|
+
paths?: readonly PathAllowlistEntry[];
|
|
111
|
+
snippets?: readonly SnippetAllowlistEntry[];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Reads file content for the scanner.
|
|
115
|
+
*
|
|
116
|
+
* `path` is workspace-relative. The resolver should return the **post-image**
|
|
117
|
+
* (after the diff is applied) when scanning a diff. For a directory scan, it
|
|
118
|
+
* returns the current file content.
|
|
119
|
+
*
|
|
120
|
+
* Return `null` for files that don't exist or that the host wants to skip
|
|
121
|
+
* silently (e.g. binary files filtered upstream).
|
|
122
|
+
*/
|
|
123
|
+
export type FileResolver = (path: string) => Promise<string | null>;
|
|
124
|
+
/** Optional symbol resolver for `Finding.enclosingSymbol`. */
|
|
125
|
+
export type SymbolResolver = (path: string, line: number) => Promise<string | null>;
|
|
126
|
+
/** A source of files to scan. Exactly one of `diff`, `paths`, or `dir` must be set. */
|
|
127
|
+
export interface ScanInput {
|
|
128
|
+
/** Unified diff content. The scanner extracts changed files and added line ranges. */
|
|
129
|
+
diff?: string;
|
|
130
|
+
/** Explicit file list (workspace-relative paths). The whole file is scanned. */
|
|
131
|
+
paths?: readonly string[];
|
|
132
|
+
/** Directory to scan recursively. */
|
|
133
|
+
dir?: string;
|
|
134
|
+
}
|
|
135
|
+
export interface ScanOptions {
|
|
136
|
+
/** Reads file content. Required when scanning a diff. */
|
|
137
|
+
fileResolver: FileResolver;
|
|
138
|
+
/** Optional symbol resolver for nicer findings. */
|
|
139
|
+
symbolResolver?: SymbolResolver;
|
|
140
|
+
/** Override the rules pack. Defaults to the built-in `@obfuscan/rules`. */
|
|
141
|
+
rules?: RuleSet;
|
|
142
|
+
/** Allowlist to apply. Merged with anything loaded from `.obfuscan/allowlist.json`. */
|
|
143
|
+
allowlist?: Allowlist;
|
|
144
|
+
/** Hard limit on concurrent file scans. Default: `Math.max(2, os.cpus().length - 1)`. */
|
|
145
|
+
concurrency?: number;
|
|
146
|
+
/** Per-file timeout in ms. Default: 5000. Files that time out emit a single `info` finding and are skipped. */
|
|
147
|
+
fileTimeoutMs?: number;
|
|
148
|
+
/** Severity threshold below which findings are dropped entirely. Default: `"info"`. */
|
|
149
|
+
minSeverity?: Severity;
|
|
150
|
+
/** Optional progress callback. */
|
|
151
|
+
onProgress?: (progress: ScanProgress) => void;
|
|
152
|
+
/** Optional logger; defaults to `console` for warnings, silent for everything else. */
|
|
153
|
+
logger?: Logger;
|
|
154
|
+
/** Disable specific detectors by id (e.g. `["obf.high-entropy-literal"]`). */
|
|
155
|
+
disabledDetectors?: readonly string[];
|
|
156
|
+
/**
|
|
157
|
+
* Override the detector list entirely. When omitted, `defaultDetectors()` is used.
|
|
158
|
+
* Provide an explicit list to extend (`[...defaultDetectors(), myDetector]`) or replace
|
|
159
|
+
* the default set. `disabledDetectors` is applied on top of whichever list is in effect.
|
|
160
|
+
*/
|
|
161
|
+
detectors?: readonly Detector[];
|
|
162
|
+
}
|
|
163
|
+
export interface ScanProgress {
|
|
164
|
+
filesTotal: number;
|
|
165
|
+
filesDone: number;
|
|
166
|
+
currentFile?: string;
|
|
167
|
+
}
|
|
168
|
+
export interface Logger {
|
|
169
|
+
debug(msg: string, meta?: unknown): void;
|
|
170
|
+
info(msg: string, meta?: unknown): void;
|
|
171
|
+
warn(msg: string, meta?: unknown): void;
|
|
172
|
+
error(msg: string, meta?: unknown): void;
|
|
173
|
+
}
|
|
174
|
+
/** A file as the detectors see it. */
|
|
175
|
+
export interface FileContext {
|
|
176
|
+
readonly path: string;
|
|
177
|
+
readonly languageId: string | null;
|
|
178
|
+
readonly config: LanguageConfig | null;
|
|
179
|
+
readonly source: string;
|
|
180
|
+
/** 1-based, inclusive line ranges that were added by the diff. Empty when scanning a full file. */
|
|
181
|
+
readonly addedRanges: ReadonlyArray<readonly [number, number]>;
|
|
182
|
+
/** Lazy parser handle. `null` when no grammar is available for this language. */
|
|
183
|
+
readonly grammar: GrammarHandle | null;
|
|
184
|
+
/** Convenience: the parsed tree, populated on first access. */
|
|
185
|
+
tree(): Promise<unknown | null>;
|
|
186
|
+
}
|
|
187
|
+
/** Detectors are pure: same input → same output. They must not throw to the pipeline. */
|
|
188
|
+
export interface Detector {
|
|
189
|
+
/** Stable detector id. Becomes part of `Finding.ruleId`. */
|
|
190
|
+
readonly id: string;
|
|
191
|
+
/** Documentation URL, optional. Surfaced in findings for users who want to learn more. */
|
|
192
|
+
readonly docsUrl?: string;
|
|
193
|
+
/** Whether this detector applies to a given file. Cheap; called once per file. */
|
|
194
|
+
applies(ctx: FileContext): boolean;
|
|
195
|
+
/** Run the detector. Must catch its own errors. Returns findings synchronously or as a promise. */
|
|
196
|
+
run(ctx: FileContext): Finding[] | Promise<Finding[]>;
|
|
197
|
+
}
|
|
198
|
+
export interface ScanResult {
|
|
199
|
+
/** Aggregated, sorted findings. Sorted by `(severity desc, score desc, file, line)`. */
|
|
200
|
+
findings: readonly Finding[];
|
|
201
|
+
/** Files scanned and their language. */
|
|
202
|
+
files: ReadonlyArray<{
|
|
203
|
+
path: string;
|
|
204
|
+
languageId: string | null;
|
|
205
|
+
}>;
|
|
206
|
+
/** Total wall-clock time in ms. */
|
|
207
|
+
durationMs: number;
|
|
208
|
+
/** Detector ids that failed internally on at least one file (logged, not thrown). */
|
|
209
|
+
failedDetectors: readonly string[];
|
|
210
|
+
/** Rule pack version used. */
|
|
211
|
+
rulesVersion: string;
|
|
212
|
+
/** Engine version used. */
|
|
213
|
+
engineVersion: string;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine version, replaced at build time by the bundler.
|
|
3
|
+
*
|
|
4
|
+
* In source mode (when running tests directly against TS via Vitest), we
|
|
5
|
+
* fall back to reading `packages/core/package.json` lazily. The token
|
|
6
|
+
* `__ENGINE_VERSION__` is replaced by the build pipeline (tsup/esbuild
|
|
7
|
+
* `define`) when shipping a published artifact.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ENGINE_VERSION: string;
|
|
10
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,eAAO,MAAM,cAAc,EAAE,MAgCzB,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine version, replaced at build time by the bundler.
|
|
3
|
+
*
|
|
4
|
+
* In source mode (when running tests directly against TS via Vitest), we
|
|
5
|
+
* fall back to reading `packages/core/package.json` lazily. The token
|
|
6
|
+
* `__ENGINE_VERSION__` is replaced by the build pipeline (tsup/esbuild
|
|
7
|
+
* `define`) when shipping a published artifact.
|
|
8
|
+
*/
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
let cached = null;
|
|
13
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
export const ENGINE_VERSION = (() => {
|
|
15
|
+
if (cached)
|
|
16
|
+
return cached;
|
|
17
|
+
const placeholder = "__ENGINE_VERSION__";
|
|
18
|
+
// Build pipelines replace the literal string above. If still present, we're
|
|
19
|
+
// running against TS sources — read the version from package.json.
|
|
20
|
+
if (placeholder !== "__ENGINE" + "_VERSION__") {
|
|
21
|
+
cached = placeholder;
|
|
22
|
+
return cached;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
// Walk up from this file to locate the nearest package.json.
|
|
26
|
+
const req = createRequire(import.meta.url);
|
|
27
|
+
const candidates = [
|
|
28
|
+
path.resolve(here, "..", "package.json"),
|
|
29
|
+
path.resolve(here, "..", "..", "package.json"),
|
|
30
|
+
];
|
|
31
|
+
for (const c of candidates) {
|
|
32
|
+
try {
|
|
33
|
+
const pkg = req(c);
|
|
34
|
+
if (pkg.name === "@obfuscan/core" && typeof pkg.version === "string") {
|
|
35
|
+
cached = pkg.version;
|
|
36
|
+
return cached;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// try next
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
cached = "0.0.0-source";
|
|
48
|
+
return cached;
|
|
49
|
+
})();
|
|
50
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,MAAM,GAAkB,IAAI,CAAC;AACjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAW,CAAC,GAAG,EAAE;IAC1C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,WAAW,GAAG,oBAAoB,CAAC;IACzC,4EAA4E;IAC5E,mEAAmE;IACnE,IAAI,WAAW,KAAK,UAAU,GAAG,YAAY,EAAE,CAAC;QAC9C,MAAM,GAAG,WAAW,CAAC;QACrB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACH,6DAA6D;QAC7D,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;SAC/C,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAwC,CAAC;gBAC1D,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBACrE,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;oBACrB,OAAO,MAAM,CAAC;gBAChB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,WAAW;YACb,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IACD,MAAM,GAAG,cAAc,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,EAAE,CAAC"}
|