@elliotllliu/agent-shield 0.3.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/LICENSE +21 -0
- package/README.md +297 -0
- package/README.zh-CN.md +130 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +265 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +91 -0
- package/dist/config.js.map +1 -0
- package/dist/discover.d.ts +9 -0
- package/dist/discover.js +143 -0
- package/dist/discover.js.map +1 -0
- package/dist/llm/anthropic.d.ts +10 -0
- package/dist/llm/anthropic.js +67 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/index.d.ts +10 -0
- package/dist/llm/index.js +41 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/ollama.d.ts +9 -0
- package/dist/llm/ollama.js +61 -0
- package/dist/llm/ollama.js.map +1 -0
- package/dist/llm/openai.d.ts +10 -0
- package/dist/llm/openai.js +66 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/prompt.d.ts +3 -0
- package/dist/llm/prompt.js +31 -0
- package/dist/llm/prompt.js.map +1 -0
- package/dist/llm/types.d.ts +23 -0
- package/dist/llm/types.js +3 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/llm-analyzer.d.ts +13 -0
- package/dist/llm-analyzer.js +169 -0
- package/dist/llm-analyzer.js.map +1 -0
- package/dist/reporter/badge.d.ts +7 -0
- package/dist/reporter/badge.js +50 -0
- package/dist/reporter/badge.js.map +1 -0
- package/dist/reporter/json.d.ts +3 -0
- package/dist/reporter/json.js +5 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/reporter/terminal.d.ts +2 -0
- package/dist/reporter/terminal.js +64 -0
- package/dist/reporter/terminal.js.map +1 -0
- package/dist/rules/backdoor.d.ts +2 -0
- package/dist/rules/backdoor.js +57 -0
- package/dist/rules/backdoor.js.map +1 -0
- package/dist/rules/credential-hardcode.d.ts +2 -0
- package/dist/rules/credential-hardcode.js +57 -0
- package/dist/rules/credential-hardcode.js.map +1 -0
- package/dist/rules/crypto-mining.d.ts +2 -0
- package/dist/rules/crypto-mining.js +41 -0
- package/dist/rules/crypto-mining.js.map +1 -0
- package/dist/rules/data-exfil.d.ts +2 -0
- package/dist/rules/data-exfil.js +61 -0
- package/dist/rules/data-exfil.js.map +1 -0
- package/dist/rules/env-leak.d.ts +2 -0
- package/dist/rules/env-leak.js +43 -0
- package/dist/rules/env-leak.js.map +1 -0
- package/dist/rules/excessive-perms.d.ts +2 -0
- package/dist/rules/excessive-perms.js +50 -0
- package/dist/rules/excessive-perms.js.map +1 -0
- package/dist/rules/hidden-files.d.ts +2 -0
- package/dist/rules/hidden-files.js +52 -0
- package/dist/rules/hidden-files.js.map +1 -0
- package/dist/rules/index.d.ts +5 -0
- package/dist/rules/index.js +53 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/mcp-manifest.d.ts +2 -0
- package/dist/rules/mcp-manifest.js +270 -0
- package/dist/rules/mcp-manifest.js.map +1 -0
- package/dist/rules/network-ssrf.d.ts +2 -0
- package/dist/rules/network-ssrf.js +51 -0
- package/dist/rules/network-ssrf.js.map +1 -0
- package/dist/rules/obfuscation.d.ts +2 -0
- package/dist/rules/obfuscation.js +51 -0
- package/dist/rules/obfuscation.js.map +1 -0
- package/dist/rules/phone-home.d.ts +2 -0
- package/dist/rules/phone-home.js +38 -0
- package/dist/rules/phone-home.js.map +1 -0
- package/dist/rules/privilege.d.ts +2 -0
- package/dist/rules/privilege.js +111 -0
- package/dist/rules/privilege.js.map +1 -0
- package/dist/rules/prompt-injection.d.ts +2 -0
- package/dist/rules/prompt-injection.js +323 -0
- package/dist/rules/prompt-injection.js.map +1 -0
- package/dist/rules/reverse-shell.d.ts +2 -0
- package/dist/rules/reverse-shell.js +53 -0
- package/dist/rules/reverse-shell.js.map +1 -0
- package/dist/rules/sensitive-read.d.ts +2 -0
- package/dist/rules/sensitive-read.js +53 -0
- package/dist/rules/sensitive-read.js.map +1 -0
- package/dist/rules/skill-risks.d.ts +2 -0
- package/dist/rules/skill-risks.js +148 -0
- package/dist/rules/skill-risks.js.map +1 -0
- package/dist/rules/supply-chain.d.ts +6 -0
- package/dist/rules/supply-chain.js +105 -0
- package/dist/rules/supply-chain.js.map +1 -0
- package/dist/rules/tool-shadowing.d.ts +2 -0
- package/dist/rules/tool-shadowing.js +129 -0
- package/dist/rules/tool-shadowing.js.map +1 -0
- package/dist/rules/toxic-flow.d.ts +2 -0
- package/dist/rules/toxic-flow.js +160 -0
- package/dist/rules/toxic-flow.js.map +1 -0
- package/dist/rules/typosquatting.d.ts +2 -0
- package/dist/rules/typosquatting.js +56 -0
- package/dist/rules/typosquatting.js.map +1 -0
- package/dist/scanner/files.d.ts +5 -0
- package/dist/scanner/files.js +105 -0
- package/dist/scanner/files.js.map +1 -0
- package/dist/scanner/index.d.ts +6 -0
- package/dist/scanner/index.js +198 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/score.d.ts +14 -0
- package/dist/score.js +35 -0
- package/dist/score.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/yaml-simple.d.ts +6 -0
- package/dist/yaml-simple.js +98 -0
- package/dist/yaml-simple.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { riskLabel } from "../score.js";
|
|
3
|
+
const SEVERITY_ICON = {
|
|
4
|
+
critical: chalk.red("🔴 CRITICAL"),
|
|
5
|
+
warning: chalk.yellow("🟡 WARNING"),
|
|
6
|
+
info: chalk.blue("🟢 INFO"),
|
|
7
|
+
};
|
|
8
|
+
const SEVERITY_LINE = {
|
|
9
|
+
critical: chalk.red,
|
|
10
|
+
warning: chalk.yellow,
|
|
11
|
+
info: chalk.dim,
|
|
12
|
+
};
|
|
13
|
+
export function printReport(result) {
|
|
14
|
+
const { target, filesScanned, linesScanned, findings, score, duration } = result;
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(chalk.bold("🛡️ AgentShield Security Report"));
|
|
17
|
+
console.log(chalk.dim(`📁 Scanned: ${target} (${filesScanned} files, ${formatLines(linesScanned)})`));
|
|
18
|
+
console.log();
|
|
19
|
+
// Group by severity
|
|
20
|
+
const bySeverity = groupBy(findings, (f) => f.severity);
|
|
21
|
+
for (const severity of ["critical", "warning", "info"]) {
|
|
22
|
+
const group = bySeverity[severity];
|
|
23
|
+
if (!group || group.length === 0)
|
|
24
|
+
continue;
|
|
25
|
+
console.log(`${SEVERITY_ICON[severity]} (${group.length})`);
|
|
26
|
+
for (let i = 0; i < group.length; i++) {
|
|
27
|
+
const f = group[i];
|
|
28
|
+
const prefix = i < group.length - 1 ? " ├─" : " └─";
|
|
29
|
+
const loc = f.line ? `${f.file}:${f.line}` : f.file;
|
|
30
|
+
const colorize = SEVERITY_LINE[f.severity] || chalk.white;
|
|
31
|
+
console.log(colorize(`${prefix} ${loc} — [${f.rule}] ${f.message}`));
|
|
32
|
+
if (f.possibleFalsePositive) {
|
|
33
|
+
const fpPrefix = i < group.length - 1 ? " │ " : " ";
|
|
34
|
+
console.log(chalk.dim(`${fpPrefix}⚠️ Likely false positive: ${f.falsePositiveReason}`));
|
|
35
|
+
}
|
|
36
|
+
if (f.evidence) {
|
|
37
|
+
const ePrefix = i < group.length - 1 ? " │ " : " ";
|
|
38
|
+
console.log(chalk.dim(`${ePrefix}${f.evidence}`));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
console.log();
|
|
42
|
+
}
|
|
43
|
+
// Score
|
|
44
|
+
const scoreColor = score >= 90 ? chalk.green : score >= 70 ? chalk.yellow : score >= 40 ? chalk.hex("#FF8800") : chalk.red;
|
|
45
|
+
console.log(scoreColor(`✅ Score: ${score}/100 (${riskLabel(score)})`));
|
|
46
|
+
console.log(chalk.dim(`⏱ ${duration}ms`));
|
|
47
|
+
console.log();
|
|
48
|
+
}
|
|
49
|
+
function formatLines(n) {
|
|
50
|
+
if (n >= 1000)
|
|
51
|
+
return `${(n / 1000).toFixed(1)}K lines`;
|
|
52
|
+
return `${n} lines`;
|
|
53
|
+
}
|
|
54
|
+
function groupBy(arr, fn) {
|
|
55
|
+
const result = {};
|
|
56
|
+
for (const item of arr) {
|
|
57
|
+
const key = fn(item);
|
|
58
|
+
if (!result[key])
|
|
59
|
+
result[key] = [];
|
|
60
|
+
result[key].push(item);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/reporter/terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: backdoor
|
|
3
|
+
* Detects eval(), new Function(), child_process.exec() with dynamic strings
|
|
4
|
+
*/
|
|
5
|
+
const BACKDOOR_PATTERNS = [
|
|
6
|
+
// JavaScript/TypeScript
|
|
7
|
+
{ pattern: /\beval\s*\(/, desc: "eval() with dynamic input", severity: "critical" },
|
|
8
|
+
{ pattern: /new\s+Function\s*\(/, desc: "new Function() constructor", severity: "critical" },
|
|
9
|
+
{ pattern: /child_process\s*\.\s*exec\s*\(/, desc: "child_process.exec() — use execFile instead", severity: "critical" },
|
|
10
|
+
{ pattern: /child_process\s*\.\s*spawn\s*\(.*\bshell\s*:\s*true/, desc: "spawn() with shell: true", severity: "critical" },
|
|
11
|
+
{ pattern: /execSync\s*\(\s*`/, desc: "execSync() with template literal", severity: "critical" },
|
|
12
|
+
{ pattern: /execSync\s*\(\s*[^"']/, desc: "execSync() with dynamic string", severity: "warning" },
|
|
13
|
+
{ pattern: /require\s*\(\s*[^"'`]/, desc: "dynamic require()", severity: "warning" },
|
|
14
|
+
{ pattern: /import\s*\(\s*[^"'`]/, desc: "dynamic import()", severity: "warning" },
|
|
15
|
+
// Python
|
|
16
|
+
{ pattern: /\bexec\s*\(\s*[^"']/, desc: "Python exec() with dynamic input", severity: "critical" },
|
|
17
|
+
{ pattern: /\bos\.system\s*\(/, desc: "os.system() — use subprocess.run instead", severity: "critical" },
|
|
18
|
+
{ pattern: /subprocess\.call\s*\(\s*[^[\]].*shell\s*=\s*True/, desc: "subprocess with shell=True", severity: "critical" },
|
|
19
|
+
{ pattern: /\b__import__\s*\(/, desc: "dynamic __import__()", severity: "warning" },
|
|
20
|
+
// Shell
|
|
21
|
+
{ pattern: /\$\(curl\s/, desc: "command substitution with curl", severity: "critical" },
|
|
22
|
+
{ pattern: /\beval\s+\$/, desc: "shell eval with variable", severity: "critical" },
|
|
23
|
+
{ pattern: /bash\s+-c\s+\$/, desc: "bash -c with variable", severity: "critical" },
|
|
24
|
+
];
|
|
25
|
+
export const backdoorRule = {
|
|
26
|
+
id: "backdoor",
|
|
27
|
+
name: "Dynamic Code Execution",
|
|
28
|
+
description: "Detects eval(), exec(), and other dynamic code execution patterns",
|
|
29
|
+
run(files) {
|
|
30
|
+
const findings = [];
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
if (file.ext === ".json" || file.ext === ".yaml" || file.ext === ".yml" || file.ext === ".toml" || file.ext === ".md")
|
|
33
|
+
continue;
|
|
34
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
35
|
+
const line = file.lines[i];
|
|
36
|
+
const trimmed = line.trimStart();
|
|
37
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("#") || trimmed.startsWith("*"))
|
|
38
|
+
continue;
|
|
39
|
+
for (const { pattern, desc, severity } of BACKDOOR_PATTERNS) {
|
|
40
|
+
if (pattern.test(line)) {
|
|
41
|
+
findings.push({
|
|
42
|
+
rule: "backdoor",
|
|
43
|
+
severity,
|
|
44
|
+
file: file.relativePath,
|
|
45
|
+
line: i + 1,
|
|
46
|
+
message: desc,
|
|
47
|
+
evidence: line.trim().slice(0, 120),
|
|
48
|
+
});
|
|
49
|
+
break; // one finding per line
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return findings;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=backdoor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backdoor.js","sourceRoot":"","sources":["../../src/rules/backdoor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: credential-hardcode
|
|
3
|
+
* Detects hardcoded API keys, tokens, and passwords in source code.
|
|
4
|
+
*/
|
|
5
|
+
const CREDENTIAL_PATTERNS = [
|
|
6
|
+
// Generic API keys / tokens
|
|
7
|
+
{ pattern: /["'](?:sk|pk|api[_-]?key|token|secret)[_-]?[a-zA-Z]*["']\s*[:=]\s*["'][a-zA-Z0-9_\-/.]{20,}["']/, desc: "Hardcoded API key/token" },
|
|
8
|
+
// AWS
|
|
9
|
+
{ pattern: /AKIA[0-9A-Z]{16}/, desc: "Hardcoded AWS Access Key ID" },
|
|
10
|
+
// GitHub
|
|
11
|
+
{ pattern: /ghp_[a-zA-Z0-9]{36}/, desc: "Hardcoded GitHub personal access token" },
|
|
12
|
+
{ pattern: /github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}/, desc: "Hardcoded GitHub fine-grained token" },
|
|
13
|
+
// Slack
|
|
14
|
+
{ pattern: /xoxb-[0-9]{10,}-[0-9]{10,}-[a-zA-Z0-9]{24}/, desc: "Hardcoded Slack bot token" },
|
|
15
|
+
{ pattern: /xoxp-[0-9]{10,}-[0-9]{10,}-[0-9]{10,}-[a-f0-9]{32}/, desc: "Hardcoded Slack user token" },
|
|
16
|
+
// OpenAI
|
|
17
|
+
{ pattern: /sk-[a-zA-Z0-9]{20,}T3BlbkFJ[a-zA-Z0-9]{20,}/, desc: "Hardcoded OpenAI API key" },
|
|
18
|
+
// Stripe
|
|
19
|
+
{ pattern: /sk_live_[a-zA-Z0-9]{24,}/, desc: "Hardcoded Stripe live key" },
|
|
20
|
+
// Generic password assignment
|
|
21
|
+
{ pattern: /(?:password|passwd|pwd)\s*[:=]\s*["'][^"']{8,}["']/i, desc: "Hardcoded password" },
|
|
22
|
+
// Private key block
|
|
23
|
+
{ pattern: /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/, desc: "Embedded private key" },
|
|
24
|
+
];
|
|
25
|
+
export const credentialHardcodeRule = {
|
|
26
|
+
id: "credential-hardcode",
|
|
27
|
+
name: "Hardcoded Credentials",
|
|
28
|
+
description: "Detects API keys, tokens, passwords, and private keys in source code",
|
|
29
|
+
run(files) {
|
|
30
|
+
const findings = [];
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
if (file.ext === ".md")
|
|
33
|
+
continue;
|
|
34
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
35
|
+
const line = file.lines[i];
|
|
36
|
+
const trimmed = line.trimStart();
|
|
37
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("#") || trimmed.startsWith("*"))
|
|
38
|
+
continue;
|
|
39
|
+
for (const { pattern, desc } of CREDENTIAL_PATTERNS) {
|
|
40
|
+
if (pattern.test(line)) {
|
|
41
|
+
findings.push({
|
|
42
|
+
rule: "credential-hardcode",
|
|
43
|
+
severity: "critical",
|
|
44
|
+
file: file.relativePath,
|
|
45
|
+
line: i + 1,
|
|
46
|
+
message: desc,
|
|
47
|
+
evidence: line.trim().replace(/["'][a-zA-Z0-9_\-/.]{10,}["']/g, '"***"').slice(0, 120),
|
|
48
|
+
});
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return findings;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=credential-hardcode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-hardcode.js","sourceRoot":"","sources":["../../src/rules/credential-hardcode.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,mBAAmB,GAA6C;IACpE,4BAA4B;IAC5B,EAAE,OAAO,EAAE,iGAAiG,EAAE,IAAI,EAAE,yBAAyB,EAAE;IAC/I,MAAM;IACN,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,6BAA6B,EAAE;IACpE,SAAS;IACT,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,wCAAwC,EAAE;IAClF,EAAE,OAAO,EAAE,4CAA4C,EAAE,IAAI,EAAE,qCAAqC,EAAE;IACtG,QAAQ;IACR,EAAE,OAAO,EAAE,4CAA4C,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC5F,EAAE,OAAO,EAAE,oDAAoD,EAAE,IAAI,EAAE,4BAA4B,EAAE;IACrG,SAAS;IACT,EAAE,OAAO,EAAE,6CAA6C,EAAE,IAAI,EAAE,0BAA0B,EAAE;IAC5F,SAAS;IACT,EAAE,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC1E,8BAA8B;IAC9B,EAAE,OAAO,EAAE,qDAAqD,EAAE,IAAI,EAAE,oBAAoB,EAAE;IAC9F,oBAAoB;IACpB,EAAE,OAAO,EAAE,+CAA+C,EAAE,IAAI,EAAE,sBAAsB,EAAE;CAC3F,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAS;IAC1C,EAAE,EAAE,qBAAqB;IACzB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,sEAAsE;IAEnF,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK;gBAAE,SAAS;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAE7F,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,mBAAmB,EAAE,CAAC;oBACpD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,qBAAqB;4BAC3B,QAAQ,EAAE,UAAU;4BACpB,IAAI,EAAE,IAAI,CAAC,YAAY;4BACvB,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,IAAI;4BACb,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACvF,CAAC,CAAC;wBACH,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: crypto-mining
|
|
3
|
+
* Detects cryptocurrency mining patterns.
|
|
4
|
+
*/
|
|
5
|
+
const MINING_PATTERNS = [
|
|
6
|
+
{ pattern: /stratum\+tcp:\/\/|stratum\+ssl:\/\//, desc: "Stratum mining protocol URL" },
|
|
7
|
+
{ pattern: /xmrig|cpuminer|minerd|minergate|coinhive|cryptonight/i, desc: "Known mining software reference" },
|
|
8
|
+
{ pattern: /\bmining_pool\b|\bpool_url\b|\bpool_address\b/i, desc: "Mining pool configuration" },
|
|
9
|
+
{ pattern: /\bmonero\b.*\bwallet\b|\bwallet\b.*\bmonero\b/i, desc: "Monero wallet reference" },
|
|
10
|
+
{ pattern: /crypto\.createHash.*\bwhile\b.*true|for\s*\(\s*;\s*;\s*\).*hash/i, desc: "Infinite loop with hashing — potential mining" },
|
|
11
|
+
];
|
|
12
|
+
export const cryptoMiningRule = {
|
|
13
|
+
id: "crypto-mining",
|
|
14
|
+
name: "Cryptocurrency Mining",
|
|
15
|
+
description: "Detects mining pool connections, known miners, and mining-related patterns",
|
|
16
|
+
run(files) {
|
|
17
|
+
const findings = [];
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
if (file.ext === ".md")
|
|
20
|
+
continue;
|
|
21
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
22
|
+
const line = file.lines[i];
|
|
23
|
+
for (const { pattern, desc } of MINING_PATTERNS) {
|
|
24
|
+
if (pattern.test(line)) {
|
|
25
|
+
findings.push({
|
|
26
|
+
rule: "crypto-mining",
|
|
27
|
+
severity: "critical",
|
|
28
|
+
file: file.relativePath,
|
|
29
|
+
line: i + 1,
|
|
30
|
+
message: desc,
|
|
31
|
+
evidence: line.trim().slice(0, 120),
|
|
32
|
+
});
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return findings;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=crypto-mining.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-mining.js","sourceRoot":"","sources":["../../src/rules/crypto-mining.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,eAAe,GAA6C;IAChE,EAAE,OAAO,EAAE,qCAAqC,EAAE,IAAI,EAAE,6BAA6B,EAAE;IACvF,EAAE,OAAO,EAAE,uDAAuD,EAAE,IAAI,EAAE,iCAAiC,EAAE;IAC7G,EAAE,OAAO,EAAE,gDAAgD,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAChG,EAAE,OAAO,EAAE,gDAAgD,EAAE,IAAI,EAAE,yBAAyB,EAAE;IAC9F,EAAE,OAAO,EAAE,kEAAkE,EAAE,IAAI,EAAE,+CAA+C,EAAE;CACvI,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,4EAA4E;IAEzF,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK;gBAAE,SAAS;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;gBAE5B,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,eAAe,EAAE,CAAC;oBAChD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,eAAe;4BACrB,QAAQ,EAAE,UAAU;4BACpB,IAAI,EAAE,IAAI,CAAC,YAAY;4BACvB,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,IAAI;4BACb,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACpC,CAAC,CAAC;wBACH,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: data-exfil
|
|
3
|
+
* Detects code that reads sensitive files AND sends HTTP requests — a classic exfiltration pattern.
|
|
4
|
+
*/
|
|
5
|
+
const SENSITIVE_READ_RE = /readFile|readFileSync|fs\.read|open\(|\.ssh|\.env|credentials|\.aws|\.kube|\.npmrc|\.gitconfig|\.openclaw/i;
|
|
6
|
+
const HTTP_SEND_RE = /fetch\s*\(|axios\.|http\.request|https\.request|XMLHttpRequest|\.post\s*\(|\.put\s*\(|urllib|requests\.(post|put|patch)|curl\s/i;
|
|
7
|
+
const DYNAMIC_URL_RE = /fetch\s*\(\s*`[^`]*\$\{|fetch\s*\(\s*[a-zA-Z_]\w*\s*[+,)]/;
|
|
8
|
+
export const dataExfilRule = {
|
|
9
|
+
id: "data-exfil",
|
|
10
|
+
name: "Data Exfiltration",
|
|
11
|
+
description: "Detects patterns where sensitive data is read and sent over HTTP",
|
|
12
|
+
run(files) {
|
|
13
|
+
const findings = [];
|
|
14
|
+
for (const file of files) {
|
|
15
|
+
if (file.ext === ".json" || file.ext === ".yaml" || file.ext === ".yml" || file.ext === ".toml" || file.ext === ".md")
|
|
16
|
+
continue;
|
|
17
|
+
const content = file.content;
|
|
18
|
+
const hasSensitiveRead = SENSITIVE_READ_RE.test(content);
|
|
19
|
+
const hasHttpSend = HTTP_SEND_RE.test(content);
|
|
20
|
+
// Critical: same file reads sensitive data AND sends it out
|
|
21
|
+
if (hasSensitiveRead && hasHttpSend) {
|
|
22
|
+
// Find the specific lines
|
|
23
|
+
const readLines = [];
|
|
24
|
+
const sendLines = [];
|
|
25
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
26
|
+
const line = file.lines[i];
|
|
27
|
+
if (SENSITIVE_READ_RE.test(line))
|
|
28
|
+
readLines.push(i + 1);
|
|
29
|
+
if (HTTP_SEND_RE.test(line))
|
|
30
|
+
sendLines.push(i + 1);
|
|
31
|
+
}
|
|
32
|
+
if (readLines.length > 0 && sendLines.length > 0) {
|
|
33
|
+
findings.push({
|
|
34
|
+
rule: "data-exfil",
|
|
35
|
+
severity: "critical",
|
|
36
|
+
file: file.relativePath,
|
|
37
|
+
line: sendLines[0],
|
|
38
|
+
message: `Reads sensitive data (line ${readLines.join(",")}) and sends HTTP request (line ${sendLines.join(",")}) — possible exfiltration`,
|
|
39
|
+
evidence: file.lines[sendLines[0] - 1]?.trim().slice(0, 120),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Warning: dynamic URL construction in fetch/request calls
|
|
44
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
45
|
+
const line = file.lines[i];
|
|
46
|
+
if (DYNAMIC_URL_RE.test(line)) {
|
|
47
|
+
findings.push({
|
|
48
|
+
rule: "data-exfil",
|
|
49
|
+
severity: "warning",
|
|
50
|
+
file: file.relativePath,
|
|
51
|
+
line: i + 1,
|
|
52
|
+
message: "Dynamic URL construction in HTTP request — potential SSRF",
|
|
53
|
+
evidence: line.trim().slice(0, 120),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return findings;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=data-exfil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-exfil.js","sourceRoot":"","sources":["../../src/rules/data-exfil.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: env-leak
|
|
3
|
+
* Detects process.env access combined with HTTP send — leaking environment variables.
|
|
4
|
+
*/
|
|
5
|
+
const ENV_ACCESS_RE = /process\.env\b|os\.environ|getenv\s*\(/i;
|
|
6
|
+
const HTTP_SEND_RE = /fetch\s*\(|axios\.|http\.request|https\.request|requests\.(post|put|patch)|\.post\s*\(|curl\s/i;
|
|
7
|
+
export const envLeakRule = {
|
|
8
|
+
id: "env-leak",
|
|
9
|
+
name: "Environment Variable Leak",
|
|
10
|
+
description: "Detects process.env access combined with outbound HTTP requests",
|
|
11
|
+
run(files) {
|
|
12
|
+
const findings = [];
|
|
13
|
+
for (const file of files) {
|
|
14
|
+
if (file.ext === ".json" || file.ext === ".yaml" || file.ext === ".yml" || file.ext === ".md")
|
|
15
|
+
continue;
|
|
16
|
+
const hasEnvAccess = ENV_ACCESS_RE.test(file.content);
|
|
17
|
+
const hasHttpSend = HTTP_SEND_RE.test(file.content);
|
|
18
|
+
if (hasEnvAccess && hasHttpSend) {
|
|
19
|
+
const envLines = [];
|
|
20
|
+
const sendLines = [];
|
|
21
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
22
|
+
const line = file.lines[i];
|
|
23
|
+
if (ENV_ACCESS_RE.test(line))
|
|
24
|
+
envLines.push(i + 1);
|
|
25
|
+
if (HTTP_SEND_RE.test(line))
|
|
26
|
+
sendLines.push(i + 1);
|
|
27
|
+
}
|
|
28
|
+
if (envLines.length > 0 && sendLines.length > 0) {
|
|
29
|
+
findings.push({
|
|
30
|
+
rule: "env-leak",
|
|
31
|
+
severity: "critical",
|
|
32
|
+
file: file.relativePath,
|
|
33
|
+
line: sendLines[0],
|
|
34
|
+
message: `Reads environment variables (line ${envLines.join(",")}) and sends HTTP request (line ${sendLines.join(",")}) — possible env leak`,
|
|
35
|
+
evidence: file.lines[sendLines[0] - 1]?.trim().slice(0, 120),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return findings;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=env-leak.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-leak.js","sourceRoot":"","sources":["../../src/rules/env-leak.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,aAAa,GAAG,yCAAyC,CAAC;AAChE,MAAM,YAAY,GAAG,gGAAgG,CAAC;AAEtH,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,2BAA2B;IACjC,WAAW,EAAE,iEAAiE;IAE9E,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK;gBAAE,SAAS;YAExG,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAEpD,IAAI,YAAY,IAAI,WAAW,EAAE,CAAC;gBAChC,MAAM,QAAQ,GAAa,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAa,EAAE,CAAC;gBAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;oBAC5B,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBACnD,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrD,CAAC;gBAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChD,QAAQ,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,UAAU;wBAChB,QAAQ,EAAE,UAAU;wBACpB,IAAI,EAAE,IAAI,CAAC,YAAY;wBACvB,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;wBAClB,OAAO,EAAE,qCAAqC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,kCAAkC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,uBAAuB;wBAC5I,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qBAC9D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import matter from "gray-matter";
|
|
2
|
+
/**
|
|
3
|
+
* Rule: excessive-perms
|
|
4
|
+
* Detects skills that request too many or dangerous permissions.
|
|
5
|
+
*/
|
|
6
|
+
const DANGEROUS_PERMS = new Set(["exec", "admin", "root", "sudo", "network", "browser"]);
|
|
7
|
+
const MAX_REASONABLE_PERMS = 5;
|
|
8
|
+
export const excessivePermsRule = {
|
|
9
|
+
id: "excessive-perms",
|
|
10
|
+
name: "Excessive Permissions",
|
|
11
|
+
description: "Detects skills requesting too many or dangerous permissions",
|
|
12
|
+
run(files) {
|
|
13
|
+
const findings = [];
|
|
14
|
+
const skillMd = files.find((f) => f.relativePath === "SKILL.md" || f.relativePath.endsWith("/SKILL.md"));
|
|
15
|
+
if (!skillMd)
|
|
16
|
+
return findings;
|
|
17
|
+
let permissions = [];
|
|
18
|
+
try {
|
|
19
|
+
const { data } = matter(skillMd.content);
|
|
20
|
+
if (Array.isArray(data.permissions)) {
|
|
21
|
+
permissions = data.permissions.filter((p) => typeof p === "string");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return findings;
|
|
26
|
+
}
|
|
27
|
+
// Check for dangerous permissions
|
|
28
|
+
for (const perm of permissions) {
|
|
29
|
+
if (DANGEROUS_PERMS.has(perm.toLowerCase())) {
|
|
30
|
+
findings.push({
|
|
31
|
+
rule: "excessive-perms",
|
|
32
|
+
severity: "warning",
|
|
33
|
+
file: skillMd.relativePath,
|
|
34
|
+
message: `Requests dangerous permission: '${perm}'`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Check for excessive number of permissions
|
|
39
|
+
if (permissions.length > MAX_REASONABLE_PERMS) {
|
|
40
|
+
findings.push({
|
|
41
|
+
rule: "excessive-perms",
|
|
42
|
+
severity: "warning",
|
|
43
|
+
file: skillMd.relativePath,
|
|
44
|
+
message: `Requests ${permissions.length} permissions (threshold: ${MAX_REASONABLE_PERMS}) — review if all are necessary`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return findings;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=excessive-perms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"excessive-perms.js","sourceRoot":"","sources":["../../src/rules/excessive-perms.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC;;;GAGG;AAEH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AACzF,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B,MAAM,CAAC,MAAM,kBAAkB,GAAS;IACtC,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,6DAA6D;IAE1E,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,UAAU,IAAI,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC7E,CAAC;QACF,IAAI,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAC;QAE9B,IAAI,WAAW,GAAa,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBACpC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YAC/E,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,kCAAkC;QAClC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,iBAAiB;oBACvB,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,OAAO,CAAC,YAAY;oBAC1B,OAAO,EAAE,mCAAmC,IAAI,GAAG;iBACpD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,IAAI,WAAW,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,iBAAiB;gBACvB,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,OAAO,CAAC,YAAY;gBAC1B,OAAO,EAAE,YAAY,WAAW,CAAC,MAAM,4BAA4B,oBAAoB,iCAAiC;aACzH,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: hidden-files
|
|
3
|
+
* Detects exposed .env files and other hidden config files that shouldn't be committed.
|
|
4
|
+
*/
|
|
5
|
+
const DANGEROUS_FILES = [
|
|
6
|
+
{ pattern: /^\.env($|\.)/, desc: "Environment file with secrets" },
|
|
7
|
+
{ pattern: /^\.env\.local$/, desc: "Local environment file" },
|
|
8
|
+
{ pattern: /^\.env\.production$/, desc: "Production environment file" },
|
|
9
|
+
{ pattern: /^\.htpasswd$/, desc: "Apache password file" },
|
|
10
|
+
{ pattern: /^\.htaccess$/, desc: "Apache config file" },
|
|
11
|
+
{ pattern: /^\.pgpass$/, desc: "PostgreSQL password file" },
|
|
12
|
+
{ pattern: /^\.netrc$/, desc: "Network credentials file" },
|
|
13
|
+
];
|
|
14
|
+
const SECRET_IN_ENV_RE = /^[A-Z_]+=(?!$).*(?:key|secret|token|password|credential|auth)/i;
|
|
15
|
+
export const hiddenFilesRule = {
|
|
16
|
+
id: "hidden-files",
|
|
17
|
+
name: "Hidden/Secret Files",
|
|
18
|
+
description: "Detects .env files and other hidden configs that may leak secrets",
|
|
19
|
+
run(files) {
|
|
20
|
+
const findings = [];
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
const basename = file.relativePath.split("/").pop() || "";
|
|
23
|
+
for (const { pattern, desc } of DANGEROUS_FILES) {
|
|
24
|
+
if (pattern.test(basename)) {
|
|
25
|
+
findings.push({
|
|
26
|
+
rule: "hidden-files",
|
|
27
|
+
severity: "critical",
|
|
28
|
+
file: file.relativePath,
|
|
29
|
+
message: `${desc} found in repository — should be in .gitignore`,
|
|
30
|
+
});
|
|
31
|
+
// Check for actual secrets in the file
|
|
32
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
33
|
+
const line = file.lines[i];
|
|
34
|
+
if (SECRET_IN_ENV_RE.test(line) && !line.trimStart().startsWith("#")) {
|
|
35
|
+
findings.push({
|
|
36
|
+
rule: "hidden-files",
|
|
37
|
+
severity: "critical",
|
|
38
|
+
file: file.relativePath,
|
|
39
|
+
line: i + 1,
|
|
40
|
+
message: "Hardcoded secret in environment file",
|
|
41
|
+
evidence: line.replace(/=.*/, "=***").slice(0, 80),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return findings;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=hidden-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hidden-files.js","sourceRoot":"","sources":["../../src/rules/hidden-files.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,eAAe,GAAG;IACtB,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,+BAA+B,EAAE;IAClE,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAC7D,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,6BAA6B,EAAE;IACvE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,sBAAsB,EAAE;IACzD,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACvD,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,EAAE;IAC3D,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,0BAA0B,EAAE;CAC3D,CAAC;AAEF,MAAM,gBAAgB,GACpB,gEAAgE,CAAC;AAEnE,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,mEAAmE;IAEhF,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE1D,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,eAAe,EAAE,CAAC;gBAChD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3B,QAAQ,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,cAAc;wBACpB,QAAQ,EAAE,UAAU;wBACpB,IAAI,EAAE,IAAI,CAAC,YAAY;wBACvB,OAAO,EAAE,GAAG,IAAI,gDAAgD;qBACjE,CAAC,CAAC;oBAEH,uCAAuC;oBACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;wBAC5B,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;4BACrE,QAAQ,CAAC,IAAI,CAAC;gCACZ,IAAI,EAAE,cAAc;gCACpB,QAAQ,EAAE,UAAU;gCACpB,IAAI,EAAE,IAAI,CAAC,YAAY;gCACvB,IAAI,EAAE,CAAC,GAAG,CAAC;gCACX,OAAO,EAAE,sCAAsC;gCAC/C,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;6BACnD,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;oBACD,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { sensitiveReadRule } from "./sensitive-read.js";
|
|
2
|
+
import { backdoorRule } from "./backdoor.js";
|
|
3
|
+
import { dataExfilRule } from "./data-exfil.js";
|
|
4
|
+
import { privilegeRule } from "./privilege.js";
|
|
5
|
+
import { supplyChainRule } from "./supply-chain.js";
|
|
6
|
+
import { obfuscationRule } from "./obfuscation.js";
|
|
7
|
+
import { envLeakRule } from "./env-leak.js";
|
|
8
|
+
import { cryptoMiningRule } from "./crypto-mining.js";
|
|
9
|
+
import { reverseShellRule } from "./reverse-shell.js";
|
|
10
|
+
import { typosquattingRule } from "./typosquatting.js";
|
|
11
|
+
import { hiddenFilesRule } from "./hidden-files.js";
|
|
12
|
+
import { excessivePermsRule } from "./excessive-perms.js";
|
|
13
|
+
import { phoneHomeRule } from "./phone-home.js";
|
|
14
|
+
import { credentialHardcodeRule } from "./credential-hardcode.js";
|
|
15
|
+
import { networkSsrfRule } from "./network-ssrf.js";
|
|
16
|
+
import { mcpManifestRule } from "./mcp-manifest.js";
|
|
17
|
+
import { promptInjection } from "./prompt-injection.js";
|
|
18
|
+
import { toolShadowing } from "./tool-shadowing.js";
|
|
19
|
+
import { skillRisks } from "./skill-risks.js";
|
|
20
|
+
import { toxicFlow } from "./toxic-flow.js";
|
|
21
|
+
/** All registered rules */
|
|
22
|
+
export const rules = [
|
|
23
|
+
// Original 5
|
|
24
|
+
dataExfilRule,
|
|
25
|
+
backdoorRule,
|
|
26
|
+
privilegeRule,
|
|
27
|
+
supplyChainRule,
|
|
28
|
+
sensitiveReadRule,
|
|
29
|
+
// New 10
|
|
30
|
+
obfuscationRule,
|
|
31
|
+
envLeakRule,
|
|
32
|
+
cryptoMiningRule,
|
|
33
|
+
reverseShellRule,
|
|
34
|
+
typosquattingRule,
|
|
35
|
+
hiddenFilesRule,
|
|
36
|
+
excessivePermsRule,
|
|
37
|
+
phoneHomeRule,
|
|
38
|
+
credentialHardcodeRule,
|
|
39
|
+
networkSsrfRule,
|
|
40
|
+
mcpManifestRule,
|
|
41
|
+
// Prompt injection & tool shadowing
|
|
42
|
+
promptInjection,
|
|
43
|
+
toolShadowing,
|
|
44
|
+
// Skill risk assessment
|
|
45
|
+
skillRisks,
|
|
46
|
+
// Toxic flow analysis
|
|
47
|
+
toxicFlow,
|
|
48
|
+
];
|
|
49
|
+
/** Get a rule by ID */
|
|
50
|
+
export function getRule(id) {
|
|
51
|
+
return rules.find((r) => r.id === id);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,2BAA2B;AAC3B,MAAM,CAAC,MAAM,KAAK,GAAW;IAC3B,aAAa;IACb,aAAa;IACb,YAAY;IACZ,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,SAAS;IACT,eAAe;IACf,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,aAAa;IACb,sBAAsB;IACtB,eAAe;IACf,eAAe;IACf,oCAAoC;IACpC,eAAe;IACf,aAAa;IACb,wBAAwB;IACxB,UAAU;IACV,sBAAsB;IACtB,SAAS;CACV,CAAC;AAEF,uBAAuB;AACvB,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACxC,CAAC"}
|