tangkal 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +62 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +4 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/analyzers/dependencies.d.ts +4 -0
  7. package/dist/src/analyzers/dependencies.d.ts.map +1 -0
  8. package/dist/src/analyzers/dependencies.js +79 -0
  9. package/dist/src/analyzers/dependencies.js.map +1 -0
  10. package/dist/src/analyzers/network.d.ts +17 -0
  11. package/dist/src/analyzers/network.d.ts.map +1 -0
  12. package/dist/src/analyzers/network.js +203 -0
  13. package/dist/src/analyzers/network.js.map +1 -0
  14. package/dist/src/analyzers/static-analysis.d.ts +18 -0
  15. package/dist/src/analyzers/static-analysis.d.ts.map +1 -0
  16. package/dist/src/analyzers/static-analysis.js +246 -0
  17. package/dist/src/analyzers/static-analysis.js.map +1 -0
  18. package/dist/src/cli.d.ts +2 -0
  19. package/dist/src/cli.d.ts.map +1 -0
  20. package/dist/src/cli.js +112 -0
  21. package/dist/src/cli.js.map +1 -0
  22. package/dist/src/config.d.ts +9 -0
  23. package/dist/src/config.d.ts.map +1 -0
  24. package/dist/src/config.js +40 -0
  25. package/dist/src/config.js.map +1 -0
  26. package/dist/src/scanner.d.ts +8 -0
  27. package/dist/src/scanner.d.ts.map +1 -0
  28. package/dist/src/scanner.js +115 -0
  29. package/dist/src/scanner.js.map +1 -0
  30. package/dist/src/utils/entropy.d.ts +7 -0
  31. package/dist/src/utils/entropy.d.ts.map +1 -0
  32. package/dist/src/utils/entropy.js +25 -0
  33. package/dist/src/utils/entropy.js.map +1 -0
  34. package/dist/src/utils/ignore.d.ts +3 -0
  35. package/dist/src/utils/ignore.d.ts.map +1 -0
  36. package/dist/src/utils/ignore.js +18 -0
  37. package/dist/src/utils/ignore.js.map +1 -0
  38. package/dist/src/utils/lockfile.d.ts +9 -0
  39. package/dist/src/utils/lockfile.d.ts.map +1 -0
  40. package/dist/src/utils/lockfile.js +143 -0
  41. package/dist/src/utils/lockfile.js.map +1 -0
  42. package/dist/src/utils/popular-packages.d.ts +2 -0
  43. package/dist/src/utils/popular-packages.d.ts.map +1 -0
  44. package/dist/src/utils/popular-packages.js +22 -0
  45. package/dist/src/utils/popular-packages.js.map +1 -0
  46. package/package.json +53 -0
