@elliotllliu/agent-shield 0.3.1 → 0.4.3

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.
Files changed (98) hide show
  1. package/README.md +253 -170
  2. package/README.zh-CN.md +153 -72
  3. package/dist/cli.js +23 -7
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +4 -4
  6. package/dist/config.js +5 -5
  7. package/dist/config.js.map +1 -1
  8. package/dist/discover.js +1 -1
  9. package/dist/discover.js.map +1 -1
  10. package/dist/llm/anthropic.js +1 -1
  11. package/dist/llm/anthropic.js.map +1 -1
  12. package/dist/llm/ollama.js +1 -1
  13. package/dist/llm/ollama.js.map +1 -1
  14. package/dist/llm/openai.js +1 -1
  15. package/dist/llm/openai.js.map +1 -1
  16. package/dist/llm/prompt.d.ts +1 -1
  17. package/dist/llm/prompt.js +1 -1
  18. package/dist/llm/types.d.ts +1 -1
  19. package/dist/llm-analyzer.js +2 -2
  20. package/dist/llm-analyzer.js.map +1 -1
  21. package/dist/reporter/badge.js +1 -1
  22. package/dist/reporter/badge.js.map +1 -1
  23. package/dist/reporter/terminal.js +32 -18
  24. package/dist/reporter/terminal.js.map +1 -1
  25. package/dist/rules/attack-chain.d.ts +2 -0
  26. package/dist/rules/attack-chain.js +177 -0
  27. package/dist/rules/attack-chain.js.map +1 -0
  28. package/dist/rules/backdoor.js +18 -16
  29. package/dist/rules/backdoor.js.map +1 -1
  30. package/dist/rules/credential-hardcode.js +1 -1
  31. package/dist/rules/credential-hardcode.js.map +1 -1
  32. package/dist/rules/cross-file.d.ts +2 -0
  33. package/dist/rules/cross-file.js +234 -0
  34. package/dist/rules/cross-file.js.map +1 -0
  35. package/dist/rules/crypto-mining.js +1 -1
  36. package/dist/rules/crypto-mining.js.map +1 -1
  37. package/dist/rules/data-exfil.js +15 -4
  38. package/dist/rules/data-exfil.js.map +1 -1
  39. package/dist/rules/description-integrity.d.ts +2 -0
  40. package/dist/rules/description-integrity.js +204 -0
  41. package/dist/rules/description-integrity.js.map +1 -0
  42. package/dist/rules/env-leak.js +1 -1
  43. package/dist/rules/env-leak.js.map +1 -1
  44. package/dist/rules/excessive-perms.js +2 -2
  45. package/dist/rules/excessive-perms.js.map +1 -1
  46. package/dist/rules/hidden-files.js +2 -2
  47. package/dist/rules/hidden-files.js.map +1 -1
  48. package/dist/rules/index.js +21 -0
  49. package/dist/rules/index.js.map +1 -1
  50. package/dist/rules/mcp-manifest.js +14 -14
  51. package/dist/rules/mcp-manifest.js.map +1 -1
  52. package/dist/rules/mcp-runtime.d.ts +2 -0
  53. package/dist/rules/mcp-runtime.js +202 -0
  54. package/dist/rules/mcp-runtime.js.map +1 -0
  55. package/dist/rules/multilang-injection.d.ts +2 -0
  56. package/dist/rules/multilang-injection.js +107 -0
  57. package/dist/rules/multilang-injection.js.map +1 -0
  58. package/dist/rules/network-ssrf.js +8 -8
  59. package/dist/rules/network-ssrf.js.map +1 -1
  60. package/dist/rules/obfuscation.js +6 -6
  61. package/dist/rules/obfuscation.js.map +1 -1
  62. package/dist/rules/phone-home.js +1 -1
  63. package/dist/rules/phone-home.js.map +1 -1
  64. package/dist/rules/privilege.js +4 -4
  65. package/dist/rules/privilege.js.map +1 -1
  66. package/dist/rules/prompt-injection.js +99 -83
  67. package/dist/rules/prompt-injection.js.map +1 -1
  68. package/dist/rules/python-ast.d.ts +2 -0
  69. package/dist/rules/python-ast.js +109 -0
  70. package/dist/rules/python-ast.js.map +1 -0
  71. package/dist/rules/python-security.d.ts +2 -0
  72. package/dist/rules/python-security.js +91 -0
  73. package/dist/rules/python-security.js.map +1 -0
  74. package/dist/rules/reverse-shell.js +1 -1
  75. package/dist/rules/reverse-shell.js.map +1 -1
  76. package/dist/rules/sensitive-read.js +1 -1
  77. package/dist/rules/sensitive-read.js.map +1 -1
  78. package/dist/rules/skill-risks.js +5 -5
  79. package/dist/rules/skill-risks.js.map +1 -1
  80. package/dist/rules/supply-chain.js +4 -4
  81. package/dist/rules/supply-chain.js.map +1 -1
  82. package/dist/rules/tool-shadowing.js +3 -3
  83. package/dist/rules/tool-shadowing.js.map +1 -1
  84. package/dist/rules/toxic-flow.js +3 -3
  85. package/dist/rules/toxic-flow.js.map +1 -1
  86. package/dist/rules/typosquatting.js +1 -1
  87. package/dist/rules/typosquatting.js.map +1 -1
  88. package/dist/scanner/files.d.ts +4 -0
  89. package/dist/scanner/files.js +35 -1
  90. package/dist/scanner/files.js.map +1 -1
  91. package/dist/scanner/index.js +88 -13
  92. package/dist/scanner/index.js.map +1 -1
  93. package/dist/score.d.ts +5 -4
  94. package/dist/score.js +14 -7
  95. package/dist/score.js.map +1 -1
  96. package/dist/types.d.ts +8 -4
  97. package/package.json +22 -20
  98. package/src/analyzers/python_ast.py +304 -0
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Rule: cross-file
3
+ * Cross-file correlation analysis — detects attack patterns that span multiple files.
4
+ * This is a capability that single-file scanners (like Snyk Agent Scan) cannot do.
5
+ *
6
+ * Checks:
7
+ * 1. Data flow: File A reads secrets → File B sends HTTP (cross-file exfiltration)
8
+ * 2. Code injection: File A receives input → File B passes to eval/exec
9
+ * 3. Capability mismatch: manifest/config declares X, code does Y
10
+ * 4. Import chain: suspicious module imports across the project
11
+ */
12
+ // === Data sources (where sensitive data originates) ===
13
+ const SECRET_READ_PATTERNS = [
14
+ /readFileSync\s*\([^)]*(?:\.ssh|\.env|\.aws|credentials|private.?key|secret)/i,
15
+ /open\s*\([^)]*(?:\.ssh|\.env|\.aws|credentials|private.?key|secret)/i,
16
+ /os\.environ\s*\[/,
17
+ /os\.getenv\s*\(/,
18
+ /process\.env\s*\./,
19
+ /process\.env\s*\[/,
20
+ ];
21
+ // === Data sinks (where data leaves the system) ===
22
+ const HTTP_SINK_PATTERNS = [
23
+ /fetch\s*\(\s*["'`]https?:\/\/(?!localhost|127\.0\.0\.1)/,
24
+ /requests\.(post|put|patch)\s*\(\s*["'`]https?:\/\//,
25
+ /axios\.(post|put|patch)\s*\(/,
26
+ /urllib\.request\.urlopen/,
27
+ /http\.request\s*\(/,
28
+ /\.post\s*\(\s*["'`]https?:\/\/(?!localhost|127\.0\.0\.1)/,
29
+ ];
30
+ // === Code injection sinks ===
31
+ const EXEC_SINK_PATTERNS = [
32
+ /\beval\s*\(\s*[a-zA-Z_]/,
33
+ /\bexec\s*\(\s*[a-zA-Z_]/,
34
+ /new\s+Function\s*\(/,
35
+ /child_process\.\s*exec\s*\(/,
36
+ /subprocess\.(?:call|run|Popen)\s*\(/,
37
+ /os\.system\s*\(/,
38
+ ];
39
+ // === User input sources ===
40
+ const INPUT_SOURCE_PATTERNS = [
41
+ /req\.(?:body|query|params|headers)\s*[\[.]/,
42
+ /request\.(?:form|args|json|data)\s*[\[.]/,
43
+ /process\.argv/,
44
+ /sys\.argv/,
45
+ // Note: tool_parameters and self.runtime are SDK interfaces, not raw user input
46
+ // They are handled by the framework and don't represent direct injection vectors
47
+ ];
48
+ // === Capability patterns for manifest checking ===
49
+ const CAPABILITY_PATTERNS = {
50
+ network: [
51
+ /fetch\s*\(/, /requests\.\w+\s*\(/, /axios/, /urllib/,
52
+ /http\.request/, /https\.request/, /XMLHttpRequest/,
53
+ ],
54
+ filesystem: [
55
+ /readFile|writeFile|readFileSync|writeFileSync/,
56
+ /open\s*\(/, /os\.path/, /pathlib/,
57
+ /fs\.read|fs\.write|fs\.unlink|fs\.mkdir/,
58
+ ],
59
+ exec: [
60
+ /child_process/, /subprocess/, /os\.system/, /os\.popen/,
61
+ /exec\s*\(/, /eval\s*\(/, /spawn\s*\(/,
62
+ ],
63
+ crypto: [
64
+ /crypto\./, /hashlib\./, /hmac\./, /bcrypt/, /jwt\./,
65
+ ],
66
+ };
67
+ function analyzeFile(file) {
68
+ const content = file.content;
69
+ const sig = {
70
+ file,
71
+ hasSecretRead: SECRET_READ_PATTERNS.some(p => p.test(content)),
72
+ hasHttpSink: HTTP_SINK_PATTERNS.some(p => p.test(content)),
73
+ hasExecSink: EXEC_SINK_PATTERNS.some(p => p.test(content)),
74
+ hasInputSource: INPUT_SOURCE_PATTERNS.some(p => p.test(content)),
75
+ capabilities: new Set(),
76
+ exportsModules: [],
77
+ importsModules: [],
78
+ };
79
+ // Detect capabilities
80
+ for (const [cap, patterns] of Object.entries(CAPABILITY_PATTERNS)) {
81
+ if (patterns.some(p => p.test(content))) {
82
+ sig.capabilities.add(cap);
83
+ }
84
+ }
85
+ // Detect imports (Python)
86
+ const pyImports = content.matchAll(/^(?:from|import)\s+([\w.]+)/gm);
87
+ for (const m of pyImports) {
88
+ sig.importsModules.push(m[1]);
89
+ }
90
+ // Detect imports (JS/TS)
91
+ const jsImports = content.matchAll(/(?:import|require)\s*\(?["'`]([^"'`]+)["'`]\)?/g);
92
+ for (const m of jsImports) {
93
+ sig.importsModules.push(m[1]);
94
+ }
95
+ return sig;
96
+ }
97
+ export const crossFileRule = {
98
+ id: "cross-file",
99
+ name: "Cross-File Correlation",
100
+ description: "Detects attack patterns spanning multiple files (data flow, capability mismatch)",
101
+ run(files) {
102
+ const findings = [];
103
+ if (files.length < 2)
104
+ return findings;
105
+ const codeFiles = files.filter(f => [".ts", ".js", ".py", ".sh"].includes(f.ext));
106
+ if (codeFiles.length === 0)
107
+ return findings;
108
+ // Analyze all code files
109
+ const signatures = codeFiles.map(analyzeFile);
110
+ // === Check 1: Cross-file data exfiltration (needs >= 2 code files) ===
111
+ if (codeFiles.length >= 2) {
112
+ // File A reads secrets, File B (different file) sends HTTP to external
113
+ // Exclude test/debug files — they commonly mock secrets and HTTP
114
+ const secretReaders = signatures.filter(s => s.hasSecretRead && s.file.context !== "test");
115
+ const httpSenders = signatures.filter(s => s.hasHttpSink && s.file.context !== "test");
116
+ for (const reader of secretReaders) {
117
+ for (const sender of httpSenders) {
118
+ if (reader.file.relativePath === sender.file.relativePath)
119
+ continue;
120
+ // Check if they're connected (same module/package or import relationship)
121
+ const readerModule = reader.file.relativePath.replace(/\.[^.]+$/, "").replace(/\//g, ".");
122
+ const connected = sender.importsModules.some(m => readerModule.includes(m) || m.includes(readerModule.split("/").pop()));
123
+ if (connected) {
124
+ findings.push({
125
+ rule: "cross-file",
126
+ severity: "high",
127
+ file: sender.file.relativePath,
128
+ message: `Cross-file data flow: ${reader.file.relativePath} reads secrets → ${sender.file.relativePath} sends HTTP externally (connected via imports)`,
129
+ confidence: "high",
130
+ });
131
+ }
132
+ else {
133
+ // Even without direct import, flag if in same directory
134
+ const readerDir = reader.file.relativePath.split("/").slice(0, -1).join("/");
135
+ const senderDir = sender.file.relativePath.split("/").slice(0, -1).join("/");
136
+ if (readerDir === senderDir && readerDir !== "") {
137
+ findings.push({
138
+ rule: "cross-file",
139
+ severity: "medium",
140
+ file: sender.file.relativePath,
141
+ message: `Cross-file data flow risk: ${reader.file.relativePath} reads secrets, ${sender.file.relativePath} sends HTTP (same directory: ${readerDir}/)`,
142
+ confidence: "medium",
143
+ });
144
+ }
145
+ }
146
+ }
147
+ }
148
+ } // end check 1: codeFiles >= 2
149
+ // === Check 2: Cross-file code injection ===
150
+ // File A receives user input, File B passes to eval/exec
151
+ // Exclude test/debug files as input sources — they simulate input, not receive real user data
152
+ if (codeFiles.length >= 2) {
153
+ const inputReceivers = signatures.filter(s => s.hasInputSource && s.file.context !== "test");
154
+ const execSinks = signatures.filter(s => s.hasExecSink && s.file.context !== "test");
155
+ for (const receiver of inputReceivers) {
156
+ for (const executor of execSinks) {
157
+ if (receiver.file.relativePath === executor.file.relativePath)
158
+ continue;
159
+ const receiverModule = receiver.file.relativePath.replace(/\.[^.]+$/, "");
160
+ const connected = executor.importsModules.some(m => receiverModule.includes(m) || m.includes(receiverModule.split("/").pop()));
161
+ if (connected) {
162
+ findings.push({
163
+ rule: "cross-file",
164
+ severity: "high",
165
+ file: executor.file.relativePath,
166
+ message: `Cross-file code injection risk: ${receiver.file.relativePath} receives input → ${executor.file.relativePath} passes to eval/exec (connected via imports)`,
167
+ confidence: "high",
168
+ });
169
+ }
170
+ }
171
+ }
172
+ } // end codeFiles >= 2
173
+ // === Check 3: Capability mismatch ===
174
+ // manifest.yaml declares limited capabilities, but code uses more
175
+ const manifestFile = files.find(f => f.relativePath === "manifest.yaml" || f.relativePath === "manifest.yml" ||
176
+ f.relativePath === "manifest.json");
177
+ if (manifestFile) {
178
+ const manifestCaps = new Set();
179
+ const manifestContent = manifestFile.content.toLowerCase();
180
+ // Detect what the manifest claims
181
+ if (/network|http|api|fetch|request/i.test(manifestContent))
182
+ manifestCaps.add("network");
183
+ if (/file|read|write|path|directory/i.test(manifestContent))
184
+ manifestCaps.add("filesystem");
185
+ if (/exec|command|shell|process/i.test(manifestContent))
186
+ manifestCaps.add("exec");
187
+ // Check what code actually does (exclude test files)
188
+ const allCodeCaps = new Set();
189
+ for (const sig of signatures) {
190
+ if (sig.file.context === "test")
191
+ continue;
192
+ for (const cap of sig.capabilities) {
193
+ allCodeCaps.add(cap);
194
+ }
195
+ }
196
+ // Find undeclared capabilities
197
+ for (const cap of allCodeCaps) {
198
+ if (!manifestCaps.has(cap) && cap === "exec") {
199
+ // Exec capability not mentioned in manifest — suspicious
200
+ const execFiles = signatures
201
+ .filter(s => s.capabilities.has("exec"))
202
+ .map(s => s.file.relativePath);
203
+ findings.push({
204
+ rule: "cross-file",
205
+ severity: "medium",
206
+ file: manifestFile.relativePath,
207
+ message: `Capability mismatch: manifest doesn't declare '${cap}' but code uses it in: ${execFiles.join(", ")}`,
208
+ confidence: "medium",
209
+ });
210
+ }
211
+ }
212
+ }
213
+ // === Check 4: Suspicious import chains ===
214
+ // Detect files that import known-dangerous modules in unusual ways
215
+ const dangerousModules = new Set([
216
+ "pickle", "marshal", "shelve", "ctypes",
217
+ "webbrowser", "ftplib", "telnetlib",
218
+ ]);
219
+ for (const sig of signatures) {
220
+ const dangerousImports = sig.importsModules.filter(m => dangerousModules.has(m) || dangerousModules.has(m.split(".")[0]));
221
+ if (dangerousImports.length >= 2) {
222
+ findings.push({
223
+ rule: "cross-file",
224
+ severity: "medium",
225
+ file: sig.file.relativePath,
226
+ message: `Multiple dangerous module imports: ${dangerousImports.join(", ")} — review usage carefully`,
227
+ confidence: "medium",
228
+ });
229
+ }
230
+ }
231
+ return findings;
232
+ },
233
+ };
234
+ //# sourceMappingURL=cross-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-file.js","sourceRoot":"","sources":["../../src/rules/cross-file.ts"],"names":[],"mappings":"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"}
@@ -24,7 +24,7 @@ export const cryptoMiningRule = {
24
24
  if (pattern.test(line)) {
25
25
  findings.push({
26
26
  rule: "crypto-mining",
27
- severity: "critical",
27
+ severity: "high",
28
28
  file: file.relativePath,
29
29
  line: i + 1,
30
30
  message: desc,
@@ -1 +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"}
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,MAAM;4BAChB,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"}
@@ -2,7 +2,11 @@
2
2
  * Rule: data-exfil
3
3
  * Detects code that reads sensitive files AND sends HTTP requests — a classic exfiltration pattern.
4
4
  */
5
- const SENSITIVE_READ_RE = /readFile|readFileSync|fs\.read|open\(|\.ssh|\.env|credentials|\.aws|\.kube|\.npmrc|\.gitconfig|\.openclaw/i;
5
+ const SENSITIVE_READ_RE = /readFile|readFileSync|fs\.read|\/\.ssh\/|\/\.aws\/|\/\.kube\/|\/\.npmrc|\/\.gitconfig/i;
6
+ /** Patterns that look like sensitive reads but aren't */
7
+ const SENSITIVE_FALSE_POSITIVE_RE = /SSHException|SSHClient|ssh_exception|load_dotenv|dotenv|\.env\.example|\.env\.template|metadata\.openclaw/i;
8
+ /** Credential access patterns that are NORMAL in plugin/SDK context */
9
+ const SAFE_CREDENTIAL_RE = /self\.runtime\.credentials|this\.credentials|self\.config|tool_parameters|plugin_config|runtime\.credentials|provider_credentials/i;
6
10
  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
11
  const DYNAMIC_URL_RE = /fetch\s*\(\s*`[^`]*\$\{|fetch\s*\(\s*[a-zA-Z_]\w*\s*[+,)]/;
8
12
  export const dataExfilRule = {
@@ -19,12 +23,15 @@ export const dataExfilRule = {
19
23
  const hasHttpSend = HTTP_SEND_RE.test(content);
20
24
  // Critical: same file reads sensitive data AND sends it out
21
25
  if (hasSensitiveRead && hasHttpSend) {
26
+ // Check if "sensitive reads" are actually safe credential access (plugin SDK patterns)
27
+ const hasSafeCredentials = SAFE_CREDENTIAL_RE.test(content);
22
28
  // Find the specific lines
23
29
  const readLines = [];
24
30
  const sendLines = [];
25
31
  for (let i = 0; i < file.lines.length; i++) {
26
32
  const line = file.lines[i];
27
- if (SENSITIVE_READ_RE.test(line))
33
+ // Skip lines that are safe credential access or false positive patterns
34
+ if (SENSITIVE_READ_RE.test(line) && !SAFE_CREDENTIAL_RE.test(line) && !SENSITIVE_FALSE_POSITIVE_RE.test(line))
28
35
  readLines.push(i + 1);
29
36
  if (HTTP_SEND_RE.test(line))
30
37
  sendLines.push(i + 1);
@@ -32,13 +39,17 @@ export const dataExfilRule = {
32
39
  if (readLines.length > 0 && sendLines.length > 0) {
33
40
  findings.push({
34
41
  rule: "data-exfil",
35
- severity: "critical",
42
+ severity: "high",
36
43
  file: file.relativePath,
37
44
  line: sendLines[0],
38
45
  message: `Reads sensitive data (line ${readLines.join(",")}) and sends HTTP request (line ${sendLines.join(",")}) — possible exfiltration`,
39
46
  evidence: file.lines[sendLines[0] - 1]?.trim().slice(0, 120),
40
47
  });
41
48
  }
49
+ else if (hasSafeCredentials && sendLines.length > 0) {
50
+ // Credential access + HTTP is normal for API plugins — skip entirely
51
+ // (don't even report as medium — this is expected behavior)
52
+ }
42
53
  }
43
54
  // Warning: dynamic URL construction in fetch/request calls
44
55
  for (let i = 0; i < file.lines.length; i++) {
@@ -46,7 +57,7 @@ export const dataExfilRule = {
46
57
  if (DYNAMIC_URL_RE.test(line)) {
47
58
  findings.push({
48
59
  rule: "data-exfil",
49
- severity: "warning",
60
+ severity: "medium",
50
61
  file: file.relativePath,
51
62
  line: i + 1,
52
63
  message: "Dynamic URL construction in HTTP request — potential SSRF",
@@ -1 +1 @@
1
- {"version":3,"file":"data-exfil.js","sourceRoot":"","sources":["../../src/rules/data-exfil.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-exfil.js","sourceRoot":"","sources":["../../src/rules/data-exfil.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const descriptionIntegrityRule: Rule;
@@ -0,0 +1,204 @@
1
+ // Extract tool declarations from YAML/JSON configs
2
+ function extractToolDeclarations(files) {
3
+ const tools = [];
4
+ for (const file of files) {
5
+ if (![".yaml", ".yml", ".json"].includes(file.ext))
6
+ continue;
7
+ // YAML tool definitions (Dify, OpenClaw, MCP)
8
+ const nameMatch = file.content.match(/(?:^|\n)\s*(?:name|tool_name)\s*:\s*["']?([^"'\n]+)/);
9
+ const descMatch = file.content.match(/(?:^|\n)\s*(?:description|desc)\s*:\s*["']?([^"'\n]+)/);
10
+ // Multi-line description
11
+ const descBlockMatch = file.content.match(/(?:^|\n)\s*description\s*:\s*>\s*\n([\s\S]*?)(?:\n\S|\n$)/);
12
+ if (nameMatch || descMatch) {
13
+ tools.push({
14
+ name: nameMatch?.[1]?.trim() || file.relativePath,
15
+ description: (descBlockMatch?.[1] || descMatch?.[1] || "").trim().toLowerCase(),
16
+ file: file.relativePath,
17
+ });
18
+ }
19
+ // JSON tool definitions (MCP)
20
+ if (file.ext === ".json") {
21
+ try {
22
+ const json = JSON.parse(file.content);
23
+ if (json.tools) {
24
+ for (const tool of Object.values(json.tools)) {
25
+ if (tool.description) {
26
+ tools.push({
27
+ name: tool.name || "unknown",
28
+ description: (tool.description || "").toLowerCase(),
29
+ file: file.relativePath,
30
+ });
31
+ }
32
+ }
33
+ }
34
+ }
35
+ catch { }
36
+ }
37
+ }
38
+ return tools;
39
+ }
40
+ // Analyze code behavior
41
+ function analyzeCodeBehavior(files) {
42
+ const behaviors = [];
43
+ for (const file of files) {
44
+ if (![".py", ".ts", ".js", ".sh"].includes(file.ext))
45
+ continue;
46
+ if (file.context === "test")
47
+ continue;
48
+ const c = file.content;
49
+ behaviors.push({
50
+ file: file.relativePath,
51
+ hasNetworkAccess: /requests\.\w+\s*\(|fetch\s*\(|urllib|http\.request|axios|httpx/i.test(c),
52
+ hasFileWrite: /writeFile|writeFileSync|open\s*\([^)]*['"]w|\.write\s*\(|shutil\.copy|shutil\.move/i.test(c),
53
+ hasFileDelete: /unlink|rmtree|os\.remove|fs\.rm|shutil\.rmtree/i.test(c),
54
+ hasCodeExec: /\beval\s*\(|\bexec\s*\(|subprocess|os\.system|os\.popen|child_process/i.test(c),
55
+ hasEnvAccess: /os\.environ|os\.getenv|process\.env|dotenv/i.test(c),
56
+ hasCryptoOps: /hashlib|hmac|crypto\.|bcrypt|jwt\.|encrypt|decrypt/i.test(c),
57
+ hasDbAccess: /sqlite|psycopg|mysql|pymongo|redis\.|sqlalchemy|cursor\.execute/i.test(c),
58
+ sendsEmail: /smtplib|email\.mime|sendmail|send_mail/i.test(c),
59
+ spawnsProcess: /subprocess\.(?:run|call|Popen)|os\.system|child_process\.exec/i.test(c),
60
+ });
61
+ }
62
+ return behaviors;
63
+ }
64
+ // Keywords that indicate a tool claims to be limited/safe
65
+ const SAFE_CLAIMS = {
66
+ readOnly: /\bread[\s-]?only\b|only\s+read|does\s+not\s+(?:write|modify|delete)|no\s+(?:write|modify|side\s*effect)/i,
67
+ localOnly: /\blocal[\s-]?only\b|offline|no\s+(?:network|internet|http|api\s+call)|does\s+not\s+(?:connect|send|request)/i,
68
+ noExec: /\bsafe\b.*\bno\s+(?:exec|code\s+execution)|does\s+not\s+(?:execute|run)\s+(?:code|commands?)/i,
69
+ noData: /\bno\s+(?:data|file)\s+(?:access|collection)|does\s+not\s+(?:access|collect|read)\s+(?:data|files?|personal)/i,
70
+ };
71
+ // Keywords that indicate a narrow scope
72
+ const NARROW_SCOPE_KEYWORDS = {
73
+ calculator: /\b(?:calculator?|math|arithmetic|compute|calculate)\b/i,
74
+ formatter: /\b(?:format|beautif|prettif|lint|style)\b/i,
75
+ validator: /\b(?:validat|verify|check|lint)\b/i,
76
+ converter: /\b(?:convert|transform|translate|encode|decode)\b/i,
77
+ search: /\b(?:search|find|query|lookup|look\s+up)\b/i,
78
+ };
79
+ export const descriptionIntegrityRule = {
80
+ id: "description-integrity",
81
+ name: "Description-Code Integrity",
82
+ description: "Detects mismatches between tool descriptions and actual code behavior",
83
+ run(files) {
84
+ const findings = [];
85
+ const declarations = extractToolDeclarations(files);
86
+ const behaviors = analyzeCodeBehavior(files);
87
+ if (declarations.length === 0 || behaviors.length === 0)
88
+ return findings;
89
+ // Aggregate all code behaviors
90
+ const aggregatedBehavior = {
91
+ file: ".",
92
+ hasNetworkAccess: behaviors.some(b => b.hasNetworkAccess),
93
+ hasFileWrite: behaviors.some(b => b.hasFileWrite),
94
+ hasFileDelete: behaviors.some(b => b.hasFileDelete),
95
+ hasCodeExec: behaviors.some(b => b.hasCodeExec),
96
+ hasEnvAccess: behaviors.some(b => b.hasEnvAccess),
97
+ hasCryptoOps: behaviors.some(b => b.hasCryptoOps),
98
+ hasDbAccess: behaviors.some(b => b.hasDbAccess),
99
+ sendsEmail: behaviors.some(b => b.sendsEmail),
100
+ spawnsProcess: behaviors.some(b => b.spawnsProcess),
101
+ };
102
+ for (const decl of declarations) {
103
+ const desc = decl.description;
104
+ // Check 1: Claims read-only but writes/deletes files
105
+ if (SAFE_CLAIMS.readOnly.test(desc)) {
106
+ if (aggregatedBehavior.hasFileWrite) {
107
+ const writers = behaviors.filter(b => b.hasFileWrite).map(b => b.file);
108
+ findings.push({
109
+ rule: "description-integrity",
110
+ severity: "high",
111
+ file: decl.file,
112
+ message: `Description claims "read-only" but code writes files in: ${writers.join(", ")}`,
113
+ confidence: "high",
114
+ });
115
+ }
116
+ if (aggregatedBehavior.hasFileDelete) {
117
+ const deleters = behaviors.filter(b => b.hasFileDelete).map(b => b.file);
118
+ findings.push({
119
+ rule: "description-integrity",
120
+ severity: "high",
121
+ file: decl.file,
122
+ message: `Description claims "read-only" but code deletes files in: ${deleters.join(", ")}`,
123
+ confidence: "high",
124
+ });
125
+ }
126
+ }
127
+ // Check 2: Claims local/offline but makes network requests
128
+ if (SAFE_CLAIMS.localOnly.test(desc)) {
129
+ if (aggregatedBehavior.hasNetworkAccess) {
130
+ const networkers = behaviors.filter(b => b.hasNetworkAccess).map(b => b.file);
131
+ findings.push({
132
+ rule: "description-integrity",
133
+ severity: "high",
134
+ file: decl.file,
135
+ message: `Description claims "local only/offline" but code makes network requests in: ${networkers.join(", ")}`,
136
+ confidence: "high",
137
+ });
138
+ }
139
+ }
140
+ // Check 3: Claims no execution but runs eval/exec
141
+ if (SAFE_CLAIMS.noExec.test(desc)) {
142
+ if (aggregatedBehavior.hasCodeExec) {
143
+ const executors = behaviors.filter(b => b.hasCodeExec).map(b => b.file);
144
+ findings.push({
145
+ rule: "description-integrity",
146
+ severity: "high",
147
+ file: decl.file,
148
+ message: `Description claims "no code execution" but code uses eval/exec in: ${executors.join(", ")}`,
149
+ confidence: "high",
150
+ });
151
+ }
152
+ }
153
+ // Check 4: Claims no data access but reads env/files
154
+ if (SAFE_CLAIMS.noData.test(desc)) {
155
+ if (aggregatedBehavior.hasEnvAccess) {
156
+ findings.push({
157
+ rule: "description-integrity",
158
+ severity: "medium",
159
+ file: decl.file,
160
+ message: `Description claims "no data access" but code reads environment variables`,
161
+ confidence: "medium",
162
+ });
163
+ }
164
+ }
165
+ // Check 5: Narrow scope tool with undisclosed capabilities
166
+ for (const [scope, pattern] of Object.entries(NARROW_SCOPE_KEYWORDS)) {
167
+ if (pattern.test(desc)) {
168
+ // Calculator/formatter/validator shouldn't need network or exec
169
+ if (aggregatedBehavior.hasNetworkAccess && !desc.includes("api") && !desc.includes("http") && !desc.includes("online")) {
170
+ const networkers = behaviors.filter(b => b.hasNetworkAccess).map(b => b.file);
171
+ findings.push({
172
+ rule: "description-integrity",
173
+ severity: "medium",
174
+ file: decl.file,
175
+ message: `Scope creep: "${scope}" tool makes undisclosed network requests in: ${networkers.join(", ")}`,
176
+ confidence: "medium",
177
+ });
178
+ }
179
+ if (aggregatedBehavior.sendsEmail) {
180
+ findings.push({
181
+ rule: "description-integrity",
182
+ severity: "high",
183
+ file: decl.file,
184
+ message: `Scope creep: "${scope}" tool sends emails — undisclosed and suspicious capability`,
185
+ confidence: "high",
186
+ });
187
+ }
188
+ if (aggregatedBehavior.spawnsProcess && scope !== "converter") {
189
+ findings.push({
190
+ rule: "description-integrity",
191
+ severity: "medium",
192
+ file: decl.file,
193
+ message: `Scope creep: "${scope}" tool spawns processes — undisclosed capability`,
194
+ confidence: "medium",
195
+ });
196
+ }
197
+ break; // Only match first scope
198
+ }
199
+ }
200
+ }
201
+ return findings;
202
+ },
203
+ };
204
+ //# sourceMappingURL=description-integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"description-integrity.js","sourceRoot":"","sources":["../../src/rules/description-integrity.ts"],"names":[],"mappings":"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"}
@@ -28,7 +28,7 @@ export const envLeakRule = {
28
28
  if (envLines.length > 0 && sendLines.length > 0) {
29
29
  findings.push({
30
30
  rule: "env-leak",
31
- severity: "critical",
31
+ severity: "medium",
32
32
  file: file.relativePath,
33
33
  line: sendLines[0],
34
34
  message: `Reads environment variables (line ${envLines.join(",")}) and sends HTTP request (line ${sendLines.join(",")}) — possible env leak`,
@@ -1 +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"}
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,QAAQ;wBAClB,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"}
@@ -29,7 +29,7 @@ export const excessivePermsRule = {
29
29
  if (DANGEROUS_PERMS.has(perm.toLowerCase())) {
30
30
  findings.push({
31
31
  rule: "excessive-perms",
32
- severity: "warning",
32
+ severity: "low",
33
33
  file: skillMd.relativePath,
34
34
  message: `Requests dangerous permission: '${perm}'`,
35
35
  });
@@ -39,7 +39,7 @@ export const excessivePermsRule = {
39
39
  if (permissions.length > MAX_REASONABLE_PERMS) {
40
40
  findings.push({
41
41
  rule: "excessive-perms",
42
- severity: "warning",
42
+ severity: "low",
43
43
  file: skillMd.relativePath,
44
44
  message: `Requests ${permissions.length} permissions (threshold: ${MAX_REASONABLE_PERMS}) — review if all are necessary`,
45
45
  });
@@ -1 +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"}
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,KAAK;oBACf,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,KAAK;gBACf,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"}
@@ -24,7 +24,7 @@ export const hiddenFilesRule = {
24
24
  if (pattern.test(basename)) {
25
25
  findings.push({
26
26
  rule: "hidden-files",
27
- severity: "critical",
27
+ severity: "low",
28
28
  file: file.relativePath,
29
29
  message: `${desc} found in repository — should be in .gitignore`,
30
30
  });
@@ -34,7 +34,7 @@ export const hiddenFilesRule = {
34
34
  if (SECRET_IN_ENV_RE.test(line) && !line.trimStart().startsWith("#")) {
35
35
  findings.push({
36
36
  rule: "hidden-files",
37
- severity: "critical",
37
+ severity: "low",
38
38
  file: file.relativePath,
39
39
  line: i + 1,
40
40
  message: "Hardcoded secret in environment file",