scriptguard 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.
- package/README.md +430 -0
- package/dist/ai/analyzers/false-positive-filter.d.ts +15 -0
- package/dist/ai/analyzers/false-positive-filter.d.ts.map +1 -0
- package/dist/ai/analyzers/false-positive-filter.js +162 -0
- package/dist/ai/analyzers/false-positive-filter.js.map +1 -0
- package/dist/ai/analyzers/insight-generator.d.ts +7 -0
- package/dist/ai/analyzers/insight-generator.d.ts.map +1 -0
- package/dist/ai/analyzers/insight-generator.js +384 -0
- package/dist/ai/analyzers/insight-generator.js.map +1 -0
- package/dist/ai/analyzers/threat-detector.d.ts +7 -0
- package/dist/ai/analyzers/threat-detector.d.ts.map +1 -0
- package/dist/ai/analyzers/threat-detector.js +249 -0
- package/dist/ai/analyzers/threat-detector.js.map +1 -0
- package/dist/ai/gemini-client.d.ts +47 -0
- package/dist/ai/gemini-client.d.ts.map +1 -0
- package/dist/ai/gemini-client.js +222 -0
- package/dist/ai/gemini-client.js.map +1 -0
- package/dist/ai/index.d.ts +8 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts.d.ts +11 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +212 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +283 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/scanners/index.d.ts +10 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +202 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/lifecycle.d.ts +10 -0
- package/dist/scanners/lifecycle.d.ts.map +1 -0
- package/dist/scanners/lifecycle.js +202 -0
- package/dist/scanners/lifecycle.js.map +1 -0
- package/dist/scanners/patterns.d.ts +4 -0
- package/dist/scanners/patterns.d.ts.map +1 -0
- package/dist/scanners/patterns.js +188 -0
- package/dist/scanners/patterns.js.map +1 -0
- package/dist/types/index.d.ts +123 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** ScriptGuard — Lifecycle script parser — reads package.json files from node_modules */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.analyzePackage = analyzePackage;
|
|
38
|
+
exports.scanInstalledPackages = scanInstalledPackages;
|
|
39
|
+
exports.scanSinglePackage = scanSinglePackage;
|
|
40
|
+
exports.extractLifecycleScripts = extractLifecycleScripts;
|
|
41
|
+
exports.calculateRiskScore = calculateRiskScore;
|
|
42
|
+
exports.riskLevelFromScore = riskLevelFromScore;
|
|
43
|
+
const fs = __importStar(require("node:fs"));
|
|
44
|
+
const path = __importStar(require("node:path"));
|
|
45
|
+
const patterns_js_1 = require("./patterns.js");
|
|
46
|
+
const LIFECYCLE_SCRIPTS = [
|
|
47
|
+
'preinstall',
|
|
48
|
+
'install',
|
|
49
|
+
'postinstall',
|
|
50
|
+
'preprepare',
|
|
51
|
+
'prepare',
|
|
52
|
+
'postprepare',
|
|
53
|
+
'prepack',
|
|
54
|
+
'postpack',
|
|
55
|
+
'preuninstall',
|
|
56
|
+
'uninstall',
|
|
57
|
+
'postuninstall',
|
|
58
|
+
'prerestart',
|
|
59
|
+
'restart',
|
|
60
|
+
'postrestart',
|
|
61
|
+
'preversion',
|
|
62
|
+
'version',
|
|
63
|
+
'postversion',
|
|
64
|
+
'prebuild',
|
|
65
|
+
'postbuild',
|
|
66
|
+
'prestart',
|
|
67
|
+
'poststart',
|
|
68
|
+
'pretest',
|
|
69
|
+
'posttest',
|
|
70
|
+
];
|
|
71
|
+
const RISK_WEIGHTS = {
|
|
72
|
+
low: 5,
|
|
73
|
+
medium: 25,
|
|
74
|
+
high: 60,
|
|
75
|
+
critical: 100,
|
|
76
|
+
};
|
|
77
|
+
function extractLifecycleScripts(scripts) {
|
|
78
|
+
const result = {};
|
|
79
|
+
for (const name of LIFECYCLE_SCRIPTS) {
|
|
80
|
+
if (scripts[name]) {
|
|
81
|
+
result[name] = scripts[name];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
function analyzeScriptContent(packageName, version, scriptName, scriptContent) {
|
|
87
|
+
const findings = [];
|
|
88
|
+
for (const rule of patterns_js_1.PATTERN_RULES) {
|
|
89
|
+
const match = rule.pattern.exec(scriptContent);
|
|
90
|
+
if (match) {
|
|
91
|
+
findings.push({
|
|
92
|
+
package: packageName,
|
|
93
|
+
scriptName,
|
|
94
|
+
scriptContent,
|
|
95
|
+
pattern: rule.name,
|
|
96
|
+
description: rule.description,
|
|
97
|
+
riskLevel: rule.riskLevel,
|
|
98
|
+
match: match[0],
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return findings;
|
|
103
|
+
}
|
|
104
|
+
function calculateRiskScore(findings) {
|
|
105
|
+
if (findings.length === 0)
|
|
106
|
+
return 0;
|
|
107
|
+
const maxScore = Math.max(...findings.map((f) => RISK_WEIGHTS[f.riskLevel]));
|
|
108
|
+
const avgScore = findings.reduce((sum, f) => sum + RISK_WEIGHTS[f.riskLevel], 0) / findings.length;
|
|
109
|
+
return Math.min(100, Math.round((maxScore * 0.6 + avgScore * 0.4)));
|
|
110
|
+
}
|
|
111
|
+
function riskLevelFromScore(score) {
|
|
112
|
+
if (score >= 75)
|
|
113
|
+
return 'critical';
|
|
114
|
+
if (score >= 50)
|
|
115
|
+
return 'high';
|
|
116
|
+
if (score >= 25)
|
|
117
|
+
return 'medium';
|
|
118
|
+
return 'low';
|
|
119
|
+
}
|
|
120
|
+
function analyzePackage(name, version, scripts) {
|
|
121
|
+
const lifecycleScripts = extractLifecycleScripts(scripts);
|
|
122
|
+
const allFindings = [];
|
|
123
|
+
for (const [scriptName, scriptContent] of Object.entries(lifecycleScripts)) {
|
|
124
|
+
const scriptFindings = analyzeScriptContent(name, version, scriptName, scriptContent);
|
|
125
|
+
allFindings.push(...scriptFindings);
|
|
126
|
+
// Flag any lifecycle script that exists without findings as "low" info
|
|
127
|
+
if (scriptFindings.length === 0 && ['postinstall', 'preinstall', 'install'].includes(scriptName)) {
|
|
128
|
+
allFindings.push({
|
|
129
|
+
package: name,
|
|
130
|
+
scriptName,
|
|
131
|
+
scriptContent,
|
|
132
|
+
pattern: 'lifecycle-script-present',
|
|
133
|
+
description: `Package runs code during ${scriptName} — review recommended`,
|
|
134
|
+
riskLevel: 'low',
|
|
135
|
+
match: scriptContent.substring(0, 60),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const riskScore = calculateRiskScore(allFindings);
|
|
140
|
+
return {
|
|
141
|
+
name,
|
|
142
|
+
version,
|
|
143
|
+
scripts: lifecycleScripts,
|
|
144
|
+
findings: allFindings,
|
|
145
|
+
riskScore,
|
|
146
|
+
riskLevel: riskLevelFromScore(riskScore),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function scanInstalledPackages(projectPath, includeDev = false) {
|
|
150
|
+
const nodeModulesPath = path.join(projectPath, 'node_modules');
|
|
151
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
152
|
+
throw new Error(`No node_modules found at ${nodeModulesPath}`);
|
|
153
|
+
}
|
|
154
|
+
const analyses = [];
|
|
155
|
+
const visited = new Set();
|
|
156
|
+
function scanDir(dir) {
|
|
157
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
158
|
+
for (const entry of entries) {
|
|
159
|
+
if (entry.name.startsWith('.'))
|
|
160
|
+
continue;
|
|
161
|
+
const fullPath = path.join(dir, entry.name);
|
|
162
|
+
if (entry.isDirectory()) {
|
|
163
|
+
// Handle scoped packages (@scope/pkg)
|
|
164
|
+
if (entry.name.startsWith('@')) {
|
|
165
|
+
scanDir(fullPath);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const pkgJsonPath = path.join(fullPath, 'package.json');
|
|
169
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
170
|
+
try {
|
|
171
|
+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
172
|
+
const pkgKey = `${pkgJson.name}@${pkgJson.version}`;
|
|
173
|
+
if (visited.has(pkgKey))
|
|
174
|
+
continue;
|
|
175
|
+
visited.add(pkgKey);
|
|
176
|
+
if (pkgJson.scripts && Object.keys(pkgJson.scripts).length > 0) {
|
|
177
|
+
analyses.push(analyzePackage(pkgJson.name || entry.name, pkgJson.version || 'unknown', pkgJson.scripts));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Skip malformed package.json
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Don't recurse into nested node_modules
|
|
185
|
+
if (!fullPath.includes('node_modules' + path.sep + entry.name + path.sep + 'node_modules')) {
|
|
186
|
+
// Check for nested packages
|
|
187
|
+
const nested = path.join(fullPath, 'node_modules');
|
|
188
|
+
if (!fs.existsSync(nested)) {
|
|
189
|
+
// Some packages have sub-packages in subdirectories
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
scanDir(nodeModulesPath);
|
|
196
|
+
return analyses.sort((a, b) => b.riskScore - a.riskScore);
|
|
197
|
+
}
|
|
198
|
+
function scanSinglePackage(pkgJsonContent) {
|
|
199
|
+
const pkgJson = JSON.parse(pkgJsonContent);
|
|
200
|
+
return analyzePackage(pkgJson.name || 'unknown', pkgJson.version || 'unknown', pkgJson.scripts || {});
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/scanners/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/scanners/patterns.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,aAAa,EAAE,WAAW,EA2LtC,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** ScriptGuard — Pattern rules for detecting malicious lifecycle scripts */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.PATTERN_RULES = void 0;
|
|
5
|
+
exports.PATTERN_RULES = [
|
|
6
|
+
// === NETWORK — data exfiltration vectors ===
|
|
7
|
+
{
|
|
8
|
+
name: 'curl-pipe',
|
|
9
|
+
pattern: /curl\s+[^|]*\|\s*(?:sh|bash|sudo|zsh)/,
|
|
10
|
+
riskLevel: 'critical',
|
|
11
|
+
description: 'Downloads and executes remote code via curl pipe',
|
|
12
|
+
category: 'network',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'wget-pipe',
|
|
16
|
+
pattern: /wget\s+.*\|\s*(?:sh|bash|sudo|zsh)/,
|
|
17
|
+
riskLevel: 'critical',
|
|
18
|
+
description: 'Downloads and executes remote code via wget pipe',
|
|
19
|
+
category: 'network',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'curl-silent',
|
|
23
|
+
pattern: /curl\s+.*-[sS]\b/,
|
|
24
|
+
riskLevel: 'high',
|
|
25
|
+
description: 'Silent HTTP request — common in data exfiltration',
|
|
26
|
+
category: 'network',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'curl-post',
|
|
30
|
+
pattern: /curl\s+.*-[dX]\s+(?:POST|PUT|PATCH)/,
|
|
31
|
+
riskLevel: 'high',
|
|
32
|
+
description: 'HTTP POST/PUT request — may send data externally',
|
|
33
|
+
category: 'network',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'http-request',
|
|
37
|
+
pattern: /(?:https?:\/\/[^\s'"]+|fetch\s*\(|request\s*\(|http\.request|http\.get|axios|got\()/,
|
|
38
|
+
riskLevel: 'medium',
|
|
39
|
+
description: 'Outbound HTTP request detected',
|
|
40
|
+
category: 'network',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'dns-lookup',
|
|
44
|
+
pattern: /(?:nslookup|dig|host\s+\S+\.\S+|dns\.resolve)/,
|
|
45
|
+
riskLevel: 'medium',
|
|
46
|
+
description: 'DNS lookup — can be used for DNS-based data exfiltration',
|
|
47
|
+
category: 'network',
|
|
48
|
+
},
|
|
49
|
+
// === EXECUTION — arbitrary code execution ===
|
|
50
|
+
{
|
|
51
|
+
name: 'eval-usage',
|
|
52
|
+
pattern: /(?:^|\s|;|&&|\|\|)(?:eval|Function)\s*[\($]/,
|
|
53
|
+
riskLevel: 'high',
|
|
54
|
+
description: 'eval() or Function() constructor — arbitrary code execution',
|
|
55
|
+
category: 'execution',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'child-process',
|
|
59
|
+
pattern: /(?:exec|execSync|spawn|spawnSync|execFile|fork)\s*\(/,
|
|
60
|
+
riskLevel: 'medium',
|
|
61
|
+
description: 'Spawns child process — can execute arbitrary commands',
|
|
62
|
+
category: 'execution',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'shell-exec',
|
|
66
|
+
pattern: /(?:sh\s+-c|bash\s+-c|zsh\s+-c|\/bin\/sh|\/bin\/bash|\/bin\/zsh)/,
|
|
67
|
+
riskLevel: 'high',
|
|
68
|
+
description: 'Direct shell execution',
|
|
69
|
+
category: 'execution',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'node-eval',
|
|
73
|
+
pattern: /node\s+-e\s+/,
|
|
74
|
+
riskLevel: 'high',
|
|
75
|
+
description: 'Evaluates Node.js code from command line',
|
|
76
|
+
category: 'execution',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'require-resolve',
|
|
80
|
+
pattern: /require\s*\(\s*[^'"]*\+/,
|
|
81
|
+
riskLevel: 'medium',
|
|
82
|
+
description: 'Dynamic require with string concatenation',
|
|
83
|
+
category: 'execution',
|
|
84
|
+
},
|
|
85
|
+
// === FILESYSTEM — sensitive file access ===
|
|
86
|
+
{
|
|
87
|
+
name: 'ssh-access',
|
|
88
|
+
pattern: /(?:~\/\.ssh|\/\.ssh|id_rsa|id_ed25519|id_ecdsa)/,
|
|
89
|
+
riskLevel: 'critical',
|
|
90
|
+
description: 'Accesses SSH keys — credential theft risk',
|
|
91
|
+
category: 'filesystem',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'aws-creds',
|
|
95
|
+
pattern: /(?:~\/\.aws|\/\.aws|AWS_|aws_access_key|aws_secret_key)/,
|
|
96
|
+
riskLevel: 'critical',
|
|
97
|
+
description: 'Accesses AWS credentials — cloud account takeover risk',
|
|
98
|
+
category: 'filesystem',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'env-file',
|
|
102
|
+
pattern: /\.env(?:\.local|\.production|\.staging)?/,
|
|
103
|
+
riskLevel: 'high',
|
|
104
|
+
description: 'Reads .env files — may expose secrets',
|
|
105
|
+
category: 'filesystem',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'passwd-shadow',
|
|
109
|
+
pattern: /\/etc\/(?:passwd|shadow|sudoers|hosts)/,
|
|
110
|
+
riskLevel: 'critical',
|
|
111
|
+
description: 'Reads system credential files',
|
|
112
|
+
category: 'filesystem',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'tmp-write',
|
|
116
|
+
pattern: /(?:\/tmp\/|os\.tmpdir|tempdir|writeFileSync|writeFile).*\.sh/,
|
|
117
|
+
riskLevel: 'medium',
|
|
118
|
+
description: 'Writes executable to temp directory',
|
|
119
|
+
category: 'filesystem',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'chmod-exec',
|
|
123
|
+
pattern: /chmod\s+\+x/,
|
|
124
|
+
riskLevel: 'medium',
|
|
125
|
+
description: 'Makes a file executable',
|
|
126
|
+
category: 'filesystem',
|
|
127
|
+
},
|
|
128
|
+
// === EXFILTRATION — stealing data ===
|
|
129
|
+
{
|
|
130
|
+
name: 'env-exfil',
|
|
131
|
+
pattern: /(?:process\.env|export|printenv|env\s)/,
|
|
132
|
+
riskLevel: 'high',
|
|
133
|
+
description: 'Reads environment variables — may contain secrets',
|
|
134
|
+
category: 'exfiltration',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'clipboard-access',
|
|
138
|
+
pattern: /(?:pbcopy|xclip|xsel|clipboard)/,
|
|
139
|
+
riskLevel: 'high',
|
|
140
|
+
description: 'Accesses system clipboard — can steal copied data',
|
|
141
|
+
category: 'exfiltration',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'keychain-access',
|
|
145
|
+
pattern: /(?:security\s+find|keychain|osascript.*keychain)/,
|
|
146
|
+
riskLevel: 'critical',
|
|
147
|
+
description: 'Accesses macOS Keychain or credential store',
|
|
148
|
+
category: 'exfiltration',
|
|
149
|
+
},
|
|
150
|
+
// === OBFUSCATION — hiding malicious intent ===
|
|
151
|
+
{
|
|
152
|
+
name: 'base64-exec',
|
|
153
|
+
pattern: /(?:base64\s+-d|atob|Buffer\.from\s*\([^)]*,\s*['"]base64['"]\))\s*[;|&&\n].*(?:eval|exec|sh|bash)/,
|
|
154
|
+
riskLevel: 'critical',
|
|
155
|
+
description: 'Base64 decode + execute — classic obfuscation technique',
|
|
156
|
+
category: 'obfuscation',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'hex-encode',
|
|
160
|
+
pattern: /\\x[0-9a-fA-F]{2}.*\\x[0-9a-fA-F]{2}.*\\x[0-9a-fA-F]{2}/,
|
|
161
|
+
riskLevel: 'high',
|
|
162
|
+
description: 'Hex-encoded strings — likely hiding payload',
|
|
163
|
+
category: 'obfuscation',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'unicode-escape',
|
|
167
|
+
pattern: /\\u[0-9a-fA-F]{4}.*\\u[0-9a-fA-F]{4}.*\\u[0-9a-fA-F]{4}/,
|
|
168
|
+
riskLevel: 'medium',
|
|
169
|
+
description: 'Unicode-escaped strings — potential obfuscation',
|
|
170
|
+
category: 'obfuscation',
|
|
171
|
+
},
|
|
172
|
+
// === CRYPTO — mining or ransomware ===
|
|
173
|
+
{
|
|
174
|
+
name: 'crypto-miner',
|
|
175
|
+
pattern: /(?:xmrig|minerd|cpuminer|cryptonight|stratum\+tcp)/,
|
|
176
|
+
riskLevel: 'critical',
|
|
177
|
+
description: 'Cryptocurrency mining detected',
|
|
178
|
+
category: 'crypto',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'reverse-shell',
|
|
182
|
+
pattern: /(?:nc\s+-|ncat|socat|\/dev\/tcp|bash\s+-i\s+>&)/,
|
|
183
|
+
riskLevel: 'critical',
|
|
184
|
+
description: 'Reverse shell pattern — full system takeover',
|
|
185
|
+
category: 'execution',
|
|
186
|
+
},
|
|
187
|
+
];
|
|
188
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/scanners/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** ScriptGuard — Type definitions */
|
|
2
|
+
export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
|
3
|
+
export type AIMode = 'basic' | 'standard' | 'thorough';
|
|
4
|
+
export interface AIOptions {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
mode: AIMode;
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
maxTokens?: number;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
mitigation?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface AIInsight {
|
|
13
|
+
type: 'false-positive' | 'threat' | 'mitigation';
|
|
14
|
+
severity: RiskLevel;
|
|
15
|
+
description: string;
|
|
16
|
+
attackTechnique?: string;
|
|
17
|
+
remediation?: string;
|
|
18
|
+
confidence: number;
|
|
19
|
+
}
|
|
20
|
+
export interface AIAnalysis {
|
|
21
|
+
package: string;
|
|
22
|
+
version: string;
|
|
23
|
+
falsePositivesFiltered: number;
|
|
24
|
+
newThreatsDetected: number;
|
|
25
|
+
insights: AIInsight[];
|
|
26
|
+
confidence: number;
|
|
27
|
+
tokensUsed: number;
|
|
28
|
+
}
|
|
29
|
+
export interface AIBatchRequest {
|
|
30
|
+
packages: Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
version: string;
|
|
33
|
+
scripts: Record<string, string>;
|
|
34
|
+
findings: Finding[];
|
|
35
|
+
}>;
|
|
36
|
+
mode: AIMode;
|
|
37
|
+
}
|
|
38
|
+
export interface AIBatchResponse {
|
|
39
|
+
analyses: AIAnalysis[];
|
|
40
|
+
totalTokensUsed: number;
|
|
41
|
+
}
|
|
42
|
+
export interface Finding {
|
|
43
|
+
/** The package that triggered this finding */
|
|
44
|
+
package: string;
|
|
45
|
+
/** Which lifecycle script (e.g., "postinstall", "preinstall") */
|
|
46
|
+
scriptName: string;
|
|
47
|
+
/** The full script content */
|
|
48
|
+
scriptContent: string;
|
|
49
|
+
/** What was detected */
|
|
50
|
+
pattern: string;
|
|
51
|
+
/** Human-readable description of the risk */
|
|
52
|
+
description: string;
|
|
53
|
+
/** How severe */
|
|
54
|
+
riskLevel: RiskLevel;
|
|
55
|
+
/** Line/position where found (if applicable) */
|
|
56
|
+
match: string;
|
|
57
|
+
/** AI analysis if available */
|
|
58
|
+
aiAnalysis?: AIAnalysis;
|
|
59
|
+
}
|
|
60
|
+
export interface PackageAnalysis {
|
|
61
|
+
/** Package name */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Package version */
|
|
64
|
+
version: string;
|
|
65
|
+
/** All lifecycle scripts found */
|
|
66
|
+
scripts: Record<string, string>;
|
|
67
|
+
/** Findings for this package */
|
|
68
|
+
findings: Finding[];
|
|
69
|
+
/** Overall risk score 0-100 */
|
|
70
|
+
riskScore: number;
|
|
71
|
+
/** Overall risk level */
|
|
72
|
+
riskLevel: RiskLevel;
|
|
73
|
+
}
|
|
74
|
+
export interface ScanResult {
|
|
75
|
+
/** Total packages scanned */
|
|
76
|
+
totalPackages: number;
|
|
77
|
+
/** Packages with lifecycle scripts */
|
|
78
|
+
packagesWithScripts: number;
|
|
79
|
+
/** Individual package analyses */
|
|
80
|
+
analyses: PackageAnalysis[];
|
|
81
|
+
/** Total findings */
|
|
82
|
+
totalFindings: number;
|
|
83
|
+
/** Findings by risk level */
|
|
84
|
+
findingsByLevel: Record<RiskLevel, number>;
|
|
85
|
+
/** Overall risk score (average weighted) */
|
|
86
|
+
overallRiskScore: number;
|
|
87
|
+
/** Overall risk level */
|
|
88
|
+
overallRiskLevel: RiskLevel;
|
|
89
|
+
/** Duration of scan in ms */
|
|
90
|
+
scanDurationMs: number;
|
|
91
|
+
/** AI analysis if enabled */
|
|
92
|
+
aiAnalysis?: {
|
|
93
|
+
totalTokensUsed: number;
|
|
94
|
+
totalFalsePositivesFiltered: number;
|
|
95
|
+
totalNewThreatsDetected: number;
|
|
96
|
+
durationMs: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export interface PatternRule {
|
|
100
|
+
/** Unique name for this rule */
|
|
101
|
+
name: string;
|
|
102
|
+
/** Regex pattern to match */
|
|
103
|
+
pattern: RegExp;
|
|
104
|
+
/** Risk level if matched */
|
|
105
|
+
riskLevel: RiskLevel;
|
|
106
|
+
/** Human description */
|
|
107
|
+
description: string;
|
|
108
|
+
/** What this pattern indicates */
|
|
109
|
+
category: 'network' | 'execution' | 'filesystem' | 'exfiltration' | 'obfuscation' | 'crypto';
|
|
110
|
+
}
|
|
111
|
+
export interface ScanOptions {
|
|
112
|
+
/** Path to scan (defaults to cwd) */
|
|
113
|
+
path: string;
|
|
114
|
+
/** Include dev dependencies */
|
|
115
|
+
includeDev: boolean;
|
|
116
|
+
/** Minimum risk level to report */
|
|
117
|
+
minRiskLevel: RiskLevel;
|
|
118
|
+
/** Output format */
|
|
119
|
+
format: 'table' | 'json' | 'sarif';
|
|
120
|
+
/** Fail on findings at or above this level (for CI) */
|
|
121
|
+
failLevel?: RiskLevel;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA,qCAAqC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "scriptguard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Security scanner for npm package lifecycle scripts — detect malicious postinstall, preinstall, and prepare scripts before they run",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"scriptguard": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"test:watch": "vitest",
|
|
13
|
+
"lint": "tsc --noEmit",
|
|
14
|
+
"start": "node dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"npm",
|
|
18
|
+
"security",
|
|
19
|
+
"lifecycle",
|
|
20
|
+
"scripts",
|
|
21
|
+
"postinstall",
|
|
22
|
+
"preinstall",
|
|
23
|
+
"supply-chain",
|
|
24
|
+
"audit",
|
|
25
|
+
"scanner",
|
|
26
|
+
"malware"
|
|
27
|
+
],
|
|
28
|
+
"author": "Peter Ferriere",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@google/generative-ai": "^0.21.0",
|
|
32
|
+
"chalk": "^5.3.0",
|
|
33
|
+
"commander": "^12.0.0",
|
|
34
|
+
"ora": "^8.0.0",
|
|
35
|
+
"p-throttle": "^6.0.0",
|
|
36
|
+
"zod": "^3.22.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^20.11.0",
|
|
40
|
+
"typescript": "^5.4.0",
|
|
41
|
+
"vitest": "^1.3.0"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|