mitnick-cli 1.0.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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/analyzers/analyzer.interface.d.ts +32 -0
  4. package/dist/analyzers/analyzer.interface.d.ts.map +1 -0
  5. package/dist/analyzers/analyzer.interface.js +2 -0
  6. package/dist/analyzers/analyzer.interface.js.map +1 -0
  7. package/dist/analyzers/analyzer.registry.d.ts +16 -0
  8. package/dist/analyzers/analyzer.registry.d.ts.map +1 -0
  9. package/dist/analyzers/analyzer.registry.js +40 -0
  10. package/dist/analyzers/analyzer.registry.js.map +1 -0
  11. package/dist/analyzers/dependency-confusion/index.d.ts +14 -0
  12. package/dist/analyzers/dependency-confusion/index.d.ts.map +1 -0
  13. package/dist/analyzers/dependency-confusion/index.js +147 -0
  14. package/dist/analyzers/dependency-confusion/index.js.map +1 -0
  15. package/dist/analyzers/dormant-package/index.d.ts +14 -0
  16. package/dist/analyzers/dormant-package/index.d.ts.map +1 -0
  17. package/dist/analyzers/dormant-package/index.js +137 -0
  18. package/dist/analyzers/dormant-package/index.js.map +1 -0
  19. package/dist/analyzers/file-based-analyzer.d.ts +20 -0
  20. package/dist/analyzers/file-based-analyzer.d.ts.map +1 -0
  21. package/dist/analyzers/file-based-analyzer.js +35 -0
  22. package/dist/analyzers/file-based-analyzer.js.map +1 -0
  23. package/dist/analyzers/install-scripts/index.d.ts +13 -0
  24. package/dist/analyzers/install-scripts/index.d.ts.map +1 -0
  25. package/dist/analyzers/install-scripts/index.js +125 -0
  26. package/dist/analyzers/install-scripts/index.js.map +1 -0
  27. package/dist/analyzers/license/index.d.ts +12 -0
  28. package/dist/analyzers/license/index.d.ts.map +1 -0
  29. package/dist/analyzers/license/index.js +199 -0
  30. package/dist/analyzers/license/index.js.map +1 -0
  31. package/dist/analyzers/maintainer/index.d.ts +12 -0
  32. package/dist/analyzers/maintainer/index.d.ts.map +1 -0
  33. package/dist/analyzers/maintainer/index.js +93 -0
  34. package/dist/analyzers/maintainer/index.js.map +1 -0
  35. package/dist/analyzers/network-calls/index.d.ts +15 -0
  36. package/dist/analyzers/network-calls/index.d.ts.map +1 -0
  37. package/dist/analyzers/network-calls/index.js +212 -0
  38. package/dist/analyzers/network-calls/index.js.map +1 -0
  39. package/dist/analyzers/obfuscation/index.d.ts +19 -0
  40. package/dist/analyzers/obfuscation/index.d.ts.map +1 -0
  41. package/dist/analyzers/obfuscation/index.js +218 -0
  42. package/dist/analyzers/obfuscation/index.js.map +1 -0
  43. package/dist/analyzers/prototype-pollution/index.d.ts +18 -0
  44. package/dist/analyzers/prototype-pollution/index.d.ts.map +1 -0
  45. package/dist/analyzers/prototype-pollution/index.js +257 -0
  46. package/dist/analyzers/prototype-pollution/index.js.map +1 -0
  47. package/dist/analyzers/sensitive-data/index.d.ts +16 -0
  48. package/dist/analyzers/sensitive-data/index.d.ts.map +1 -0
  49. package/dist/analyzers/sensitive-data/index.js +254 -0
  50. package/dist/analyzers/sensitive-data/index.js.map +1 -0
  51. package/dist/analyzers/typosquatting/index.d.ts +14 -0
  52. package/dist/analyzers/typosquatting/index.d.ts.map +1 -0
  53. package/dist/analyzers/typosquatting/index.js +127 -0
  54. package/dist/analyzers/typosquatting/index.js.map +1 -0
  55. package/dist/analyzers/typosquatting/popular-packages.d.ts +9 -0
  56. package/dist/analyzers/typosquatting/popular-packages.d.ts.map +1 -0
  57. package/dist/analyzers/typosquatting/popular-packages.js +236 -0
  58. package/dist/analyzers/typosquatting/popular-packages.js.map +1 -0
  59. package/dist/analyzers/vulnerability/index.d.ts +12 -0
  60. package/dist/analyzers/vulnerability/index.d.ts.map +1 -0
  61. package/dist/analyzers/vulnerability/index.js +147 -0
  62. package/dist/analyzers/vulnerability/index.js.map +1 -0
  63. package/dist/cli/commands/check.d.ts +21 -0
  64. package/dist/cli/commands/check.d.ts.map +1 -0
  65. package/dist/cli/commands/check.js +204 -0
  66. package/dist/cli/commands/check.js.map +1 -0
  67. package/dist/cli/formatters/formatter.interface.d.ts +14 -0
  68. package/dist/cli/formatters/formatter.interface.d.ts.map +1 -0
  69. package/dist/cli/formatters/formatter.interface.js +2 -0
  70. package/dist/cli/formatters/formatter.interface.js.map +1 -0
  71. package/dist/cli/formatters/json.d.ts +12 -0
  72. package/dist/cli/formatters/json.d.ts.map +1 -0
  73. package/dist/cli/formatters/json.js +12 -0
  74. package/dist/cli/formatters/json.js.map +1 -0
  75. package/dist/cli/formatters/sarif.d.ts +13 -0
  76. package/dist/cli/formatters/sarif.d.ts.map +1 -0
  77. package/dist/cli/formatters/sarif.js +101 -0
  78. package/dist/cli/formatters/sarif.js.map +1 -0
  79. package/dist/cli/formatters/terminal.d.ts +13 -0
  80. package/dist/cli/formatters/terminal.d.ts.map +1 -0
  81. package/dist/cli/formatters/terminal.js +110 -0
  82. package/dist/cli/formatters/terminal.js.map +1 -0
  83. package/dist/cli/index.d.ts +9 -0
  84. package/dist/cli/index.d.ts.map +1 -0
  85. package/dist/cli/index.js +86 -0
  86. package/dist/cli/index.js.map +1 -0
  87. package/dist/core/engine.d.ts +23 -0
  88. package/dist/core/engine.d.ts.map +1 -0
  89. package/dist/core/engine.js +55 -0
  90. package/dist/core/engine.js.map +1 -0
  91. package/dist/core/scorer.d.ts +30 -0
  92. package/dist/core/scorer.d.ts.map +1 -0
  93. package/dist/core/scorer.js +88 -0
  94. package/dist/core/scorer.js.map +1 -0
  95. package/dist/core/types.d.ts +76 -0
  96. package/dist/core/types.d.ts.map +1 -0
  97. package/dist/core/types.js +30 -0
  98. package/dist/core/types.js.map +1 -0
  99. package/dist/index.d.ts +33 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +30 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/registry/client.d.ts +27 -0
  104. package/dist/registry/client.d.ts.map +1 -0
  105. package/dist/registry/client.js +189 -0
  106. package/dist/registry/client.js.map +1 -0
  107. package/dist/registry/tarball.d.ts +34 -0
  108. package/dist/registry/tarball.d.ts.map +1 -0
  109. package/dist/registry/tarball.js +103 -0
  110. package/dist/registry/tarball.js.map +1 -0
  111. package/dist/utils/ast.d.ts +74 -0
  112. package/dist/utils/ast.d.ts.map +1 -0
  113. package/dist/utils/ast.js +150 -0
  114. package/dist/utils/ast.js.map +1 -0
  115. package/dist/utils/fs.d.ts +28 -0
  116. package/dist/utils/fs.d.ts.map +1 -0
  117. package/dist/utils/fs.js +78 -0
  118. package/dist/utils/fs.js.map +1 -0
  119. package/dist/utils/http.d.ts +40 -0
  120. package/dist/utils/http.d.ts.map +1 -0
  121. package/dist/utils/http.js +116 -0
  122. package/dist/utils/http.js.map +1 -0
  123. package/dist/utils/logger.d.ts +46 -0
  124. package/dist/utils/logger.d.ts.map +1 -0
  125. package/dist/utils/logger.js +91 -0
  126. package/dist/utils/logger.js.map +1 -0
  127. package/dist/utils/strings.d.ts +8 -0
  128. package/dist/utils/strings.d.ts.map +1 -0
  129. package/dist/utils/strings.js +12 -0
  130. package/dist/utils/strings.js.map +1 -0
  131. package/package.json +96 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Network Call Analyzer — detects outbound HTTP requests, WebSocket