@@ -0,0 +1,246 @@
1
+ import { parse } from '@babel/parser';
2
+ import _traverse from '@babel/traverse';
3
+ import { isObfuscated, hasLongLines } from '../utils/entropy.js';
4
+ // @ts-ignore
5
+ const traverse = _traverse.default || _traverse;
6
+ import fs from 'fs';
7
+ import readline from 'readline';
8
+ export async function analyzeStream(filePath) {
9
+ const findings = [];
10
+ const fileStream = fs.createReadStream(filePath, { encoding: 'utf-8' });
11
+ const rl = readline.createInterface({
12
+ input: fileStream,
13
+ crlfDelay: Infinity
14
+ });
15
+ let lineIndex = 0;
16
+ let sampleContent = '';
17
+ const SAMPLE_SIZE = 5000;
18
+ for await (const line of rl) {
19
+ lineIndex++;
20
+ if (line.length > 1000) {
21
+ findings.push({
22
+ type: 'Heuristic',
23
+ name: 'Massive Line Length',
24
+ file: filePath,
25
+ line: lineIndex,
26
+ severity: 'high',
27
+ content: `Line length: ${line.length} chars`,
28
+ description: 'Extremely long line detected (Streaming Scan).'
29
+ });
30
+ rl.close();
31
+ break;
32
+ }
33
+ if (sampleContent.length < SAMPLE_SIZE) {
34
+ sampleContent += line + '\n';
35
+ }
36
+ }
37
+ if (sampleContent.length > 0 && isObfuscated(sampleContent)) {
38
+ findings.push({
39
+ type: 'Heuristic',
40
+ name: 'High Entropy',
41
+ file: filePath,
42
+ line: 0,
43
+ severity: 'medium',
44
+ content: 'File content appears random/encrypted',
45
+ description: 'Shannon entropy is abnormally high (Sampled).'
46
+ });
47
+ }
48
+ return findings;
49
+ }
50
+ export function analyzeContent(content, file) {
51
+ const findings = [];
52
+ const lines = content.split('\n');
53
+ const isJson = file.endsWith('.json');
54
+ if (isJson)
55
+ return [];
56
+ if (content.length > 1024 * 1024) {
57
+ const longLine = hasLongLines(content);
58
+ if (longLine) {
59
+ findings.push({
60
+ type: 'Heuristic',
61
+ name: 'Massive Line Length',
62
+ file,
63
+ line: longLine.lineIndex,
64
+ severity: 'high',
65
+ content: `Line length: ${longLine.length} chars`,
66
+ description: 'Extremely long line detected (File too large for AST).'
67
+ });
68
+ }
69
+ return findings;
70
+ }
71
+ // AST Analysis
72
+ try {
73
+ const ast = parse(content, {
74
+ sourceType: 'unambiguous',
75
+ plugins: ['typescript', 'jsx']
76
+ });
77
+ traverse(ast, {
78
+ CallExpression(path) {
79
+ const callee = path.node.callee;
80
+ const line = path.node.loc?.start.line || 0;
81
+ const rawLine = lines[line - 1];
82
+ const codeSnippet = rawLine ? rawLine.trim() : 'N/A';
83
+ // eval()
84
+ if (callee.type === 'Identifier' && callee.name === 'eval') {
85
+ findings.push({
86
+ type: 'AST',
87
+ name: 'Dynamic Execution',
88
+ file,
89
+ line,
90
+ severity: 'high',
91
+ content: codeSnippet,
92
+ description: 'Use of eval() detected. Vulnerable to code injection.'
93
+ });
94
+ }
95
+ // child_process, fs, net, etc.
96
+ if (callee.type === 'MemberExpression') {
97
+ const obj = callee.object;
98
+ const prop = callee.property;
99
+ if (obj.type === 'Identifier' && prop.type === 'Identifier') {
100
+ if (obj.name === 'child_process') {
101
+ findings.push({
102
+ type: 'AST',
103
+ name: 'Shell Execution',
104
+ file,
105
+ line,
106
+ severity: 'medium',
107
+ content: codeSnippet,
108
+ description: `Executes system commands: ${obj.name}.${prop.name}(...)`
109
+ });
110
+ }
111
+ if (obj.name === 'fs' || obj.name === 'fs/promises') {
112
+ findings.push({
113
+ type: 'AST',
114
+ name: 'File System Access',
115
+ file,
116
+ line,
117
+ severity: 'medium',
118
+ content: codeSnippet,
119
+ description: `Accesses file system: ${obj.name}.${prop.name}(...)`
120
+ });
121
+ }
122
+ if (['net', 'http', 'https', 'dgram', 'tls'].includes(obj.name)) {
123
+ findings.push({
124
+ type: 'AST',
125
+ name: 'Network Access',
126
+ file,
127
+ line,
128
+ severity: 'medium',
129
+ content: codeSnippet,
130
+ description: `Establishes network connection: ${obj.name}.${prop.name}(...)`
131
+ });
132
+ }
133
+ // Buffer.from(..., 'base64')
134
+ if (obj.name === 'Buffer' && prop.name === 'from') {
135
+ const args = path.node.arguments;
136
+ if (args.length > 1 && args[1].type === 'StringLiteral' && args[1].value === 'base64') {
137
+ findings.push({
138
+ type: 'AST',
139
+ name: 'Base64 Decoding',
140
+ file,
141
+ line,
142
+ severity: 'medium',
143
+ content: codeSnippet,
144
+ description: 'Decodes Base64 content. Often used to hide payloads.'
145
+ });
146
+ }
147
+ }
148
+ }
149
+ }
150
+ },
151
+ MemberExpression(path) {
152
+ // process.env
153
+ const line = path.node.loc?.start.line || 0;
154
+ const rawLine = lines[line - 1];
155
+ const codeSnippet = rawLine ? rawLine.trim() : 'N/A';
156
+ if (path.node.object.type === 'Identifier' && path.node.object.name === 'process' &&
157
+ path.node.property.type === 'Identifier' && path.node.property.name === 'env') {
158
+ findings.push({
159
+ type: 'AST',
160
+ name: 'Environment Access',
161
+ file,
162
+ line,
163
+ severity: 'low',
164
+ content: codeSnippet,
165
+ description: 'Accesses environment variables (process.env).'
166
+ });
167
+ }
168
+ },
169
+ StringLiteral(path) {
170
+ const val = path.node.value;
171
+ const line = path.node.loc?.start.line || 0;
172
+ const rawLine = lines[line - 1];
173
+ const codeSnippet = rawLine ? rawLine.trim() : val;
174
+ if (/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/.test(val)) {
175
+ if (val !== '127.0.0.1' && val !== '0.0.0.0') {
176
+ findings.push({
177
+ type: 'AST',
178
+ name: 'Suspicious IP',
179
+ file,
180
+ line,
181
+ severity: 'medium',
182
+ content: codeSnippet,
183
+ description: `Contains hardcoded IP address: ${val}`
184
+ });
185
+ }
186
+ }
187
+ if (val.startsWith('http://') || (val.startsWith('https://') && !val.includes('npmjs') && !val.includes('github'))) {
188
+ findings.push({
189
+ type: 'AST',
190
+ name: 'Suspicious URL',
191
+ file,
192
+ line,
193
+ severity: 'medium',
194
+ content: codeSnippet,
195
+ description: `Contains hardcoded URL: ${val}`
196
+ });
197
+ }
198
+ },
199
+ NewExpression(path) {
200
+ const callee = path.node.callee;
201
+ const line = path.node.loc?.start.line || 0;
202
+ const rawLine = lines[line - 1];
203
+ const codeSnippet = rawLine ? rawLine.trim() : 'new Function(...)';
204
+ if (callee.type === 'Identifier' && callee.name === 'Function') {
205
+ findings.push({
206
+ type: 'AST',
207
+ name: 'Dynamic Execution',
208
+ file,
209
+ line,
210
+ severity: 'high',
211
+ content: codeSnippet,
212
+ description: 'Creates function from string (new Function). Vulnerable to injection.'
213
+ });
214
+ }
215
+ }
216
+ });
217
+ }
218
+ catch (e) { }
219
+ // 2. Heuristics (Long Lines)
220
+ const longLine = hasLongLines(content);
221
+ if (longLine) {
222
+ findings.push({
223
+ type: 'Heuristic',
224
+ name: 'Massive Line Length',
225
+ file,
226
+ line: longLine.lineIndex,
227
+ severity: 'high',
228
+ content: `Line length: ${longLine.length} chars`,
229
+ description: 'Extremely long line detected. Often indicates minified malware or packed code.'
230
+ });
231
+ }
232
+ // 3. Entropy Check (Obfuscation)
233
+ if (!file.endsWith('.json') && isObfuscated(content)) {
234
+ findings.push({
235
+ type: 'Heuristic',
236
+ name: 'High Entropy',
237
+ file,
238
+ line: 0,
239
+ severity: 'medium',
240
+ content: 'File content appears random/encrypted',
241
+ description: 'Shannon entropy is abnormally high.'
242
+ });
243
+ }
244
+ return findings;
245
+ }
246
+ //# sourceMappingURL=static-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-analysis.js","sourceRoot":"","sources":["../../../src/analyzers/static-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function run(): Promise<void>;
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AA4HA,wBAAsB,GAAG,kBAExB"}
@@ -0,0 +1,112 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+ import inquirer from 'inquirer';
6
+ import { scanDirectory } from './scanner.js';
7
+ const program = new Command();
8
+ program
9
+ .name('tangkal')
10
+ .description('Preventive security scanner for cloned repositories')
11
+ .version('1.1.0')
12
+ .argument('[directory]', 'directory to scan', '.')
13
+ .option('--json', 'output results as JSON')
14
+ .option('--no-audit', 'skip npm audit check')
15
+ .option('--nuke', 'interactive mode to delete suspicious files')
16
+ .action(async (directory, options) => {
17
+ try {
18
+ const results = await scanDirectory(directory, options);
19
+ if (options.json) {
20
+ console.log(JSON.stringify(results, null, 2));
21
+ return;
22
+ }
23
+ if (results.length === 0) {
24
+ console.log(chalk.green.bold('\nOK: No suspicious patterns found.'));
25
+ return;
26
+ }
27
+ // Separate vulnerabilities from other results for special formatting
28
+ const vulnerabilities = results.filter(f => f.type === 'Vulnerability');
29
+ const otherResults = results.filter(f => f.type !== 'Vulnerability');
30
+ if (otherResults.length > 0) {
31
+ console.log(chalk.red.bold('\n===================================='));
32
+ console.log(chalk.red.bold('ALERT: Malicious Code Detected'));
33
+ console.log(chalk.red.bold('===================================='));
34
+ otherResults.forEach(f => {
35
+ console.log(chalk.red('--------------------------------------------------'));
36
+ console.log(`${chalk.red.bold('TYPE:')} ${chalk.white.bold(f.name || f.type)} ${chalk.gray(`(Severity: ${f.severity.toUpperCase()})`)}`);
37
+ console.log(`${chalk.cyan('FILE:')} ${chalk.white(f.file)}:${chalk.yellow(f.line || 0)}`);
38
+ console.log(`${chalk.cyan('DESC:')} ${chalk.yellow(f.description)}`);
39
+ if (f.content) {
40
+ console.log(chalk.cyan('CODE:'));
41
+ console.log(chalk.bgBlack.white(` ${f.content.trim()} `));
42
+ }
43
+ console.log('');
44
+ });
45
+ }
46
+ if (vulnerabilities.length > 0) {
47
+ console.log(chalk.red.bold('\n===================================='));
48
+ console.log(chalk.red.bold('ALERT: Vulnerable Package'));
49
+ console.log(chalk.red.bold('===================================='));
50
+ // Sort by severity (Critical first)
51
+ const severityOrder = { 'critical': 0, 'high': 1, 'moderate': 2, 'medium': 2, 'low': 3 };
52
+ vulnerabilities.sort((a, b) => (severityOrder[a.severity] ?? 99) - (severityOrder[b.severity] ?? 99));
53
+ vulnerabilities.forEach(v => {
54
+ const fixedIn = v.fixedIn || 'latest';
55
+ const severityColor = (v.severity === 'critical' || v.severity === 'high') ? chalk.red.bold : chalk.yellow;
56
+ const pkgLabel = chalk.magenta(`${v.name}@${v.version}`);
57
+ console.log(chalk.green(`[SOLUTION]: Upgrade ${v.name}@${v.version} to ${v.name}@${fixedIn} to fix.`));
58
+ let links = `[${v.url}]`;
59
+ if (v.references && v.references.length) {
60
+ const snyk = v.references.find(r => r.includes('snyk.io'));
61
+ if (snyk)
62
+ links += ` [${snyk}]`;
63
+ }
64
+ console.log(`${chalk.white('[')}${severityColor(v.severity.toUpperCase())}${chalk.white(' Severity]')} ${chalk.blue(links)}`);
65
+ console.log(`${pkgLabel} ${chalk.white(v.summary)}`);
66
+ console.log(chalk.dim(`introduced by ${v.name}@${v.version}`));
67
+ console.log('');
68
+ });
69
+ }
70
+ // Nuke Mode
71
+ if (options.nuke) {
72
+ const filesToDelete = [...new Set(results.map(r => r.file))];
73
+ const { selected } = await inquirer.prompt([
74
+ {
75
+ type: 'checkbox',
76
+ name: 'selected',
77
+ message: 'Select files to DELETE (Space to select, Enter to confirm):',
78
+ choices: filesToDelete
79
+ }
80
+ ]);
81
+ if (selected.length > 0) {
82
+ const { confirm } = await inquirer.prompt([{
83
+ type: 'confirm',
84
+ name: 'confirm',
85
+ message: `Are you sure you want to PERMANENTLY delete ${selected.length} files?`,
86
+ default: false
87
+ }]);
88
+ if (confirm) {
89
+ for (const file of selected) {
90
+ await fs.unlink(path.resolve(directory, file));
91
+ console.log(chalk.red(`Deleted: ${file}`));
92
+ }
93
+ console.log(chalk.green('Cleanup complete.'));
94
+ }
95
+ }
96
+ }
97
+ else {
98
+ console.log(chalk.red.bold('FAIL: Potential threats found.'));
99
+ console.log(chalk.yellow('Review manually or run with --nuke to delete files interactively.'));
100
+ }
101
+ }
102
+ catch (error) {
103
+ console.error(chalk.red.bold('\nFATAL ERROR:'), error.message || error);
104
+ if (error.stack)
105
+ console.error(chalk.gray(error.stack));
106
+ process.exit(1);
107
+ }
108
+ });
109
+ export async function run() {
110
+ await program.parseAsync();
111
+ }
112
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface Pattern {
2
+ name: string;
3
+ regex: RegExp;
4
+ severity: 'critical' | 'high' | 'medium' | 'low';
5
+ description: string;
6
+ }
7
+ export declare const PATTERNS: Pattern[];
8
+ export declare const POPULAR_PACKAGES: string[];
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,QAAQ,EAAE,OAAO,EA+B7B,CAAC;AAGF,eAAO,MAAM,gBAAgB,EAAE,MAAM,EAKpC,CAAC"}
@@ -0,0 +1,40 @@
1
+ export const PATTERNS = [
2
+ {
3
+ name: 'Dynamic Execution',
4
+ regex: /\b(eval|new\s+Function)\b/g,
5
+ severity: 'high',
6
+ description: 'Executes arbitrary code strings.'
7
+ },
8
+ {
9
+ name: 'Base64 Decoding',
10
+ regex: /\b(atob|Buffer\.from\(.*['"]base64['"]\))/g,
11
+ severity: 'medium',
12
+ description: 'Often used to hide payloads.'
13
+ },
14
+ {
15
+ name: 'Suspicious Network',
16
+ regex: /\b(axios|fetch|https?:\.get)\s*\(.*(atob|Buffer|token|api|model)\b/gi,
17
+ severity: 'high',
18
+ description: 'Network call with decoded/suspicious params.'
19
+ },
20
+ {
21
+ name: 'Hex Obfuscation',
22
+ regex: /\\x[0-9a-fA-F]{2}/g,
23
+ severity: 'medium',
24
+ description: 'Hex-encoded strings used for obfuscation.'
25
+ },
26
+ {
27
+ name: 'Shell Execution',
28
+ regex: /\b(child_process|exec|spawn|fork)\b/g,
29
+ severity: 'medium',
30
+ description: 'Executes system commands.'
31
+ }
32
+ ];
33
+ // A small list of very popular packages to check against for typosquatting
34
+ export const POPULAR_PACKAGES = [
35
+ 'react', 'react-dom', 'next', 'vue', 'express', 'lodash', 'commander',
36
+ 'chalk', 'axios', 'tslib', 'typescript', 'eslint', 'jest', 'moment',
37
+ 'date-fns', 'uuid', 'classnames', 'prop-types', 'webpack', 'babel-core',
38
+ 'body-parser', 'cookie-parser', 'dotenv', 'mongoose', 'nodemon'
39
+ ];
40
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,QAAQ,GAAc;IACjC;QACE,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,4BAA4B;QACnC,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,kCAAkC;KAChD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,4CAA4C;QACnD,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,KAAK,EAAE,uEAAuE;QAC9E,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,8CAA8C;KAC5D;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,oBAAoB;QAC3B,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,2CAA2C;KACzD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,sCAAsC;QAC7C,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,2BAA2B;KACzC;CACF,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW;IACrE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ;IACnE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY;IACvE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS;CAChE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type Finding } from './analyzers/static-analysis.js';
2
+ interface ScanOptions {
3
+ json?: boolean;
4
+ skipAudit?: boolean;
5
+ }
6
+ export declare function scanDirectory(directory: string, options?: ScanOptions): Promise<Finding[]>;
7
+ export {};
8
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/scanner.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAK7F,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAmHpG"}
@@ -0,0 +1,115 @@
1
+ import fg from 'fast-glob';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
6
+ import { loadIgnore } from './utils/ignore.js';
7
+ import { analyzeContent, analyzeStream } from './analyzers/static-analysis.js';
8
+ import { checkTyposquatting } from './analyzers/dependencies.js';
9
+ import { auditDependencies } from './analyzers/network.js';
10
+ import { parsePackageLock } from './utils/lockfile.js';
11
+ export async function scanDirectory(directory, options = {}) {
12
+ const targetDir = path.resolve(directory);
13
+ const ig = await loadIgnore(targetDir);
14
+ const allFindings = [];
15
+ // 1. Find Files (Streaming)
16
+ const stream = fg.stream(['**/*.{js,ts,jsx,tsx,json}'], {
17
+ cwd: targetDir,
18
+ dot: true,
19
+ ignore: ['**/node_modules/**', '**/.git/**']
20
+ });
21
+ if (!options.json) {
22
+ console.log(chalk.gray(`Scanning files from ${targetDir} (Streaming)...`));
23
+ }
24
+ let packageJsonFound = false;
25
+ // 2. Scan Content
26
+ for await (const entry of stream) {
27
+ const file = entry;
28
+ if (ig.ignores(file))
29
+ continue;
30
+ const filePath = path.join(targetDir, file);
31
+ try {
32
+ const stat = await fs.stat(filePath);
33
+ // Optimize: Stream large files (>1MB)
34
+ if (stat.size > 1024 * 1024) {
35
+ const streamFindings = await analyzeStream(filePath);
36
+ streamFindings.forEach(f => { f.file = file; allFindings.push(f); });
37
+ continue;
38
+ }
39
+ // Standard Read for small files
40
+ let content = await fs.readFile(filePath, 'utf-8');
41
+ content = content.replace(/^\uFEFF/, '');
42
+ // Check package.json specifically
43
+ if (file === 'package.json') {
44
+ packageJsonFound = true;
45
+ try {
46
+ const pkg = JSON.parse(content);
47
+ // A. Lifecycle Scripts
48
+ const scripts = pkg.scripts || {};
49
+ const dangerousScripts = ['preinstall', 'postinstall', 'install'];
50
+ for (const name of dangerousScripts) {
51
+ if (scripts[name]) {
52
+ allFindings.push({
53
+ type: 'Lifecycle Script',
54
+ name: name,
55
+ file,
56
+ line: 0,
57
+ severity: 'critical',
58
+ content: scripts[name],
59
+ description: 'Dangerous lifecycle script that runs automatically on install.'
60
+ });
61
+ }
62
+ }
63
+ // B. Typosquatting (Async & Network-aware)
64
+ const typoFindings = await checkTyposquatting(pkg);
65
+ typoFindings.forEach(f => {
66
+ allFindings.push({ ...f, file });
67
+ });
68
+ }
69
+ catch (e) {
70
+ // Error parsing or checking typosquat
71
+ }
72
+ }
73
+ // Static Code Analysis (AST)
74
+ const contentFindings = analyzeContent(content, file);
75
+ allFindings.push(...contentFindings);
76
+ }
77
+ catch (e) {
78
+ // failed to read file
79
+ }
80
+ }
81
+ // 3. Network Audit (Reputation & Vulnerability)
82
+ if (!options.skipAudit) {
83
+ const lockDeps = await parsePackageLock(targetDir);
84
+ if (lockDeps && lockDeps.length > 0) {
85
+ if (!options.json)
86
+ console.log(chalk.gray('Running deep dependency audit...'));
87
+ const spinner = !options.json ? ora(`Auditing ${lockDeps.length} dependencies...`).start() : null;
88
+ const netFindings = await auditDependencies(lockDeps);
89
+ allFindings.push(...netFindings);
90
+ if (spinner)
91
+ spinner.succeed(`Audit complete: scanned ${lockDeps.length} packages.`);
92
+ }
93
+ else if (packageJsonFound) {
94
+ try {
95
+ const pkgPath = path.join(targetDir, 'package.json');
96
+ const pkgContent = await fs.readFile(pkgPath, 'utf-8');
97
+ const pkg = JSON.parse(pkgContent);
98
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
99
+ const directDeps = Object.keys(deps).map(k => ({ name: k, version: deps[k].replace(/[\^~]/g, '') }));
100
+ if (directDeps.length > 0) {
101
+ if (!options.json)
102
+ console.log(chalk.gray('No lockfile found. Auditing direct dependencies...'));
103
+ const spinner = !options.json ? ora(`Auditing ${directDeps.length} direct dependencies...`).start() : null;
104
+ const netFindings = await auditDependencies(directDeps);
105
+ allFindings.push(...netFindings);
106
+ if (spinner)
107
+ spinner.succeed(`Audit complete: scanned ${directDeps.length} packages.`);
108
+ }
109
+ }
110
+ catch (e) { }
111
+ }
112
+ }
113
+ return allFindings;
114
+ }
115
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function calculateEntropy(text: string): number;
2
+ export declare function isObfuscated(text: string, threshold?: number): boolean;
3
+ export declare function hasLongLines(text: string, threshold?: number): {
4
+ lineIndex: number;
5
+ length: number;
6
+ } | null;
7
+ //# sourceMappingURL=entropy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entropy.d.ts","sourceRoot":"","sources":["../../../src/utils/entropy.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,OAAO,CAInE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASzG"}
@@ -0,0 +1,25 @@
1
+ // @ts-ignore
2
+ import _entropy from 'shannon-entropy';
3
+ // @ts-ignore
4
+ const entropy = _entropy.default || _entropy;
5
+ export function calculateEntropy(text) {
6
+ if (typeof entropy !== 'function')
7
+ return 0;
8
+ return entropy(text);
9
+ }
10
+ export function isObfuscated(text, threshold = 4.5) {
11
+ // Common english text is around 3.5 - 4.5
12
+ // Packed/encrypted code often exceeds 5.0
13
+ return calculateEntropy(text) > threshold;
14
+ }
15
+ export function hasLongLines(text, threshold = 1000) {
16
+ const lines = text.split('\n');
17
+ for (let i = 0; i < lines.length; i++) {
18
+ const line = lines[i];
19
+ if (line && line.length > threshold) {
20
+ return { lineIndex: i + 1, length: line.length };
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ //# sourceMappingURL=entropy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entropy.js","sourceRoot":"","sources":["../../../src/utils/entropy.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,aAAa;AACb,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC;AAE7C,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,OAAO,OAAO,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,SAAS,GAAG,GAAG;IACxD,0CAA0C;IAC1C,0CAA0C;IAC1C,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,SAAS,GAAG,IAAI;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACpC,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Ignore } from 'ignore';
2
+ export declare function loadIgnore(dir: string): Promise<Ignore>;
3
+ //# sourceMappingURL=ignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../../src/utils/ignore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe7D"}