@kairosinternational/watchman 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/PHASE_3A_COMPLETE.md +63 -0
- package/dist/engine.d.ts +9 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +99 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/index.d.ts +2 -0
- package/dist/scanners/ai-tool-integrity/index.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/index.js +6 -0
- package/dist/scanners/ai-tool-integrity/index.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/patterns/injection-signatures.d.ts +7 -0
- package/dist/scanners/ai-tool-integrity/patterns/injection-signatures.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/patterns/injection-signatures.js +51 -0
- package/dist/scanners/ai-tool-integrity/patterns/injection-signatures.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/prompt-injection.rule.d.ts +3 -0
- package/dist/scanners/ai-tool-integrity/rules/prompt-injection.rule.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/prompt-injection.rule.js +49 -0
- package/dist/scanners/ai-tool-integrity/rules/prompt-injection.rule.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/tool-manifest-drift.rule.d.ts +3 -0
- package/dist/scanners/ai-tool-integrity/rules/tool-manifest-drift.rule.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/tool-manifest-drift.rule.js +71 -0
- package/dist/scanners/ai-tool-integrity/rules/tool-manifest-drift.rule.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/unauthorized-model-call.rule.d.ts +3 -0
- package/dist/scanners/ai-tool-integrity/rules/unauthorized-model-call.rule.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/rules/unauthorized-model-call.rule.js +56 -0
- package/dist/scanners/ai-tool-integrity/rules/unauthorized-model-call.rule.js.map +1 -0
- package/dist/scanners/ai-tool-integrity/scanner.d.ts +3 -0
- package/dist/scanners/ai-tool-integrity/scanner.d.ts.map +1 -0
- package/dist/scanners/ai-tool-integrity/scanner.js +26 -0
- package/dist/scanners/ai-tool-integrity/scanner.js.map +1 -0
- package/dist/scanners/dependency-integrity/index.d.ts +2 -0
- package/dist/scanners/dependency-integrity/index.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/index.js +6 -0
- package/dist/scanners/dependency-integrity/index.js.map +1 -0
- package/dist/scanners/dependency-integrity/patterns/known-typosquats.d.ts +8 -0
- package/dist/scanners/dependency-integrity/patterns/known-typosquats.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/patterns/known-typosquats.js +38 -0
- package/dist/scanners/dependency-integrity/patterns/known-typosquats.js.map +1 -0
- package/dist/scanners/dependency-integrity/rules/hash-validation.rule.d.ts +3 -0
- package/dist/scanners/dependency-integrity/rules/hash-validation.rule.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/rules/hash-validation.rule.js +64 -0
- package/dist/scanners/dependency-integrity/rules/hash-validation.rule.js.map +1 -0
- package/dist/scanners/dependency-integrity/rules/transitive-drift.rule.d.ts +3 -0
- package/dist/scanners/dependency-integrity/rules/transitive-drift.rule.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/rules/transitive-drift.rule.js +69 -0
- package/dist/scanners/dependency-integrity/rules/transitive-drift.rule.js.map +1 -0
- package/dist/scanners/dependency-integrity/rules/typosquat-check.rule.d.ts +3 -0
- package/dist/scanners/dependency-integrity/rules/typosquat-check.rule.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/rules/typosquat-check.rule.js +94 -0
- package/dist/scanners/dependency-integrity/rules/typosquat-check.rule.js.map +1 -0
- package/dist/scanners/dependency-integrity/scanner.d.ts +3 -0
- package/dist/scanners/dependency-integrity/scanner.d.ts.map +1 -0
- package/dist/scanners/dependency-integrity/scanner.js +26 -0
- package/dist/scanners/dependency-integrity/scanner.js.map +1 -0
- package/dist/scanners/runtime-monitor/index.d.ts +2 -0
- package/dist/scanners/runtime-monitor/index.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/index.js +6 -0
- package/dist/scanners/runtime-monitor/index.js.map +1 -0
- package/dist/scanners/runtime-monitor/patterns/known-bad-destinations.d.ts +8 -0
- package/dist/scanners/runtime-monitor/patterns/known-bad-destinations.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/patterns/known-bad-destinations.js +52 -0
- package/dist/scanners/runtime-monitor/patterns/known-bad-destinations.js.map +1 -0
- package/dist/scanners/runtime-monitor/rules/filesystem-access.rule.d.ts +3 -0
- package/dist/scanners/runtime-monitor/rules/filesystem-access.rule.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/rules/filesystem-access.rule.js +68 -0
- package/dist/scanners/runtime-monitor/rules/filesystem-access.rule.js.map +1 -0
- package/dist/scanners/runtime-monitor/rules/outbound-network.rule.d.ts +3 -0
- package/dist/scanners/runtime-monitor/rules/outbound-network.rule.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/rules/outbound-network.rule.js +62 -0
- package/dist/scanners/runtime-monitor/rules/outbound-network.rule.js.map +1 -0
- package/dist/scanners/runtime-monitor/rules/process-spawn.rule.d.ts +3 -0
- package/dist/scanners/runtime-monitor/rules/process-spawn.rule.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/rules/process-spawn.rule.js +55 -0
- package/dist/scanners/runtime-monitor/rules/process-spawn.rule.js.map +1 -0
- package/dist/scanners/runtime-monitor/rules/resource-anomaly.rule.d.ts +3 -0
- package/dist/scanners/runtime-monitor/rules/resource-anomaly.rule.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/rules/resource-anomaly.rule.js +76 -0
- package/dist/scanners/runtime-monitor/rules/resource-anomaly.rule.js.map +1 -0
- package/dist/scanners/runtime-monitor/scanner.d.ts +3 -0
- package/dist/scanners/runtime-monitor/scanner.d.ts.map +1 -0
- package/dist/scanners/runtime-monitor/scanner.js +28 -0
- package/dist/scanners/runtime-monitor/scanner.js.map +1 -0
- package/dist/scanners/secrets-exposure/index.d.ts +2 -0
- package/dist/scanners/secrets-exposure/index.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/index.js +6 -0
- package/dist/scanners/secrets-exposure/index.js.map +1 -0
- package/dist/scanners/secrets-exposure/patterns/secret-signatures.d.ts +7 -0
- package/dist/scanners/secrets-exposure/patterns/secret-signatures.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/patterns/secret-signatures.js +76 -0
- package/dist/scanners/secrets-exposure/patterns/secret-signatures.js.map +1 -0
- package/dist/scanners/secrets-exposure/rules/entropy-check.rule.d.ts +3 -0
- package/dist/scanners/secrets-exposure/rules/entropy-check.rule.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/rules/entropy-check.rule.js +77 -0
- package/dist/scanners/secrets-exposure/rules/entropy-check.rule.js.map +1 -0
- package/dist/scanners/secrets-exposure/rules/known-patterns.rule.d.ts +3 -0
- package/dist/scanners/secrets-exposure/rules/known-patterns.rule.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/rules/known-patterns.rule.js +62 -0
- package/dist/scanners/secrets-exposure/rules/known-patterns.rule.js.map +1 -0
- package/dist/scanners/secrets-exposure/rules/response-echo.rule.d.ts +3 -0
- package/dist/scanners/secrets-exposure/rules/response-echo.rule.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/rules/response-echo.rule.js +67 -0
- package/dist/scanners/secrets-exposure/rules/response-echo.rule.js.map +1 -0
- package/dist/scanners/secrets-exposure/scanner.d.ts +3 -0
- package/dist/scanners/secrets-exposure/scanner.d.ts.map +1 -0
- package/dist/scanners/secrets-exposure/scanner.js +26 -0
- package/dist/scanners/secrets-exposure/scanner.js.map +1 -0
- package/dist/types/config.types.d.ts +22 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +15 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/context.types.d.ts +23 -0
- package/dist/types/context.types.d.ts.map +1 -0
- package/dist/types/context.types.js +3 -0
- package/dist/types/context.types.js.map +1 -0
- package/dist/types/finding.types.d.ts +33 -0
- package/dist/types/finding.types.d.ts.map +1 -0
- package/dist/types/finding.types.js +3 -0
- package/dist/types/finding.types.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +32 -0
- package/src/engine.ts +129 -0
- package/src/index.ts +28 -0
- package/src/scanners/ai-tool-integrity/index.ts +1 -0
- package/src/scanners/ai-tool-integrity/patterns/injection-signatures.ts +53 -0
- package/src/scanners/ai-tool-integrity/rules/prompt-injection.rule.ts +50 -0
- package/src/scanners/ai-tool-integrity/rules/tool-manifest-drift.rule.ts +81 -0
- package/src/scanners/ai-tool-integrity/rules/unauthorized-model-call.rule.ts +59 -0
- package/src/scanners/ai-tool-integrity/scanner.ts +25 -0
- package/src/scanners/dependency-integrity/index.ts +1 -0
- package/src/scanners/dependency-integrity/patterns/known-typosquats.ts +41 -0
- package/src/scanners/dependency-integrity/rules/hash-validation.rule.ts +72 -0
- package/src/scanners/dependency-integrity/rules/transitive-drift.rule.ts +71 -0
- package/src/scanners/dependency-integrity/rules/typosquat-check.rule.ts +100 -0
- package/src/scanners/dependency-integrity/scanner.ts +25 -0
- package/src/scanners/runtime-monitor/index.ts +1 -0
- package/src/scanners/runtime-monitor/patterns/known-bad-destinations.ts +55 -0
- package/src/scanners/runtime-monitor/rules/filesystem-access.rule.ts +74 -0
- package/src/scanners/runtime-monitor/rules/outbound-network.rule.ts +67 -0
- package/src/scanners/runtime-monitor/rules/process-spawn.rule.ts +58 -0
- package/src/scanners/runtime-monitor/rules/resource-anomaly.rule.ts +79 -0
- package/src/scanners/runtime-monitor/scanner.ts +27 -0
- package/src/scanners/secrets-exposure/index.ts +1 -0
- package/src/scanners/secrets-exposure/patterns/secret-signatures.ts +78 -0
- package/src/scanners/secrets-exposure/rules/entropy-check.rule.ts +79 -0
- package/src/scanners/secrets-exposure/rules/known-patterns.rule.ts +64 -0
- package/src/scanners/secrets-exposure/rules/response-echo.rule.ts +70 -0
- package/src/scanners/secrets-exposure/scanner.ts +25 -0
- package/src/types/config.types.ts +40 -0
- package/src/types/context.types.ts +25 -0
- package/src/types/finding.types.ts +36 -0
- package/src/types/index.ts +21 -0
- package/tsconfig.json +21 -0
- package/watchman.config.ts +16 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processSpawnRule = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
|
|
6
|
+
function isCodeFile(file) {
|
|
7
|
+
const dot = file.lastIndexOf('.');
|
|
8
|
+
return dot !== -1 && CODE_EXTENSIONS.has(file.slice(dot).toLowerCase());
|
|
9
|
+
}
|
|
10
|
+
const SPAWN_PATTERNS = [
|
|
11
|
+
{ pattern: /child_process.*(?:exec|execSync|spawn|spawnSync|fork)\s*\(/g, label: 'child_process' },
|
|
12
|
+
{ pattern: /\bexec\s*\(\s*['"`]/g, label: 'exec-string' },
|
|
13
|
+
{ pattern: /\beval\s*\(\s*[^)]/g, label: 'eval' },
|
|
14
|
+
{ pattern: /new\s+Function\s*\(/g, label: 'Function-constructor' },
|
|
15
|
+
{ pattern: /child_process.*\bexec\s*\(\s*(?:req\.|params\.|query\.|body\.)/g, label: 'user-input-exec' },
|
|
16
|
+
{ pattern: /\.exec\s*\(\s*`[^`]*\$\{/g, label: 'template-exec' },
|
|
17
|
+
];
|
|
18
|
+
exports.processSpawnRule = {
|
|
19
|
+
id: 'process-spawn',
|
|
20
|
+
name: 'Process Spawn Detection',
|
|
21
|
+
description: 'Flags shell command execution and dynamic code evaluation patterns',
|
|
22
|
+
async run(ctx) {
|
|
23
|
+
const codeFiles = ctx.files.filter(isCodeFile);
|
|
24
|
+
for (const file of codeFiles) {
|
|
25
|
+
let content;
|
|
26
|
+
try {
|
|
27
|
+
content = await (0, promises_1.readFile)(file, 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const lines = content.split('\n');
|
|
33
|
+
for (let i = 0; i < lines.length; i++) {
|
|
34
|
+
const line = lines[i];
|
|
35
|
+
for (const { pattern, label } of SPAWN_PATTERNS) {
|
|
36
|
+
pattern.lastIndex = 0;
|
|
37
|
+
if (pattern.test(line)) {
|
|
38
|
+
const isUserInput = label === 'user-input-exec' || label === 'template-exec';
|
|
39
|
+
ctx.addFinding({
|
|
40
|
+
rule: 'process-spawn',
|
|
41
|
+
severity: isUserInput ? 'critical' : 'medium',
|
|
42
|
+
message: `Process spawn/eval detected: ${label}`,
|
|
43
|
+
location: { file, line: i + 1 },
|
|
44
|
+
evidence: line.trim().slice(0, 200),
|
|
45
|
+
suggestion: isUserInput
|
|
46
|
+
? 'CRITICAL: User input flows into shell execution. This is a command injection vulnerability.'
|
|
47
|
+
: 'Review whether this shell execution is necessary. Prefer native Node.js APIs.',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=process-spawn.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-spawn.rule.js","sourceRoot":"","sources":["../../../../src/scanners/runtime-monitor/rules/process-spawn.rule.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAG5C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,cAAc,GAAG;IACrB,EAAE,OAAO,EAAE,6DAA6D,EAAE,KAAK,EAAE,eAAe,EAAE;IAClG,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,aAAa,EAAE;IACzD,EAAE,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAE;IACjD,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAClE,EAAE,OAAO,EAAE,iEAAiE,EAAE,KAAK,EAAE,iBAAiB,EAAE;IACxG,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,eAAe,EAAE;CACjE,CAAC;AAEW,QAAA,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,oEAAoE;IAEjF,KAAK,CAAC,GAAG,CAAC,GAAgB;QACxB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,cAAc,EAAE,CAAC;oBAChD,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;oBACtB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,MAAM,WAAW,GAAG,KAAK,KAAK,iBAAiB,IAAI,KAAK,KAAK,eAAe,CAAC;wBAC7E,GAAG,CAAC,UAAU,CAAC;4BACb,IAAI,EAAE,eAAe;4BACrB,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;4BAC7C,OAAO,EAAE,gCAAgC,KAAK,EAAE;4BAChD,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;4BAC/B,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;4BACnC,UAAU,EAAE,WAAW;gCACrB,CAAC,CAAC,6FAA6F;gCAC/F,CAAC,CAAC,+EAA+E;yBACpF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-anomaly.rule.d.ts","sourceRoot":"","sources":["../../../../src/scanners/runtime-monitor/rules/resource-anomaly.rule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,yBAAyB,CAAC;AA0CjE,eAAO,MAAM,mBAAmB,EAAE,IAmCjC,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resourceAnomalyRule = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
|
|
6
|
+
function isCodeFile(file) {
|
|
7
|
+
const dot = file.lastIndexOf('.');
|
|
8
|
+
return dot !== -1 && CODE_EXTENSIONS.has(file.slice(dot).toLowerCase());
|
|
9
|
+
}
|
|
10
|
+
const ANOMALY_PATTERNS = [
|
|
11
|
+
{
|
|
12
|
+
pattern: /while\s*\(\s*true\s*\)/g,
|
|
13
|
+
label: 'infinite-loop',
|
|
14
|
+
severity: 'medium',
|
|
15
|
+
message: 'Infinite loop detected — potential denial of service',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /setInterval\s*\([^,]+,\s*\d{1,3}\s*\)/g,
|
|
19
|
+
label: 'tight-interval',
|
|
20
|
+
severity: 'medium',
|
|
21
|
+
message: 'Very short setInterval (< 1s) — potential resource exhaustion',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
pattern: /Buffer\.alloc(?:Unsafe)?\s*\(\s*(?:\d{8,}|[a-zA-Z_$][\w$]*\s*\*\s*[a-zA-Z_$][\w$]*)\s*\)/g,
|
|
25
|
+
label: 'large-buffer',
|
|
26
|
+
severity: 'medium',
|
|
27
|
+
message: 'Large buffer allocation — potential memory exhaustion attack',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
pattern: /new\s+RegExp\s*\(\s*(?:req\.|params\.|query\.|body\.|args\.)/g,
|
|
31
|
+
label: 'user-regex',
|
|
32
|
+
severity: 'high',
|
|
33
|
+
message: 'User input used in RegExp constructor — ReDoS vulnerability',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
pattern: /crypto\.(?:pbkdf2|scrypt).*(?:iterations|cost)\s*[:=]\s*(?:req\.|params\.|query\.|body\.)/g,
|
|
37
|
+
label: 'user-controlled-crypto',
|
|
38
|
+
severity: 'high',
|
|
39
|
+
message: 'User input controls crypto parameters — potential algorithmic complexity attack',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
exports.resourceAnomalyRule = {
|
|
43
|
+
id: 'resource-anomaly',
|
|
44
|
+
name: 'Resource Anomaly Detection',
|
|
45
|
+
description: 'Detects patterns that could cause resource exhaustion or denial of service',
|
|
46
|
+
async run(ctx) {
|
|
47
|
+
const codeFiles = ctx.files.filter(isCodeFile);
|
|
48
|
+
for (const file of codeFiles) {
|
|
49
|
+
let content;
|
|
50
|
+
try {
|
|
51
|
+
content = await (0, promises_1.readFile)(file, 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const lines = content.split('\n');
|
|
57
|
+
for (let i = 0; i < lines.length; i++) {
|
|
58
|
+
const line = lines[i];
|
|
59
|
+
for (const anomaly of ANOMALY_PATTERNS) {
|
|
60
|
+
anomaly.pattern.lastIndex = 0;
|
|
61
|
+
if (anomaly.pattern.test(line)) {
|
|
62
|
+
ctx.addFinding({
|
|
63
|
+
rule: 'resource-anomaly',
|
|
64
|
+
severity: anomaly.severity,
|
|
65
|
+
message: anomaly.message,
|
|
66
|
+
location: { file, line: i + 1 },
|
|
67
|
+
evidence: line.trim().slice(0, 200),
|
|
68
|
+
suggestion: 'Review this pattern for potential resource exhaustion.',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=resource-anomaly.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-anomaly.rule.js","sourceRoot":"","sources":["../../../../src/scanners/runtime-monitor/rules/resource-anomaly.rule.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAG5C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,gBAAgB,GAAG;IACvB;QACE,OAAO,EAAE,yBAAyB;QAClC,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,QAAiB;QAC3B,OAAO,EAAE,sDAAsD;KAChE;IACD;QACE,OAAO,EAAE,wCAAwC;QACjD,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EAAE,QAAiB;QAC3B,OAAO,EAAE,+DAA+D;KACzE;IACD;QACE,OAAO,EAAE,2FAA2F;QACpG,KAAK,EAAE,cAAc;QACrB,QAAQ,EAAE,QAAiB;QAC3B,OAAO,EAAE,8DAA8D;KACxE;IACD;QACE,OAAO,EAAE,+DAA+D;QACxE,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,MAAe;QACzB,OAAO,EAAE,6DAA6D;KACvE;IACD;QACE,OAAO,EAAE,4FAA4F;QACrG,KAAK,EAAE,wBAAwB;QAC/B,QAAQ,EAAE,MAAe;QACzB,OAAO,EAAE,iFAAiF;KAC3F;CACF,CAAC;AAEW,QAAA,mBAAmB,GAAS;IACvC,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,4BAA4B;IAClC,WAAW,EAAE,4EAA4E;IAEzF,KAAK,CAAC,GAAG,CAAC,GAAgB;QACxB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;oBACvC,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;oBAC9B,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC/B,GAAG,CAAC,UAAU,CAAC;4BACb,IAAI,EAAE,kBAAkB;4BACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;4BAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;4BACxB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;4BAC/B,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;4BACnC,UAAU,EAAE,wDAAwD;yBACrE,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/scanners/runtime-monitor/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,sBAAsB,CAAC;AAavE,eAAO,MAAM,qBAAqB,EAAE,OAanC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runtimeMonitorScanner = void 0;
|
|
4
|
+
const process_spawn_rule_js_1 = require("./rules/process-spawn.rule.js");
|
|
5
|
+
const filesystem_access_rule_js_1 = require("./rules/filesystem-access.rule.js");
|
|
6
|
+
const outbound_network_rule_js_1 = require("./rules/outbound-network.rule.js");
|
|
7
|
+
const resource_anomaly_rule_js_1 = require("./rules/resource-anomaly.rule.js");
|
|
8
|
+
const rules = [
|
|
9
|
+
process_spawn_rule_js_1.processSpawnRule,
|
|
10
|
+
filesystem_access_rule_js_1.filesystemAccessRule,
|
|
11
|
+
outbound_network_rule_js_1.outboundNetworkRule,
|
|
12
|
+
resource_anomaly_rule_js_1.resourceAnomalyRule,
|
|
13
|
+
];
|
|
14
|
+
exports.runtimeMonitorScanner = {
|
|
15
|
+
id: 'runtime-monitor',
|
|
16
|
+
name: 'Runtime Monitor',
|
|
17
|
+
description: 'Detects suspicious runtime behavior: process spawning, filesystem access, network calls, resource anomalies',
|
|
18
|
+
rules,
|
|
19
|
+
async scan(ctx) {
|
|
20
|
+
for (const rule of rules) {
|
|
21
|
+
const ruleConfig = ctx.scannerConfig.rules?.[rule.id];
|
|
22
|
+
if (ruleConfig?.enabled === false)
|
|
23
|
+
continue;
|
|
24
|
+
await rule.run(ctx);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../src/scanners/runtime-monitor/scanner.ts"],"names":[],"mappings":";;;AACA,yEAAiE;AACjE,iFAAyE;AACzE,+EAAuE;AACvE,+EAAuE;AAEvE,MAAM,KAAK,GAAW;IACpB,wCAAgB;IAChB,gDAAoB;IACpB,8CAAmB;IACnB,8CAAmB;CACpB,CAAC;AAEW,QAAA,qBAAqB,GAAY;IAC5C,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,6GAA6G;IAC1H,KAAK;IAEL,KAAK,CAAC,IAAI,CAAC,GAAgB;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtD,IAAI,UAAU,EAAE,OAAO,KAAK,KAAK;gBAAE,SAAS;YAC5C,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/secrets-exposure/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secretsExposureScanner = void 0;
|
|
4
|
+
var scanner_js_1 = require("./scanner.js");
|
|
5
|
+
Object.defineProperty(exports, "secretsExposureScanner", { enumerable: true, get: function () { return scanner_js_1.secretsExposureScanner; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/secrets-exposure/index.ts"],"names":[],"mappings":";;;AAAA,2CAAsD;AAA7C,oHAAA,sBAAsB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-signatures.d.ts","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/patterns/secret-signatures.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAuE9C,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SECRET_SIGNATURES = void 0;
|
|
4
|
+
exports.SECRET_SIGNATURES = [
|
|
5
|
+
{
|
|
6
|
+
pattern: /sk-ant-api\d{2}-[A-Za-z0-9_-]{20,}/,
|
|
7
|
+
label: 'anthropic-api-key',
|
|
8
|
+
description: 'Anthropic API key',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
pattern: /sk-[A-Za-z0-9]{48,}/,
|
|
12
|
+
label: 'openai-api-key',
|
|
13
|
+
description: 'OpenAI API key',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
pattern: /ghp_[A-Za-z0-9]{36,}/,
|
|
17
|
+
label: 'github-pat',
|
|
18
|
+
description: 'GitHub personal access token',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
pattern: /gho_[A-Za-z0-9]{36,}/,
|
|
22
|
+
label: 'github-oauth',
|
|
23
|
+
description: 'GitHub OAuth access token',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
pattern: /github_pat_[A-Za-z0-9_]{20,}/,
|
|
27
|
+
label: 'github-fine-grained-pat',
|
|
28
|
+
description: 'GitHub fine-grained personal access token',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
pattern: /xoxb-[0-9]{10,}-[0-9]{10,}-[A-Za-z0-9]{24,}/,
|
|
32
|
+
label: 'slack-bot-token',
|
|
33
|
+
description: 'Slack bot token',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
pattern: /xoxp-[0-9]{10,}-[0-9]{10,}-[A-Za-z0-9]{24,}/,
|
|
37
|
+
label: 'slack-user-token',
|
|
38
|
+
description: 'Slack user token',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
pattern: /eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/,
|
|
42
|
+
label: 'supabase-jwt',
|
|
43
|
+
description: 'Supabase JWT (anon or service_role key)',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern: /AKIA[0-9A-Z]{16}/,
|
|
47
|
+
label: 'aws-access-key',
|
|
48
|
+
description: 'AWS access key ID',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
pattern: /npm_[A-Za-z0-9]{36,}/,
|
|
52
|
+
label: 'npm-token',
|
|
53
|
+
description: 'npm access token',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
pattern: /sk_live_[A-Za-z0-9]{24,}/,
|
|
57
|
+
label: 'stripe-secret-key',
|
|
58
|
+
description: 'Stripe secret key',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /sq0csp-[A-Za-z0-9_-]{43}/,
|
|
62
|
+
label: 'square-oauth-secret',
|
|
63
|
+
description: 'Square OAuth secret',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pattern: /SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}/,
|
|
67
|
+
label: 'sendgrid-api-key',
|
|
68
|
+
description: 'SendGrid API key',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
pattern: /-----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----/,
|
|
72
|
+
label: 'private-key',
|
|
73
|
+
description: 'Private key file',
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
//# sourceMappingURL=secret-signatures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-signatures.js","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/patterns/secret-signatures.ts"],"names":[],"mappings":";;;AAMa,QAAA,iBAAiB,GAAsB;IAClD;QACE,OAAO,EAAE,oCAAoC;QAC7C,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,mBAAmB;KACjC;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,gBAAgB;KAC9B;IACD;QACE,OAAO,EAAE,sBAAsB;QAC/B,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,OAAO,EAAE,sBAAsB;QAC/B,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,2BAA2B;KACzC;IACD;QACE,OAAO,EAAE,8BAA8B;QACvC,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,2CAA2C;KACzD;IACD;QACE,OAAO,EAAE,6CAA6C;QACtD,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,iBAAiB;KAC/B;IACD;QACE,OAAO,EAAE,6CAA6C;QACtD,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,OAAO,EAAE,8EAA8E;QACvF,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,yCAAyC;KACvD;IACD;QACE,OAAO,EAAE,kBAAkB;QAC3B,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,mBAAmB;KACjC;IACD;QACE,OAAO,EAAE,sBAAsB;QAC/B,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,OAAO,EAAE,0BAA0B;QACnC,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,mBAAmB;KACjC;IACD;QACE,OAAO,EAAE,0BAA0B;QACnC,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,qBAAqB;KACnC;IACD;QACE,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,OAAO,EAAE,6CAA6C;QACtD,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,kBAAkB;KAChC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entropy-check.rule.d.ts","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/entropy-check.rule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,yBAAyB,CAAC;AAiCjE,eAAO,MAAM,gBAAgB,EAAE,IA2C9B,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.entropyCheckRule = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const CODE_EXTENSIONS = new Set([
|
|
7
|
+
'.ts', '.tsx', '.js', '.jsx', '.json', '.yaml', '.yml',
|
|
8
|
+
'.toml', '.cfg', '.ini', '.env',
|
|
9
|
+
]);
|
|
10
|
+
function isTargetFile(file) {
|
|
11
|
+
const dot = file.lastIndexOf('.');
|
|
12
|
+
if (dot === -1)
|
|
13
|
+
return (0, node_path_1.basename)(file).startsWith('.env');
|
|
14
|
+
return CODE_EXTENSIONS.has(file.slice(dot).toLowerCase());
|
|
15
|
+
}
|
|
16
|
+
function shannonEntropy(s) {
|
|
17
|
+
if (s.length === 0)
|
|
18
|
+
return 0;
|
|
19
|
+
const freq = new Map();
|
|
20
|
+
for (const ch of s) {
|
|
21
|
+
freq.set(ch, (freq.get(ch) ?? 0) + 1);
|
|
22
|
+
}
|
|
23
|
+
let entropy = 0;
|
|
24
|
+
for (const count of freq.values()) {
|
|
25
|
+
const p = count / s.length;
|
|
26
|
+
entropy -= p * Math.log2(p);
|
|
27
|
+
}
|
|
28
|
+
return entropy;
|
|
29
|
+
}
|
|
30
|
+
// Match assignment-like patterns: KEY=value, "key": "value", key: value
|
|
31
|
+
const ASSIGNMENT_PATTERN = /(?:['"]?(?:key|token|secret|password|api_key|apikey|auth|credential|private)['"_\s]*[:=]\s*['"]?)([A-Za-z0-9+/=_-]{16,})/gi;
|
|
32
|
+
const ENTROPY_THRESHOLD = 4.5;
|
|
33
|
+
const MIN_LENGTH = 16;
|
|
34
|
+
exports.entropyCheckRule = {
|
|
35
|
+
id: 'entropy-check',
|
|
36
|
+
name: 'High Entropy String Detection',
|
|
37
|
+
description: 'Flags high-entropy strings in assignment contexts that may be hardcoded secrets',
|
|
38
|
+
async run(ctx) {
|
|
39
|
+
for (const file of ctx.files) {
|
|
40
|
+
if (!isTargetFile(file))
|
|
41
|
+
continue;
|
|
42
|
+
let content;
|
|
43
|
+
try {
|
|
44
|
+
content = await (0, promises_1.readFile)(file, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const lines = content.split('\n');
|
|
50
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51
|
+
const line = lines[i];
|
|
52
|
+
if (/^\s*#/.test(line) || /^\s*\/\//.test(line))
|
|
53
|
+
continue;
|
|
54
|
+
ASSIGNMENT_PATTERN.lastIndex = 0;
|
|
55
|
+
let match;
|
|
56
|
+
while ((match = ASSIGNMENT_PATTERN.exec(line)) !== null) {
|
|
57
|
+
const value = match[1];
|
|
58
|
+
if (value.length < MIN_LENGTH)
|
|
59
|
+
continue;
|
|
60
|
+
const entropy = shannonEntropy(value);
|
|
61
|
+
if (entropy >= ENTROPY_THRESHOLD) {
|
|
62
|
+
ctx.addFinding({
|
|
63
|
+
rule: 'entropy-check',
|
|
64
|
+
severity: 'high',
|
|
65
|
+
message: `High-entropy string (${entropy.toFixed(2)} bits) in secret-like assignment`,
|
|
66
|
+
location: { file, line: i + 1 },
|
|
67
|
+
evidence: value.slice(0, 8) + '...[REDACTED]',
|
|
68
|
+
suggestion: 'This looks like a hardcoded credential. Move it to an environment variable.',
|
|
69
|
+
metadata: { entropy },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=entropy-check.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entropy-check.rule.js","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/entropy-check.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-patterns.rule.d.ts","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/known-patterns.rule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,yBAAyB,CAAC;AAqBjE,eAAO,MAAM,iBAAiB,EAAE,IAwC/B,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.knownPatternsRule = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const secret_signatures_js_1 = require("../patterns/secret-signatures.js");
|
|
7
|
+
const SKIP_FILES = new Set([
|
|
8
|
+
'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
|
|
9
|
+
'.gitignore', '.dockerignore',
|
|
10
|
+
]);
|
|
11
|
+
const BINARY_EXTENSIONS = new Set([
|
|
12
|
+
'.png', '.jpg', '.jpeg', '.gif', '.ico', '.woff', '.woff2',
|
|
13
|
+
'.ttf', '.eot', '.zip', '.tar', '.gz', '.pdf',
|
|
14
|
+
]);
|
|
15
|
+
function shouldSkip(file) {
|
|
16
|
+
const name = (0, node_path_1.basename)(file);
|
|
17
|
+
if (SKIP_FILES.has(name))
|
|
18
|
+
return true;
|
|
19
|
+
const dot = file.lastIndexOf('.');
|
|
20
|
+
if (dot !== -1 && BINARY_EXTENSIONS.has(file.slice(dot).toLowerCase()))
|
|
21
|
+
return true;
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
exports.knownPatternsRule = {
|
|
25
|
+
id: 'known-patterns',
|
|
26
|
+
name: 'Known Secret Patterns',
|
|
27
|
+
description: 'Matches known API key and credential patterns in source files',
|
|
28
|
+
async run(ctx) {
|
|
29
|
+
for (const file of ctx.files) {
|
|
30
|
+
if (shouldSkip(file))
|
|
31
|
+
continue;
|
|
32
|
+
let content;
|
|
33
|
+
try {
|
|
34
|
+
content = await (0, promises_1.readFile)(file, 'utf-8');
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const lines = content.split('\n');
|
|
40
|
+
for (let i = 0; i < lines.length; i++) {
|
|
41
|
+
const line = lines[i];
|
|
42
|
+
// Skip lines that are env template placeholders
|
|
43
|
+
if (/^\s*#/.test(line) || /=\s*$/.test(line) || /YOUR_.*_HERE/.test(line)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
for (const sig of secret_signatures_js_1.SECRET_SIGNATURES) {
|
|
47
|
+
if (sig.pattern.test(line)) {
|
|
48
|
+
ctx.addFinding({
|
|
49
|
+
rule: 'known-patterns',
|
|
50
|
+
severity: 'critical',
|
|
51
|
+
message: `${sig.description} found in source code`,
|
|
52
|
+
location: { file, line: i + 1 },
|
|
53
|
+
evidence: line.trim().slice(0, 40) + '...[REDACTED]',
|
|
54
|
+
suggestion: `Move this ${sig.label} to an environment variable. Never commit secrets to source control.`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=known-patterns.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-patterns.rule.js","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/known-patterns.rule.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAC5C,yCAAqC;AAErC,2EAAqE;AAErE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,mBAAmB,EAAE,WAAW,EAAE,gBAAgB;IAClD,YAAY,EAAE,eAAe;CAC9B,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;IAC1D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAC9C,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,IAAI,GAAG,IAAA,oBAAQ,EAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAEY,QAAA,iBAAiB,GAAS;IACrC,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,+DAA+D;IAE5E,KAAK,CAAC,GAAG,CAAC,GAAgB;QACxB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE/B,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAEtB,gDAAgD;gBAChD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1E,SAAS;gBACX,CAAC;gBAED,KAAK,MAAM,GAAG,IAAI,wCAAiB,EAAE,CAAC;oBACpC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC3B,GAAG,CAAC,UAAU,CAAC;4BACb,IAAI,EAAE,gBAAgB;4BACtB,QAAQ,EAAE,UAAU;4BACpB,OAAO,EAAE,GAAG,GAAG,CAAC,WAAW,uBAAuB;4BAClD,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;4BAC/B,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,eAAe;4BACpD,UAAU,EAAE,aAAa,GAAG,CAAC,KAAK,sEAAsE;yBACzG,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-echo.rule.d.ts","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/response-echo.rule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,yBAAyB,CAAC;AAiCjE,eAAO,MAAM,gBAAgB,EAAE,IAmC9B,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.responseEchoRule = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
|
|
6
|
+
function isCodeFile(file) {
|
|
7
|
+
const dot = file.lastIndexOf('.');
|
|
8
|
+
return dot !== -1 && CODE_EXTENSIONS.has(file.slice(dot).toLowerCase());
|
|
9
|
+
}
|
|
10
|
+
// Patterns where env vars are passed into responses, logs, or error messages
|
|
11
|
+
const ECHO_PATTERNS = [
|
|
12
|
+
{
|
|
13
|
+
pattern: /(?:res\.(?:json|send|write)|console\.(?:log|error|warn))\s*\([^)]*process\.env\.[A-Z_]*(?:KEY|SECRET|TOKEN|PASSWORD)/g,
|
|
14
|
+
label: 'env-var-in-response',
|
|
15
|
+
description: 'Environment variable containing a secret echoed in response or log',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /(?:JSON\.stringify|toString)\s*\([^)]*process\.env\b/g,
|
|
19
|
+
label: 'env-serialization',
|
|
20
|
+
description: 'process.env serialized — may leak all environment variables',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /(?:res\.(?:json|send))\s*\(\s*\{\s*\.\.\.(?:process\.env|req\.)/g,
|
|
24
|
+
label: 'spread-leak',
|
|
25
|
+
description: 'Object spread may leak sensitive fields into response',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /error\.stack|err\.stack/g,
|
|
29
|
+
label: 'stack-trace-exposure',
|
|
30
|
+
description: 'Stack trace exposed — may reveal file paths and internal structure',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
exports.responseEchoRule = {
|
|
34
|
+
id: 'response-echo',
|
|
35
|
+
name: 'Response Echo Detection',
|
|
36
|
+
description: 'Detects secrets or sensitive data being echoed in HTTP responses or logs',
|
|
37
|
+
async run(ctx) {
|
|
38
|
+
const codeFiles = ctx.files.filter(isCodeFile);
|
|
39
|
+
for (const file of codeFiles) {
|
|
40
|
+
let content;
|
|
41
|
+
try {
|
|
42
|
+
content = await (0, promises_1.readFile)(file, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const lines = content.split('\n');
|
|
48
|
+
for (let i = 0; i < lines.length; i++) {
|
|
49
|
+
const line = lines[i];
|
|
50
|
+
for (const { pattern, label, description } of ECHO_PATTERNS) {
|
|
51
|
+
pattern.lastIndex = 0;
|
|
52
|
+
if (pattern.test(line)) {
|
|
53
|
+
ctx.addFinding({
|
|
54
|
+
rule: 'response-echo',
|
|
55
|
+
severity: label === 'stack-trace-exposure' ? 'medium' : 'high',
|
|
56
|
+
message: description,
|
|
57
|
+
location: { file, line: i + 1 },
|
|
58
|
+
evidence: line.trim().slice(0, 200),
|
|
59
|
+
suggestion: 'Never echo secrets or full env objects in responses. Sanitize output.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=response-echo.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-echo.rule.js","sourceRoot":"","sources":["../../../../src/scanners/secrets-exposure/rules/response-echo.rule.ts"],"names":[],"mappings":";;;AAAA,+CAA4C;AAG5C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,6EAA6E;AAC7E,MAAM,aAAa,GAAG;IACpB;QACE,OAAO,EAAE,uHAAuH;QAChI,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,oEAAoE;KAClF;IACD;QACE,OAAO,EAAE,uDAAuD;QAChE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,6DAA6D;KAC3E;IACD;QACE,OAAO,EAAE,kEAAkE;QAC3E,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,uDAAuD;KACrE;IACD;QACE,OAAO,EAAE,0BAA0B;QACnC,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,oEAAoE;KAClF;CACF,CAAC;AAEW,QAAA,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,0EAA0E;IAEvF,KAAK,CAAC,GAAG,CAAC,GAAgB;QACxB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,aAAa,EAAE,CAAC;oBAC5D,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;oBACtB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,GAAG,CAAC,UAAU,CAAC;4BACb,IAAI,EAAE,eAAe;4BACrB,QAAQ,EAAE,KAAK,KAAK,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;4BAC9D,OAAO,EAAE,WAAW;4BACpB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;4BAC/B,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;4BACnC,UAAU,EAAE,uEAAuE;yBACpF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/scanners/secrets-exposure/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,sBAAsB,CAAC;AAWvE,eAAO,MAAM,sBAAsB,EAAE,OAapC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secretsExposureScanner = void 0;
|
|
4
|
+
const entropy_check_rule_js_1 = require("./rules/entropy-check.rule.js");
|
|
5
|
+
const known_patterns_rule_js_1 = require("./rules/known-patterns.rule.js");
|
|
6
|
+
const response_echo_rule_js_1 = require("./rules/response-echo.rule.js");
|
|
7
|
+
const rules = [
|
|
8
|
+
known_patterns_rule_js_1.knownPatternsRule,
|
|
9
|
+
entropy_check_rule_js_1.entropyCheckRule,
|
|
10
|
+
response_echo_rule_js_1.responseEchoRule,
|
|
11
|
+
];
|
|
12
|
+
exports.secretsExposureScanner = {
|
|
13
|
+
id: 'secrets-exposure',
|
|
14
|
+
name: 'Secrets Exposure',
|
|
15
|
+
description: 'Detects hardcoded secrets, high-entropy strings, and response echo vulnerabilities',
|
|
16
|
+
rules,
|
|
17
|
+
async scan(ctx) {
|
|
18
|
+
for (const rule of rules) {
|
|
19
|
+
const ruleConfig = ctx.scannerConfig.rules?.[rule.id];
|
|
20
|
+
if (ruleConfig?.enabled === false)
|
|
21
|
+
continue;
|
|
22
|
+
await rule.run(ctx);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../src/scanners/secrets-exposure/scanner.ts"],"names":[],"mappings":";;;AACA,yEAAiE;AACjE,2EAAmE;AACnE,yEAAiE;AAEjE,MAAM,KAAK,GAAW;IACpB,0CAAiB;IACjB,wCAAgB;IAChB,wCAAgB;CACjB,CAAC;AAEW,QAAA,sBAAsB,GAAY;IAC7C,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,oFAAoF;IACjG,KAAK;IAEL,KAAK,CAAC,IAAI,CAAC,GAAgB;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtD,IAAI,UAAU,EAAE,OAAO,KAAK,KAAK;gBAAE,SAAS;YAC5C,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
2
|
+
export type ScannerId = 'ai-tool-integrity' | 'secrets-exposure' | 'dependency-integrity' | 'runtime-monitor';
|
|
3
|
+
export interface RuleConfig {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
severity?: Severity;
|
|
6
|
+
options?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface ScannerConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
rules?: Record<string, RuleConfig>;
|
|
11
|
+
}
|
|
12
|
+
export interface WatchmanConfig {
|
|
13
|
+
projectRoot: string;
|
|
14
|
+
scanners: Partial<Record<ScannerId, ScannerConfig>>;
|
|
15
|
+
include?: string[];
|
|
16
|
+
exclude?: string[];
|
|
17
|
+
failOn?: Severity;
|
|
18
|
+
quiet?: boolean;
|
|
19
|
+
maxFindings?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare const DEFAULT_CONFIG: Omit<WatchmanConfig, 'projectRoot'>;
|
|
22
|
+
//# sourceMappingURL=config.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.types.d.ts","sourceRoot":"","sources":["../../src/types/config.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvE,MAAM,MAAM,SAAS,GACjB,mBAAmB,GACnB,kBAAkB,GAClB,sBAAsB,GACtB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,aAAa,CAU9D,CAAC"}
|