3
+ * connections, hardcoded IPs, and imports of networking libraries.
4
+ */
5
+ import { parseSource, walkAST, getNodeLine, isCallTo, optionalLine } from '../../utils/ast.js';
6
+ import { FileBasedAnalyzer } from '../file-based-analyzer.js';
7
+ // ─── Constants ────────────────────────────────────────────
8
+ const NETWORKING_MODULES = new Set([
9
+ 'axios',
10
+ 'got',
11
+ 'node-fetch',
12
+ 'request',
13
+ 'superagent',
14
+ 'urllib',
15
+ 'undici',
16
+ 'ky',
17
+ 'bent',
18
+ 'phin',
19
+ ]);
20
+ const HARDCODED_IP_REGEX = /\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g;
21
+ /** IPs that are generally safe / not suspicious. */
22
+ const SAFE_IPS = new Set(['127.0.0.1', '0.0.0.0', '255.255.255.255']);
23
+ // ─── Analyzer ─────────────────────────────────────────────
24
+ export class NetworkCallsAnalyzer extends FileBasedAnalyzer {
25
+ name = 'network-calls';
26
+ description = 'Detects outbound network requests, hardcoded IPs, and networking library imports';
27
+ analyzeFile(source, relPath) {
28
+ const findings = [];
29
+ findings.push(...this.detectNetworkAPIs(source, relPath));
30
+ findings.push(...this.detectNetworkImports(source, relPath));
31
+ findings.push(...this.detectHardcodedIPs(source, relPath));
32
+ return findings;
33
+ }
34
+ detectNetworkAPIs(source, relPath) {
35
+ const findings = [];
36
+ const parsed = parseSource(source, relPath);
37
+ if (!parsed.ok)
38
+ return findings;
39
+ const seenAPIs = new Set();
40
+ walkAST(parsed.ast, (node) => {
41
+ // fetch()
42
+ if (isCallTo(node, 'fetch') && !seenAPIs.has('fetch')) {
43
+ seenAPIs.add('fetch');
44
+ findings.push({
45
+ analyzer: this.name,
46
+ severity: 'medium',
47
+ title: 'fetch() call detected',
48
+ description: 'The package makes outbound HTTP requests using the fetch API.',
49
+ file: relPath,
50
+ ...optionalLine(getNodeLine(node)),
51
+ recommendation: 'Verify the fetch targets are expected and not exfiltrating data.',
52
+ });
53
+ }
54
+ // http.request(), http.get(), https.request(), https.get()
55
+ if (node.type === 'CallExpression') {
56
+ const callee = node['callee'];
57
+ if (typeof callee === 'object' && callee !== null) {
58
+ const calleeNode = callee;
59
+ if (calleeNode['type'] === 'MemberExpression') {
60
+ const obj = calleeNode['object'];
61
+ const prop = calleeNode['property'];
62
+ if (obj?.['type'] === 'Identifier' &&
63
+ (obj['name'] === 'http' || obj['name'] === 'https') &&
64
+ prop?.['type'] === 'Identifier' &&
65
+ (prop['name'] === 'request' || prop['name'] === 'get')) {
66
+ const apiName = `${obj['name']}.${prop['name']}`;
67
+ if (!seenAPIs.has(apiName)) {
68
+ seenAPIs.add(apiName);
69
+ findings.push({
70
+ analyzer: this.name,
71
+ severity: 'medium',
72
+ title: `${apiName}() call detected`,
73
+ description: `The package uses Node.js ${apiName}() for outbound HTTP requests.`,
74
+ file: relPath,
75
+ ...optionalLine(getNodeLine(node)),
76
+ recommendation: 'Verify that the HTTP targets are expected endpoints.',
77
+ });
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ // XMLHttpRequest
84
+ if (node.type === 'NewExpression' &&
85
+ typeof node['callee'] === 'object' &&
86
+ node['callee'] !== null &&
87
+ node['callee']['type'] === 'Identifier' &&
88
+ node['callee']['name'] === 'XMLHttpRequest' &&
89
+ !seenAPIs.has('XMLHttpRequest')) {
90
+ seenAPIs.add('XMLHttpRequest');
91
+ findings.push({
92
+ analyzer: this.name,
93
+ severity: 'medium',
94
+ title: 'XMLHttpRequest usage detected',
95
+ description: 'The package creates XMLHttpRequest instances for HTTP communication.',
96
+ file: relPath,
97
+ ...optionalLine(getNodeLine(node)),
98
+ recommendation: 'Review the network communication targets.',
99
+ });
100
+ }
101
+ // new WebSocket(...)
102
+ if (node.type === 'NewExpression' &&
103
+ typeof node['callee'] === 'object' &&
104
+ node['callee'] !== null &&
105
+ node['callee']['type'] === 'Identifier' &&
106
+ node['callee']['name'] === 'WebSocket' &&
107
+ !seenAPIs.has('WebSocket')) {
108
+ seenAPIs.add('WebSocket');
109
+ findings.push({
110
+ analyzer: this.name,
111
+ severity: 'medium',
112
+ title: 'WebSocket connection detected',
113
+ description: 'The package creates WebSocket connections for real-time communication.',
114
+ file: relPath,
115
+ ...optionalLine(getNodeLine(node)),
116
+ recommendation: 'Verify the WebSocket server URL and intended use.',
117
+ });
118
+ }
119
+ });
120
+ return findings;
121
+ }
122
+ detectNetworkImports(source, relPath) {
123
+ const findings = [];
124
+ const parsed = parseSource(source, relPath);
125
+ if (!parsed.ok)
126
+ return findings;
127
+ const seenImports = new Set();
128
+ walkAST(parsed.ast, (node) => {
129
+ // import declarations: import axios from 'axios'
130
+ if (node.type === 'ImportDeclaration') {
131
+ const moduleSource = node['source'];
132
+ if (typeof moduleSource === 'object' && moduleSource !== null) {
133
+ const value = moduleSource['value'];
134
+ if (typeof value === 'string' &&
135
+ NETWORKING_MODULES.has(value) &&
136
+ !seenImports.has(value)) {
137
+ seenImports.add(value);
138
+ findings.push({
139
+ analyzer: this.name,
140
+ severity: 'medium',
141
+ title: `Networking library imported: ${value}`,
142
+ description: `The package imports "${value}", an HTTP networking library.`,
143
+ file: relPath,
144
+ ...optionalLine(getNodeLine(node)),
145
+ recommendation: 'Review how this library is used in the package.',
146
+ });
147
+ }
148
+ }
149
+ }
150
+ // require() calls: const axios = require('axios')
151
+ if (isCallTo(node, 'require')) {
152
+ const args = node['arguments'];
153
+ if (Array.isArray(args) && args.length > 0) {
154
+ const firstArg = args[0];
155
+ if (firstArg?.['type'] === 'Literal' && typeof firstArg['value'] === 'string') {
156
+ const moduleName = firstArg['value'];
157
+ if (NETWORKING_MODULES.has(moduleName) && !seenImports.has(moduleName)) {
158
+ seenImports.add(moduleName);
159
+ findings.push({
160
+ analyzer: this.name,
161
+ severity: 'medium',
162
+ title: `Networking library required: ${moduleName}`,
163
+ description: `The package requires "${moduleName}", an HTTP networking library.`,
164
+ file: relPath,
165
+ ...optionalLine(getNodeLine(node)),
166
+ recommendation: 'Review how this library is used in the package.',
167
+ });
168
+ }
169
+ }
170
+ }
171
+ }
172
+ });
173
+ return findings;
174
+ }
175
+ detectHardcodedIPs(source, relPath) {
176
+ const findings = [];
177
+ const seenIPs = new Set();
178
+ const lines = source.split('\n');
179
+ for (let i = 0; i < lines.length; i++) {
180
+ const line = lines[i];
181
+ if (line === undefined)
182
+ continue;
183
+ let match;
184
+ HARDCODED_IP_REGEX.lastIndex = 0;
185
+ while ((match = HARDCODED_IP_REGEX.exec(line)) !== null) {
186
+ const ip = match[1];
187
+ if (ip === undefined || SAFE_IPS.has(ip) || seenIPs.has(ip))
188
+ continue;
189
+ const octets = ip.split('.');
190
+ const isValidIP = octets.every((o) => {
191
+ const n = parseInt(o, 10);
192
+ return n >= 0 && n <= 255;
193
+ });
194
+ if (!isValidIP)
195
+ continue;
196
+ seenIPs.add(ip);
197
+ findings.push({
198
+ analyzer: this.name,
199
+ severity: 'high',
200
+ title: `Hardcoded IP address: ${ip}`,
201
+ description: `A hardcoded IP address (${ip}) was found. ` +
202
+ 'Hardcoded IPs in packages may indicate data exfiltration or C2 communication.',
203
+ file: relPath,
204
+ line: i + 1,
205
+ recommendation: 'Investigate what this IP address is used for.',
206
+ });
207
+ }
208
+ }
209
+ return findings;
210
+ }
211
+ }
212
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/network-calls/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Obfuscation Analyzer — detects obfuscated code via entropy analysis,
3
+ * eval/Function patterns, base64 blobs, and hex-encoded strings.
4
+ */
5
+ import type { AnalysisContext, AnalyzerResult, Finding } from '../../core/types.js';
6
+ import { FileBasedAnalyzer } from '../file-based-analyzer.js';
7
+ export declare class ObfuscationAnalyzer extends FileBasedAnalyzer {
8
+ readonly name = "obfuscation";
9
+ readonly description = "Detects obfuscated code using entropy analysis and pattern matching";
10
+ analyze(context: AnalysisContext): Promise<AnalyzerResult>;
11
+ protected analyzeFile(source: string, relPath: string): Finding[];
12
+ private detectDynamicExecution;
13
+ private detectBufferBase64;
14
+ private detectHighEntropyStrings;
15
+ private detectHexEncoded;
16
+ private detectBase64Blobs;
17
+ private escalateEvalPlusObfuscation;
18
+ }
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/obfuscation/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AASpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAkC9D,qBAAa,mBAAoB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,yEAAyE;IAEvF,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAYhE,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE;IAYjE,OAAO,CAAC,sBAAsB;IA0C9B,OAAO,CAAC,kBAAkB;IA6C1B,OAAO,CAAC,wBAAwB;IAyChC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,2BAA2B;CA6BpC"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Obfuscation Analyzer — detects obfuscated code via entropy analysis,
3
+ * eval/Function patterns, base64 blobs, and hex-encoded strings.
4
+ */
5
+ import { parseSource, walkAST, extractStringLiterals, getNodeLine, isCallTo, optionalLine, } from '../../utils/ast.js';
6
+ import { FileBasedAnalyzer } from '../file-based-analyzer.js';
7
+ // ─── Constants ────────────────────────────────────────────
8
+ const ENTROPY_THRESHOLD = 4.5;
9
+ const MIN_STRING_LENGTH_FOR_ENTROPY = 20;
10
+ const BASE64_MIN_LENGTH = 256;
11
+ const BASE64_PATTERN = /^[A-Za-z0-9+/=]{256,}$/;
12
+ const HEX_ENCODED_PATTERN = /(\\x[0-9a-fA-F]{2}){8,}/;
13
+ // ─── Helpers ──────────────────────────────────────────────
14
+ function shannonEntropy(str) {
15
+ if (str.length === 0)
16
+ return 0;
17
+ const freq = new Map();
18
+ for (const char of str) {
19
+ freq.set(char, (freq.get(char) ?? 0) + 1);
20
+ }
21
+ let entropy = 0;
22
+ const len = str.length;
23
+ for (const count of freq.values()) {
24
+ const p = count / len;
25
+ if (p > 0) {
26
+ entropy -= p * Math.log2(p);
27
+ }
28
+ }
29
+ return entropy;
30
+ }
31
+ // ─── Analyzer ─────────────────────────────────────────────
32
+ export class ObfuscationAnalyzer extends FileBasedAnalyzer {
33
+ name = 'obfuscation';
34
+ description = 'Detects obfuscated code using entropy analysis and pattern matching';
35
+ async analyze(context) {
36
+ const result = await super.analyze(context);
37
+ // Escalate if both eval and obfuscation signals are present in the same package
38
+ const escalation = this.escalateEvalPlusObfuscation(result.findings);
39
+ return {
40
+ ...result,
41
+ findings: [...result.findings, ...escalation],
42
+ };
43
+ }
44
+ analyzeFile(source, relPath) {
45
+ const findings = [];
46
+ findings.push(...this.detectDynamicExecution(source, relPath));
47
+ findings.push(...this.detectBufferBase64(source, relPath));
48
+ findings.push(...this.detectHighEntropyStrings(source, relPath));
49
+ findings.push(...this.detectHexEncoded(source, relPath));
50
+ findings.push(...this.detectBase64Blobs(source, relPath));
51
+ return findings;
52
+ }
53
+ detectDynamicExecution(source, relPath) {
54
+ const findings = [];
55
+ const parsed = parseSource(source, relPath);
56
+ if (!parsed.ok)
57
+ return findings;
58
+ walkAST(parsed.ast, (node) => {
59
+ if (isCallTo(node, 'eval')) {
60
+ findings.push({
61
+ analyzer: this.name,
62
+ severity: 'high',
63
+ title: 'eval() detected',
64
+ description: 'Use of eval() can execute arbitrary code and is a common obfuscation technique.',
65
+ file: relPath,
66
+ ...optionalLine(getNodeLine(node)),
67
+ recommendation: 'Review the eval() usage and consider replacing with safer alternatives.',
68
+ });
69
+ }
70
+ if (node.type === 'NewExpression' &&
71
+ typeof node['callee'] === 'object' &&
72
+ node['callee'] !== null &&
73
+ node['callee']['type'] === 'Identifier' &&
74
+ node['callee']['name'] === 'Function') {
75
+ findings.push({
76
+ analyzer: this.name,
77
+ severity: 'high',
78
+ title: 'new Function() detected',
79
+ description: 'new Function() dynamically creates code from strings, commonly used for obfuscation.',
80
+ file: relPath,
81
+ ...optionalLine(getNodeLine(node)),
82
+ recommendation: 'Review the dynamic function creation and ensure it is not malicious.',
83
+ });
84
+ }
85
+ });
86
+ return findings;
87
+ }
88
+ detectBufferBase64(source, relPath) {
89
+ const findings = [];
90
+ const parsed = parseSource(source, relPath);
91
+ if (!parsed.ok)
92
+ return findings;
93
+ walkAST(parsed.ast, (node) => {
94
+ if (node.type !== 'CallExpression')
95
+ return;
96
+ const callee = node['callee'];
97
+ if (typeof callee !== 'object' || callee === null)
98
+ return;
99
+ const calleeNode = callee;
100
+ if (calleeNode['type'] !== 'MemberExpression')
101
+ return;
102
+ const obj = calleeNode['object'];
103
+ const prop = calleeNode['property'];
104
+ if (obj?.['type'] === 'Identifier' &&
105
+ obj['name'] === 'Buffer' &&
106
+ prop?.['type'] === 'Identifier' &&
107
+ prop['name'] === 'from') {
108
+ const args = node['arguments'];
109
+ if (Array.isArray(args) && args.length >= 2) {
110
+ const encodingArg = args[1];
111
+ if (encodingArg?.['type'] === 'Literal' && encodingArg['value'] === 'base64') {
112
+ findings.push({
113
+ analyzer: this.name,
114
+ severity: 'high',
115
+ title: 'Buffer.from() with base64 encoding',
116
+ description: 'Buffer.from(..., "base64") is commonly used to hide malicious payloads.',
117
+ file: relPath,
118
+ ...optionalLine(getNodeLine(node)),
119
+ recommendation: 'Decode and inspect the base64 content for malicious code.',
120
+ });
121
+ }
122
+ }
123
+ }
124
+ });
125
+ return findings;
126
+ }
127
+ detectHighEntropyStrings(source, relPath) {
128
+ const findings = [];
129
+ const strings = extractStringLiterals(source, relPath);
130
+ let flagCount = 0;
131
+ for (const str of strings) {
132
+ if (str.length < MIN_STRING_LENGTH_FOR_ENTROPY)
133
+ continue;
134
+ const entropy = shannonEntropy(str);
135
+ if (entropy > ENTROPY_THRESHOLD) {
136
+ flagCount++;
137
+ if (flagCount <= 5) {
138
+ findings.push({
139
+ analyzer: this.name,
140
+ severity: 'high',
141
+ title: 'High-entropy string detected',
142
+ description: `String literal with Shannon entropy ${entropy.toFixed(2)} ` +
143
+ `(threshold: ${ENTROPY_THRESHOLD}). Length: ${str.length} chars. ` +
144
+ `Preview: "${str.slice(0, 60)}..."`,
145
+ file: relPath,
146
+ recommendation: 'High-entropy strings may indicate encoded/encrypted malicious payloads.',
147
+ });
148
+ }
149
+ }
150
+ }
151
+ if (flagCount > 5) {
152
+ findings.push({
153
+ analyzer: this.name,
154
+ severity: 'high',
155
+ title: `${flagCount - 5} additional high-entropy strings omitted`,
156
+ description: `File contains ${flagCount} total high-entropy strings.`,
157
+ file: relPath,
158
+ recommendation: 'Manual review recommended for files with many high-entropy strings.',
159
+ });
160
+ }
161
+ return findings;
162
+ }
163
+ detectHexEncoded(source, relPath) {
164
+ const findings = [];
165
+ if (HEX_ENCODED_PATTERN.test(source)) {
166
+ findings.push({
167
+ analyzer: this.name,
168
+ severity: 'high',
169
+ title: 'Hex-encoded string sequences detected',
170
+ description: 'Long sequences of hex-encoded characters (\\xNN) were found, which may hide malicious content.',
171
+ file: relPath,
172
+ recommendation: 'Decode and inspect the hex content.',
173
+ });
174
+ }
175
+ return findings;
176
+ }
177
+ detectBase64Blobs(source, relPath) {
178
+ const findings = [];
179
+ const strings = extractStringLiterals(source, relPath);
180
+ for (const str of strings) {
181
+ if (str.length >= BASE64_MIN_LENGTH && BASE64_PATTERN.test(str)) {
182
+ findings.push({
183
+ analyzer: this.name,
184
+ severity: 'high',
185
+ title: 'Large Base64 blob detected',
186
+ description: `A Base64-encoded string of ${str.length} characters was found. ` +
187
+ `Large base64 blobs may contain hidden executable code.`,
188
+ file: relPath,
189
+ recommendation: 'Decode the base64 content and inspect it for malicious payloads.',
190
+ });
191
+ break;
192
+ }
193
+ }
194
+ return findings;
195
+ }
196
+ escalateEvalPlusObfuscation(findings) {
197
+ const hasEval = findings.some((f) => f.title.includes('eval()') || f.title.includes('new Function()'));
198
+ const hasObfuscation = findings.some((f) => f.title.includes('entropy') ||
199
+ f.title.includes('Base64') ||
200
+ f.title.includes('base64') ||
201
+ f.title.includes('Hex-encoded'));
202
+ if (hasEval && hasObfuscation) {
203
+ return [
204
+ {
205
+ analyzer: this.name,
206
+ severity: 'critical',
207
+ title: 'Eval combined with obfuscation signals',
208
+ description: 'This package contains both dynamic code execution (eval/new Function) and ' +
209
+ 'obfuscation indicators (high-entropy strings, base64, or hex encoding). ' +
210
+ 'This combination is a strong indicator of malicious intent.',
211
+ recommendation: 'Do NOT install this package without thorough manual review.',
212
+ },
213
+ ];
214
+ }
215
+ return [];
216
+ }
217
+ }
218
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/obfuscation/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Prototype Pollution Analyzer — detects __proto__ access, Object.prototype
3
+ * mutation, constructor.prototype patterns, and recursive merge/extend
4
+ * functions without hasOwnProperty guards.
5
+ */
6
+ import type { Finding } from '../../core/types.js';
7
+ import { FileBasedAnalyzer } from '../file-based-analyzer.js';
8
+ export declare class PrototypePollutionAnalyzer extends FileBasedAnalyzer {
9
+ readonly name = "prototype-pollution";
10
+ readonly description = "Detects prototype pollution vectors including __proto__ access and unsafe merge patterns";
11
+ protected analyzeFile(source: string, relPath: string): Finding[];
12
+ private detectProtoAccess;
13
+ private detectPrototypeMutation;
14
+ private detectConstructorPrototype;
15
+ private detectUnsafeMerge;
16
+ private bodyHasOwnPropertyGuard;
17
+ }
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/prototype-pollution/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA0B9D,qBAAa,0BAA2B,SAAQ,iBAAiB;IAC/D,QAAQ,CAAC,IAAI,yBAAyB;IACtC,QAAQ,CAAC,WAAW,8FACyE;IAE7F,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE;IAWjE,OAAO,CAAC,iBAAiB;IA8DzB,OAAO,CAAC,uBAAuB;IA0C/B,OAAO,CAAC,0BAA0B;IAgClC,OAAO,CAAC,iBAAiB;IAwEzB,OAAO,CAAC,uBAAuB;CA8ChC"}