aislop 0.10.0 → 0.10.1
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/cli.js +417 -233
- package/dist/index.js +334 -231
- package/dist/{json-DaFOYHcf.js → json-Bqkcl1DF.js} +1 -1
- package/dist/mcp.js +332 -229
- package/dist/{sarif-BtSQ92c6.js → sarif-C-vh4wcC.js} +1 -1
- package/dist/version-rlhQD8Qh.js +5 -0
- package/package.json +1 -1
- package/dist/version-DYg_ShBx.js +0 -5
package/dist/mcp.js
CHANGED
|
@@ -263,6 +263,218 @@ const loadConfig = (directory) => {
|
|
|
263
263
|
}
|
|
264
264
|
};
|
|
265
265
|
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region src/utils/source-masker.ts
|
|
268
|
+
const JS_EXTS$2 = new Set([
|
|
269
|
+
".ts",
|
|
270
|
+
".tsx",
|
|
271
|
+
".js",
|
|
272
|
+
".jsx",
|
|
273
|
+
".mjs",
|
|
274
|
+
".cjs"
|
|
275
|
+
]);
|
|
276
|
+
const PY_EXTS = new Set([".py"]);
|
|
277
|
+
const RB_EXTS = new Set([".rb"]);
|
|
278
|
+
const PHP_EXTS = new Set([".php"]);
|
|
279
|
+
const familyForExt = (ext) => {
|
|
280
|
+
if (JS_EXTS$2.has(ext)) return "js";
|
|
281
|
+
if (PY_EXTS.has(ext)) return "py";
|
|
282
|
+
if (RB_EXTS.has(ext)) return "rb";
|
|
283
|
+
if (PHP_EXTS.has(ext)) return "php";
|
|
284
|
+
return "none";
|
|
285
|
+
};
|
|
286
|
+
const maskStringsAndComments = (content, ext) => {
|
|
287
|
+
const family = familyForExt(ext);
|
|
288
|
+
if (family === "none") return content;
|
|
289
|
+
if (family === "js") return maskJs(content, true);
|
|
290
|
+
return maskSimple(content, family, true);
|
|
291
|
+
};
|
|
292
|
+
const maskComments = (content, ext) => {
|
|
293
|
+
const family = familyForExt(ext);
|
|
294
|
+
if (family === "none") return content;
|
|
295
|
+
if (family === "js") return maskJs(content, false);
|
|
296
|
+
return maskSimple(content, family, false);
|
|
297
|
+
};
|
|
298
|
+
const handleQuotesAndComments = (content, i, tplStack, mask, maskStrings) => {
|
|
299
|
+
const len = content.length;
|
|
300
|
+
const c = content[i];
|
|
301
|
+
const next = content[i + 1];
|
|
302
|
+
if (c === "\"" || c === "'") {
|
|
303
|
+
const strStart = i;
|
|
304
|
+
const end = consumeQuotedString(content, i, c);
|
|
305
|
+
if (maskStrings) mask(strStart + 1, end - 1);
|
|
306
|
+
return {
|
|
307
|
+
handled: true,
|
|
308
|
+
nextI: end
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (c === "`") {
|
|
312
|
+
const scan = consumeTemplateString(content, i + 1);
|
|
313
|
+
if (maskStrings) mask(i + 1, scan.maskEnd);
|
|
314
|
+
if (scan.openedInterp) tplStack.push(0);
|
|
315
|
+
return {
|
|
316
|
+
handled: true,
|
|
317
|
+
nextI: scan.resumeAt
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (c === "/" && next === "/") {
|
|
321
|
+
const strStart = i;
|
|
322
|
+
let k = i;
|
|
323
|
+
while (k < len && content[k] !== "\n") k++;
|
|
324
|
+
mask(strStart, k);
|
|
325
|
+
return {
|
|
326
|
+
handled: true,
|
|
327
|
+
nextI: k
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
if (c === "/" && next === "*") {
|
|
331
|
+
const strStart = i;
|
|
332
|
+
let k = i + 2;
|
|
333
|
+
while (k < len - 1 && !(content[k] === "*" && content[k + 1] === "/")) k++;
|
|
334
|
+
if (k < len - 1) k += 2;
|
|
335
|
+
mask(strStart, k);
|
|
336
|
+
return {
|
|
337
|
+
handled: true,
|
|
338
|
+
nextI: k
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
handled: false,
|
|
343
|
+
nextI: i
|
|
344
|
+
};
|
|
345
|
+
};
|
|
346
|
+
const maskJs = (content, maskStrings) => {
|
|
347
|
+
const out = content.split("");
|
|
348
|
+
const len = content.length;
|
|
349
|
+
const tplStack = [];
|
|
350
|
+
let i = 0;
|
|
351
|
+
const mask = (start, end) => {
|
|
352
|
+
for (let k = start; k < end; k++) if (out[k] !== "\n") out[k] = " ";
|
|
353
|
+
};
|
|
354
|
+
while (i < len) {
|
|
355
|
+
const c = content[i];
|
|
356
|
+
if (tplStack.length > 0) {
|
|
357
|
+
if (c === "{") {
|
|
358
|
+
tplStack[tplStack.length - 1]++;
|
|
359
|
+
i++;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (c === "}") {
|
|
363
|
+
if (tplStack[tplStack.length - 1] === 0) {
|
|
364
|
+
tplStack.pop();
|
|
365
|
+
const scan = consumeTemplateString(content, i + 1);
|
|
366
|
+
if (maskStrings) mask(i + 1, scan.maskEnd);
|
|
367
|
+
if (scan.openedInterp) tplStack.push(0);
|
|
368
|
+
i = scan.resumeAt;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
tplStack[tplStack.length - 1]--;
|
|
372
|
+
i++;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const handled = handleQuotesAndComments(content, i, tplStack, mask, maskStrings);
|
|
377
|
+
if (handled.handled) {
|
|
378
|
+
i = handled.nextI;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
i++;
|
|
382
|
+
}
|
|
383
|
+
return out.join("");
|
|
384
|
+
};
|
|
385
|
+
const consumeQuotedString = (content, start, quote) => {
|
|
386
|
+
const len = content.length;
|
|
387
|
+
let i = start + 1;
|
|
388
|
+
while (i < len) {
|
|
389
|
+
const c = content[i];
|
|
390
|
+
if (c === "\\" && i + 1 < len) {
|
|
391
|
+
i += 2;
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (c === quote) return i + 1;
|
|
395
|
+
if (c === "\n") return i;
|
|
396
|
+
i++;
|
|
397
|
+
}
|
|
398
|
+
return i;
|
|
399
|
+
};
|
|
400
|
+
const consumeTemplateString = (content, start) => {
|
|
401
|
+
const len = content.length;
|
|
402
|
+
let i = start;
|
|
403
|
+
while (i < len) {
|
|
404
|
+
const c = content[i];
|
|
405
|
+
if (c === "\\" && i + 1 < len) {
|
|
406
|
+
i += 2;
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
if (c === "`") return {
|
|
410
|
+
maskEnd: i,
|
|
411
|
+
resumeAt: i + 1,
|
|
412
|
+
openedInterp: false
|
|
413
|
+
};
|
|
414
|
+
if (c === "$" && content[i + 1] === "{") return {
|
|
415
|
+
maskEnd: i,
|
|
416
|
+
resumeAt: i + 2,
|
|
417
|
+
openedInterp: true
|
|
418
|
+
};
|
|
419
|
+
i++;
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
maskEnd: i,
|
|
423
|
+
resumeAt: i,
|
|
424
|
+
openedInterp: false
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
const maskSimple = (content, family, maskStrings) => {
|
|
428
|
+
const out = content.split("");
|
|
429
|
+
const len = content.length;
|
|
430
|
+
let i = 0;
|
|
431
|
+
const mask = (start, end) => {
|
|
432
|
+
for (let k = start; k < end; k++) if (out[k] !== "\n") out[k] = " ";
|
|
433
|
+
};
|
|
434
|
+
while (i < len) {
|
|
435
|
+
const c = content[i];
|
|
436
|
+
const next = content[i + 1];
|
|
437
|
+
if (family === "py" && (c === "\"" || c === "'")) {
|
|
438
|
+
if (content[i + 1] === c && content[i + 2] === c) {
|
|
439
|
+
const triple = c + c + c;
|
|
440
|
+
const end = content.indexOf(triple, i + 3);
|
|
441
|
+
const stop = end === -1 ? len : end + 3;
|
|
442
|
+
if (maskStrings) mask(i + 3, stop - 3);
|
|
443
|
+
i = stop;
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (c === "\"" || c === "'") {
|
|
448
|
+
const strStart = i;
|
|
449
|
+
i = consumeQuotedString(content, i, c);
|
|
450
|
+
if (maskStrings) mask(strStart + 1, i - 1);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
if ((family === "py" || family === "rb" || family === "php") && c === "#") {
|
|
454
|
+
const strStart = i;
|
|
455
|
+
while (i < len && content[i] !== "\n") i++;
|
|
456
|
+
mask(strStart, i);
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (family === "php" && c === "/" && next === "/") {
|
|
460
|
+
const strStart = i;
|
|
461
|
+
while (i < len && content[i] !== "\n") i++;
|
|
462
|
+
mask(strStart, i);
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (family === "php" && c === "/" && next === "*") {
|
|
466
|
+
const strStart = i;
|
|
467
|
+
i += 2;
|
|
468
|
+
while (i < len - 1 && !(content[i] === "*" && content[i + 1] === "/")) i++;
|
|
469
|
+
if (i < len - 1) i += 2;
|
|
470
|
+
mask(strStart, i);
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
i++;
|
|
474
|
+
}
|
|
475
|
+
return out.join("");
|
|
476
|
+
};
|
|
477
|
+
|
|
266
478
|
//#endregion
|
|
267
479
|
//#region src/utils/source-files.ts
|
|
268
480
|
const MAX_BUFFER = 50 * 1024 * 1024;
|
|
@@ -513,7 +725,7 @@ const getSourceFilesWithExtras = (context, extraExtensions) => {
|
|
|
513
725
|
|
|
514
726
|
//#endregion
|
|
515
727
|
//#region src/engines/ai-slop/abstractions.ts
|
|
516
|
-
const JS_EXTS$
|
|
728
|
+
const JS_EXTS$1 = new Set([
|
|
517
729
|
".ts",
|
|
518
730
|
".tsx",
|
|
519
731
|
".js",
|
|
@@ -524,11 +736,11 @@ const JS_EXTS$2 = new Set([
|
|
|
524
736
|
const THIN_WRAPPER_PATTERNS = [
|
|
525
737
|
{
|
|
526
738
|
pattern: /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\([^)]*\)\s*(?::\s*\w[^{]*)?\{\s*\n?\s*return\s+\w+\([^)]*\);\s*\n?\s*\}/g,
|
|
527
|
-
extensions: JS_EXTS$
|
|
739
|
+
extensions: JS_EXTS$1
|
|
528
740
|
},
|
|
529
741
|
{
|
|
530
742
|
pattern: /(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*(?::\s*\w[^=]*)?\s*=>\s*\w+\([^)]*\);/g,
|
|
531
|
-
extensions: JS_EXTS$
|
|
743
|
+
extensions: JS_EXTS$1
|
|
532
744
|
},
|
|
533
745
|
{
|
|
534
746
|
pattern: /def\s+(\w+)\s*\([^)]*\)(?:\s*->[^:]*)?:\s*\n\s+return\s+\w+\([^)]*\)\s*$/gm,
|
|
@@ -621,8 +833,9 @@ const detectOverAbstraction = async (context) => {
|
|
|
621
833
|
}
|
|
622
834
|
const relativePath = path.relative(context.rootDirectory, filePath);
|
|
623
835
|
const ext = path.extname(filePath);
|
|
624
|
-
|
|
625
|
-
diagnostics.push(...
|
|
836
|
+
const codeOnly = maskComments(content, ext);
|
|
837
|
+
diagnostics.push(...detectThinWrappers(codeOnly, relativePath, ext));
|
|
838
|
+
diagnostics.push(...detectAiNaming(codeOnly, relativePath));
|
|
626
839
|
}
|
|
627
840
|
return diagnostics;
|
|
628
841
|
};
|
|
@@ -978,9 +1191,10 @@ const detectDeadPatterns = async (context) => {
|
|
|
978
1191
|
}
|
|
979
1192
|
const ext = path.extname(filePath);
|
|
980
1193
|
const relativePath = path.relative(context.rootDirectory, filePath);
|
|
981
|
-
|
|
1194
|
+
const codeOnly = maskComments(content, ext);
|
|
1195
|
+
diagnostics.push(...detectConsoleLeftovers(codeOnly, relativePath, ext));
|
|
982
1196
|
diagnostics.push(...detectTodoStubs(content, relativePath));
|
|
983
|
-
diagnostics.push(...detectDeadCodePatterns(
|
|
1197
|
+
diagnostics.push(...detectDeadCodePatterns(codeOnly, relativePath, ext));
|
|
984
1198
|
diagnostics.push(...detectUnsafeTypePatterns(content, relativePath, ext));
|
|
985
1199
|
}
|
|
986
1200
|
return diagnostics;
|
|
@@ -1170,6 +1384,7 @@ const JS_EXTENSIONS$2 = new Set([
|
|
|
1170
1384
|
const IMPORT_FROM_RE = /^\s*import\s+([^;]*?)\s+from\s+["']([^"']+)["']/;
|
|
1171
1385
|
const TYPE_ONLY_RE = /^\s*type\b/;
|
|
1172
1386
|
const VALUE_BINDING_RE = /\{([^}]*)\}/;
|
|
1387
|
+
const NAMESPACE_RE = /\*\s+as\s+/;
|
|
1173
1388
|
const isTypeOnly = (clause) => {
|
|
1174
1389
|
if (TYPE_ONLY_RE.test(clause)) return true;
|
|
1175
1390
|
const braces = VALUE_BINDING_RE.exec(clause);
|
|
@@ -1187,7 +1402,8 @@ const extractImportLines = (content) => {
|
|
|
1187
1402
|
results.push({
|
|
1188
1403
|
spec: match[2],
|
|
1189
1404
|
line: i + 1,
|
|
1190
|
-
typeOnly: isTypeOnly(match[1])
|
|
1405
|
+
typeOnly: isTypeOnly(match[1]),
|
|
1406
|
+
namespace: NAMESPACE_RE.test(match[1])
|
|
1191
1407
|
});
|
|
1192
1408
|
}
|
|
1193
1409
|
return results;
|
|
@@ -1204,11 +1420,11 @@ const detectDuplicateImports = async (context) => {
|
|
|
1204
1420
|
} catch {
|
|
1205
1421
|
continue;
|
|
1206
1422
|
}
|
|
1207
|
-
const imports = extractImportLines(content);
|
|
1423
|
+
const imports = extractImportLines(maskComments(content, path.extname(filePath)));
|
|
1208
1424
|
if (imports.length < 2) continue;
|
|
1209
1425
|
const byBucket = /* @__PURE__ */ new Map();
|
|
1210
1426
|
for (const imp of imports) {
|
|
1211
|
-
const key = `${imp.typeOnly ? "type" : "value"}\0${imp.spec}`;
|
|
1427
|
+
const key = `${imp.namespace ? "ns" : imp.typeOnly ? "type" : "value"}\0${imp.spec}`;
|
|
1212
1428
|
const list = byBucket.get(key) ?? [];
|
|
1213
1429
|
list.push(imp);
|
|
1214
1430
|
byBucket.set(key, list);
|
|
@@ -1575,7 +1791,7 @@ const detectHardcodedConfigLiterals = async (context) => {
|
|
|
1575
1791
|
}
|
|
1576
1792
|
const relativePath = path.relative(context.rootDirectory, filePath);
|
|
1577
1793
|
const ext = path.extname(filePath);
|
|
1578
|
-
diagnostics.push(...scanFileForConfigLiterals(content, relativePath, ext));
|
|
1794
|
+
diagnostics.push(...scanFileForConfigLiterals(maskComments(content, ext), relativePath, ext));
|
|
1579
1795
|
}
|
|
1580
1796
|
return diagnostics;
|
|
1581
1797
|
};
|
|
@@ -3081,7 +3297,7 @@ const detectRustPatterns = async (context) => {
|
|
|
3081
3297
|
|
|
3082
3298
|
//#endregion
|
|
3083
3299
|
//#region src/engines/ai-slop/silent-recovery.ts
|
|
3084
|
-
const JS_EXTS
|
|
3300
|
+
const JS_EXTS = new Set([
|
|
3085
3301
|
".ts",
|
|
3086
3302
|
".tsx",
|
|
3087
3303
|
".js",
|
|
@@ -3210,7 +3426,7 @@ const detectSilentRecovery = async (context) => {
|
|
|
3210
3426
|
for (const filePath of files) {
|
|
3211
3427
|
if (isAutoGenerated(filePath)) continue;
|
|
3212
3428
|
const ext = path.extname(filePath);
|
|
3213
|
-
const isJs = JS_EXTS
|
|
3429
|
+
const isJs = JS_EXTS.has(ext);
|
|
3214
3430
|
if (!isJs && !(ext === ".py")) continue;
|
|
3215
3431
|
const relPath = path.relative(context.rootDirectory, filePath);
|
|
3216
3432
|
if (isNonProductionPath(relPath)) continue;
|
|
@@ -3689,12 +3905,92 @@ const findBraceFunctionEnd = (lines, startIndex) => {
|
|
|
3689
3905
|
maxNesting
|
|
3690
3906
|
};
|
|
3691
3907
|
};
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
let
|
|
3908
|
+
const extractPythonSignature = (lines, startIndex) => {
|
|
3909
|
+
let depth = 0;
|
|
3910
|
+
let started = false;
|
|
3911
|
+
let params = "";
|
|
3912
|
+
for (let j = startIndex; j < lines.length; j++) {
|
|
3913
|
+
const l = lines[j];
|
|
3914
|
+
for (let ci = 0; ci < l.length; ci++) {
|
|
3915
|
+
const ch = l[ci];
|
|
3916
|
+
if (ch === "(") {
|
|
3917
|
+
depth++;
|
|
3918
|
+
if (depth === 1 && !started) {
|
|
3919
|
+
started = true;
|
|
3920
|
+
continue;
|
|
3921
|
+
}
|
|
3922
|
+
} else if (ch === ")") {
|
|
3923
|
+
depth--;
|
|
3924
|
+
if (depth === 0) return {
|
|
3925
|
+
params,
|
|
3926
|
+
sigEndIndex: j
|
|
3927
|
+
};
|
|
3928
|
+
}
|
|
3929
|
+
if (started) params += ch;
|
|
3930
|
+
}
|
|
3931
|
+
if (started) params += " ";
|
|
3932
|
+
}
|
|
3933
|
+
return {
|
|
3934
|
+
params,
|
|
3935
|
+
sigEndIndex: startIndex
|
|
3936
|
+
};
|
|
3937
|
+
};
|
|
3938
|
+
const countPythonParams = (signature) => {
|
|
3939
|
+
let depth = 0;
|
|
3940
|
+
const parts = [];
|
|
3941
|
+
let current = "";
|
|
3942
|
+
for (const ch of signature) {
|
|
3943
|
+
if (ch === "(" || ch === "[" || ch === "{") depth++;
|
|
3944
|
+
else if (ch === ")" || ch === "]" || ch === "}") depth--;
|
|
3945
|
+
if (ch === "," && depth === 0) {
|
|
3946
|
+
parts.push(current);
|
|
3947
|
+
current = "";
|
|
3948
|
+
continue;
|
|
3949
|
+
}
|
|
3950
|
+
current += ch;
|
|
3951
|
+
}
|
|
3952
|
+
parts.push(current);
|
|
3953
|
+
let count = 0;
|
|
3954
|
+
for (const raw of parts) {
|
|
3955
|
+
const p = raw.trim();
|
|
3956
|
+
if (p.length === 0 || p === "*" || p === "/") continue;
|
|
3957
|
+
if (p.startsWith("*")) continue;
|
|
3958
|
+
if (p.includes("=")) continue;
|
|
3959
|
+
const name = p.split(":")[0].trim();
|
|
3960
|
+
if (name === "self" || name === "cls") continue;
|
|
3961
|
+
count++;
|
|
3962
|
+
}
|
|
3963
|
+
return count;
|
|
3964
|
+
};
|
|
3965
|
+
const countPythonBodyCodeLines = (lines, sigEndIndex, endLine) => {
|
|
3966
|
+
let count = 0;
|
|
3967
|
+
let inDoc = false;
|
|
3968
|
+
let delim = "";
|
|
3969
|
+
for (let j = sigEndIndex + 1; j <= endLine && j < lines.length; j++) {
|
|
3970
|
+
const t = lines[j].trim();
|
|
3971
|
+
if (inDoc) {
|
|
3972
|
+
if (t.includes(delim)) inDoc = false;
|
|
3973
|
+
continue;
|
|
3974
|
+
}
|
|
3975
|
+
if (t === "" || t.startsWith("#")) continue;
|
|
3976
|
+
const opener = t.startsWith("\"\"\"") ? "\"\"\"" : t.startsWith("'''") ? "'''" : "";
|
|
3977
|
+
if (opener) {
|
|
3978
|
+
if (!t.slice(3).includes(opener)) {
|
|
3979
|
+
inDoc = true;
|
|
3980
|
+
delim = opener;
|
|
3981
|
+
}
|
|
3982
|
+
continue;
|
|
3983
|
+
}
|
|
3984
|
+
count++;
|
|
3985
|
+
}
|
|
3986
|
+
return count;
|
|
3987
|
+
};
|
|
3988
|
+
const findPythonFunctionEnd = (lines, defIndex, bodyStartIndex) => {
|
|
3989
|
+
const baseIndent = lines[defIndex].match(/^(\s*)/)?.[1].length ?? 0;
|
|
3990
|
+
let endLine = bodyStartIndex;
|
|
3695
3991
|
let maxNesting = 0;
|
|
3696
3992
|
const controlIndentStack = [];
|
|
3697
|
-
for (let j =
|
|
3993
|
+
for (let j = bodyStartIndex + 1; j < lines.length; j++) {
|
|
3698
3994
|
const l = lines[j];
|
|
3699
3995
|
if (l.trim() === "") {
|
|
3700
3996
|
endLine = j;
|
|
@@ -3716,7 +4012,10 @@ const findPythonFunctionEnd = (lines, startIndex) => {
|
|
|
3716
4012
|
};
|
|
3717
4013
|
};
|
|
3718
4014
|
const findFunctionEnd = (lines, startIndex, isPython) => {
|
|
3719
|
-
if (isPython)
|
|
4015
|
+
if (isPython) {
|
|
4016
|
+
const { sigEndIndex } = extractPythonSignature(lines, startIndex);
|
|
4017
|
+
return findPythonFunctionEnd(lines, startIndex, sigEndIndex);
|
|
4018
|
+
}
|
|
3720
4019
|
return findBraceFunctionEnd(lines, startIndex);
|
|
3721
4020
|
};
|
|
3722
4021
|
const isBlockArrow = (lines, startIndex) => {
|
|
@@ -3781,7 +4080,7 @@ const FUNCTION_PATTERNS = [
|
|
|
3781
4080
|
]
|
|
3782
4081
|
},
|
|
3783
4082
|
{
|
|
3784
|
-
regex: /^\s*def\s+(\w+)\s*\(
|
|
4083
|
+
regex: /^\s*(?:async\s+)?def\s+(\w+)\s*\(/,
|
|
3785
4084
|
langFilter: [".py"]
|
|
3786
4085
|
},
|
|
3787
4086
|
{
|
|
@@ -3838,14 +4137,23 @@ const analyzeFunctions = (content, ext) => {
|
|
|
3838
4137
|
const isPython = fnMatch.patternIndex === 2;
|
|
3839
4138
|
if (fnMatch.patternIndex === 1 && !isBlockArrow(lines, i)) continue;
|
|
3840
4139
|
const { endLine, maxNesting } = findFunctionEnd(lines, i, isPython);
|
|
3841
|
-
|
|
3842
|
-
|
|
4140
|
+
let templateLines;
|
|
4141
|
+
let paramCount;
|
|
4142
|
+
if (isPython) {
|
|
4143
|
+
const sig = extractPythonSignature(lines, i);
|
|
4144
|
+
const codeLines = countPythonBodyCodeLines(lines, sig.sigEndIndex, endLine);
|
|
4145
|
+
templateLines = endLine - i + 1 - codeLines;
|
|
4146
|
+
paramCount = countPythonParams(sig.params);
|
|
4147
|
+
} else {
|
|
4148
|
+
templateLines = countTemplateLines(lines.slice(i + 1, endLine));
|
|
4149
|
+
paramCount = countParams(fnMatch.params);
|
|
4150
|
+
}
|
|
3843
4151
|
functions.push({
|
|
3844
4152
|
name: fnMatch.name,
|
|
3845
4153
|
startLine: i + 1,
|
|
3846
4154
|
lineCount: endLine - i + 1,
|
|
3847
4155
|
maxNesting,
|
|
3848
|
-
paramCount
|
|
4156
|
+
paramCount,
|
|
3849
4157
|
templateLines
|
|
3850
4158
|
});
|
|
3851
4159
|
}
|
|
@@ -5557,212 +5865,6 @@ const runCargoAudit = async (rootDir, timeout) => {
|
|
|
5557
5865
|
}
|
|
5558
5866
|
};
|
|
5559
5867
|
|
|
5560
|
-
//#endregion
|
|
5561
|
-
//#region src/utils/source-masker.ts
|
|
5562
|
-
const JS_EXTS = new Set([
|
|
5563
|
-
".ts",
|
|
5564
|
-
".tsx",
|
|
5565
|
-
".js",
|
|
5566
|
-
".jsx",
|
|
5567
|
-
".mjs",
|
|
5568
|
-
".cjs"
|
|
5569
|
-
]);
|
|
5570
|
-
const PY_EXTS = new Set([".py"]);
|
|
5571
|
-
const RB_EXTS = new Set([".rb"]);
|
|
5572
|
-
const PHP_EXTS = new Set([".php"]);
|
|
5573
|
-
const familyForExt = (ext) => {
|
|
5574
|
-
if (JS_EXTS.has(ext)) return "js";
|
|
5575
|
-
if (PY_EXTS.has(ext)) return "py";
|
|
5576
|
-
if (RB_EXTS.has(ext)) return "rb";
|
|
5577
|
-
if (PHP_EXTS.has(ext)) return "php";
|
|
5578
|
-
return "none";
|
|
5579
|
-
};
|
|
5580
|
-
const maskStringsAndComments = (content, ext) => {
|
|
5581
|
-
const family = familyForExt(ext);
|
|
5582
|
-
if (family === "none") return content;
|
|
5583
|
-
if (family === "js") return maskJs(content);
|
|
5584
|
-
return maskSimple(content, family);
|
|
5585
|
-
};
|
|
5586
|
-
const handleQuotesAndComments = (content, i, tplStack, mask) => {
|
|
5587
|
-
const len = content.length;
|
|
5588
|
-
const c = content[i];
|
|
5589
|
-
const next = content[i + 1];
|
|
5590
|
-
if (c === "\"" || c === "'") {
|
|
5591
|
-
const strStart = i;
|
|
5592
|
-
const end = consumeQuotedString(content, i, c);
|
|
5593
|
-
mask(strStart + 1, end - 1);
|
|
5594
|
-
return {
|
|
5595
|
-
handled: true,
|
|
5596
|
-
nextI: end
|
|
5597
|
-
};
|
|
5598
|
-
}
|
|
5599
|
-
if (c === "`") {
|
|
5600
|
-
const scan = consumeTemplateString(content, i + 1);
|
|
5601
|
-
mask(i + 1, scan.maskEnd);
|
|
5602
|
-
if (scan.openedInterp) tplStack.push(0);
|
|
5603
|
-
return {
|
|
5604
|
-
handled: true,
|
|
5605
|
-
nextI: scan.resumeAt
|
|
5606
|
-
};
|
|
5607
|
-
}
|
|
5608
|
-
if (c === "/" && next === "/") {
|
|
5609
|
-
const strStart = i;
|
|
5610
|
-
let k = i;
|
|
5611
|
-
while (k < len && content[k] !== "\n") k++;
|
|
5612
|
-
mask(strStart, k);
|
|
5613
|
-
return {
|
|
5614
|
-
handled: true,
|
|
5615
|
-
nextI: k
|
|
5616
|
-
};
|
|
5617
|
-
}
|
|
5618
|
-
if (c === "/" && next === "*") {
|
|
5619
|
-
const strStart = i;
|
|
5620
|
-
let k = i + 2;
|
|
5621
|
-
while (k < len - 1 && !(content[k] === "*" && content[k + 1] === "/")) k++;
|
|
5622
|
-
if (k < len - 1) k += 2;
|
|
5623
|
-
mask(strStart, k);
|
|
5624
|
-
return {
|
|
5625
|
-
handled: true,
|
|
5626
|
-
nextI: k
|
|
5627
|
-
};
|
|
5628
|
-
}
|
|
5629
|
-
return {
|
|
5630
|
-
handled: false,
|
|
5631
|
-
nextI: i
|
|
5632
|
-
};
|
|
5633
|
-
};
|
|
5634
|
-
const maskJs = (content) => {
|
|
5635
|
-
const out = content.split("");
|
|
5636
|
-
const len = content.length;
|
|
5637
|
-
const tplStack = [];
|
|
5638
|
-
let i = 0;
|
|
5639
|
-
const mask = (start, end) => {
|
|
5640
|
-
for (let k = start; k < end; k++) if (out[k] !== "\n") out[k] = " ";
|
|
5641
|
-
};
|
|
5642
|
-
while (i < len) {
|
|
5643
|
-
const c = content[i];
|
|
5644
|
-
if (tplStack.length > 0) {
|
|
5645
|
-
if (c === "{") {
|
|
5646
|
-
tplStack[tplStack.length - 1]++;
|
|
5647
|
-
i++;
|
|
5648
|
-
continue;
|
|
5649
|
-
}
|
|
5650
|
-
if (c === "}") {
|
|
5651
|
-
if (tplStack[tplStack.length - 1] === 0) {
|
|
5652
|
-
tplStack.pop();
|
|
5653
|
-
const scan = consumeTemplateString(content, i + 1);
|
|
5654
|
-
mask(i + 1, scan.maskEnd);
|
|
5655
|
-
if (scan.openedInterp) tplStack.push(0);
|
|
5656
|
-
i = scan.resumeAt;
|
|
5657
|
-
continue;
|
|
5658
|
-
}
|
|
5659
|
-
tplStack[tplStack.length - 1]--;
|
|
5660
|
-
i++;
|
|
5661
|
-
continue;
|
|
5662
|
-
}
|
|
5663
|
-
}
|
|
5664
|
-
const handled = handleQuotesAndComments(content, i, tplStack, mask);
|
|
5665
|
-
if (handled.handled) {
|
|
5666
|
-
i = handled.nextI;
|
|
5667
|
-
continue;
|
|
5668
|
-
}
|
|
5669
|
-
i++;
|
|
5670
|
-
}
|
|
5671
|
-
return out.join("");
|
|
5672
|
-
};
|
|
5673
|
-
const consumeQuotedString = (content, start, quote) => {
|
|
5674
|
-
const len = content.length;
|
|
5675
|
-
let i = start + 1;
|
|
5676
|
-
while (i < len) {
|
|
5677
|
-
const c = content[i];
|
|
5678
|
-
if (c === "\\" && i + 1 < len) {
|
|
5679
|
-
i += 2;
|
|
5680
|
-
continue;
|
|
5681
|
-
}
|
|
5682
|
-
if (c === quote) return i + 1;
|
|
5683
|
-
if (c === "\n") return i;
|
|
5684
|
-
i++;
|
|
5685
|
-
}
|
|
5686
|
-
return i;
|
|
5687
|
-
};
|
|
5688
|
-
const consumeTemplateString = (content, start) => {
|
|
5689
|
-
const len = content.length;
|
|
5690
|
-
let i = start;
|
|
5691
|
-
while (i < len) {
|
|
5692
|
-
const c = content[i];
|
|
5693
|
-
if (c === "\\" && i + 1 < len) {
|
|
5694
|
-
i += 2;
|
|
5695
|
-
continue;
|
|
5696
|
-
}
|
|
5697
|
-
if (c === "`") return {
|
|
5698
|
-
maskEnd: i,
|
|
5699
|
-
resumeAt: i + 1,
|
|
5700
|
-
openedInterp: false
|
|
5701
|
-
};
|
|
5702
|
-
if (c === "$" && content[i + 1] === "{") return {
|
|
5703
|
-
maskEnd: i,
|
|
5704
|
-
resumeAt: i + 2,
|
|
5705
|
-
openedInterp: true
|
|
5706
|
-
};
|
|
5707
|
-
i++;
|
|
5708
|
-
}
|
|
5709
|
-
return {
|
|
5710
|
-
maskEnd: i,
|
|
5711
|
-
resumeAt: i,
|
|
5712
|
-
openedInterp: false
|
|
5713
|
-
};
|
|
5714
|
-
};
|
|
5715
|
-
const maskSimple = (content, family) => {
|
|
5716
|
-
const out = content.split("");
|
|
5717
|
-
const len = content.length;
|
|
5718
|
-
let i = 0;
|
|
5719
|
-
const mask = (start, end) => {
|
|
5720
|
-
for (let k = start; k < end; k++) if (out[k] !== "\n") out[k] = " ";
|
|
5721
|
-
};
|
|
5722
|
-
while (i < len) {
|
|
5723
|
-
const c = content[i];
|
|
5724
|
-
const next = content[i + 1];
|
|
5725
|
-
if (family === "py" && (c === "\"" || c === "'")) {
|
|
5726
|
-
if (content[i + 1] === c && content[i + 2] === c) {
|
|
5727
|
-
const triple = c + c + c;
|
|
5728
|
-
const end = content.indexOf(triple, i + 3);
|
|
5729
|
-
const stop = end === -1 ? len : end + 3;
|
|
5730
|
-
mask(i + 3, stop - 3);
|
|
5731
|
-
i = stop;
|
|
5732
|
-
continue;
|
|
5733
|
-
}
|
|
5734
|
-
}
|
|
5735
|
-
if (c === "\"" || c === "'") {
|
|
5736
|
-
const strStart = i;
|
|
5737
|
-
i = consumeQuotedString(content, i, c);
|
|
5738
|
-
mask(strStart + 1, i - 1);
|
|
5739
|
-
continue;
|
|
5740
|
-
}
|
|
5741
|
-
if ((family === "py" || family === "rb" || family === "php") && c === "#") {
|
|
5742
|
-
const strStart = i;
|
|
5743
|
-
while (i < len && content[i] !== "\n") i++;
|
|
5744
|
-
mask(strStart, i);
|
|
5745
|
-
continue;
|
|
5746
|
-
}
|
|
5747
|
-
if (family === "php" && c === "/" && next === "/") {
|
|
5748
|
-
const strStart = i;
|
|
5749
|
-
while (i < len && content[i] !== "\n") i++;
|
|
5750
|
-
mask(strStart, i);
|
|
5751
|
-
continue;
|
|
5752
|
-
}
|
|
5753
|
-
if (family === "php" && c === "/" && next === "*") {
|
|
5754
|
-
const strStart = i;
|
|
5755
|
-
i += 2;
|
|
5756
|
-
while (i < len - 1 && !(content[i] === "*" && content[i + 1] === "/")) i++;
|
|
5757
|
-
if (i < len - 1) i += 2;
|
|
5758
|
-
mask(strStart, i);
|
|
5759
|
-
continue;
|
|
5760
|
-
}
|
|
5761
|
-
i++;
|
|
5762
|
-
}
|
|
5763
|
-
return out.join("");
|
|
5764
|
-
};
|
|
5765
|
-
|
|
5766
5868
|
//#endregion
|
|
5767
5869
|
//#region src/engines/security/risky.ts
|
|
5768
5870
|
const ev = "eval";
|
|
@@ -6037,6 +6139,7 @@ const scanSecrets = async (context) => {
|
|
|
6037
6139
|
} catch {
|
|
6038
6140
|
continue;
|
|
6039
6141
|
}
|
|
6142
|
+
content = maskComments(content, path.extname(filePath));
|
|
6040
6143
|
const relativePath = path.relative(context.rootDirectory, filePath);
|
|
6041
6144
|
for (const { pattern, name, keywordPrefixed } of SECRET_PATTERNS) {
|
|
6042
6145
|
const regex = new RegExp(pattern.source, pattern.flags);
|
|
@@ -6514,7 +6617,7 @@ const handleAislopBaseline = (input) => {
|
|
|
6514
6617
|
|
|
6515
6618
|
//#endregion
|
|
6516
6619
|
//#region src/version.ts
|
|
6517
|
-
const APP_VERSION = "0.10.
|
|
6620
|
+
const APP_VERSION = "0.10.1";
|
|
6518
6621
|
|
|
6519
6622
|
//#endregion
|
|
6520
6623
|
//#region src/telemetry/env.ts
|