pkgxray 0.4.0 → 0.5.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/package.json +1 -1
- package/src/auditor.js +39 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pkgxray",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Zero-dep local CLI and MCP server that scans npm packages and AI-agent extensions for supply-chain risk. OSV vuln pre-check, sandboxed quarantine, tarball-integrity verification, calibrated static heuristics.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jack Adams-Lovell",
|
package/src/auditor.js
CHANGED
|
@@ -57,19 +57,54 @@ const PERSISTENCE_REGEXES = [
|
|
|
57
57
|
const EXEC_REGEX = /\b(?:child_process\.(?:exec|execSync|spawn|spawnSync|fork)|require\(['"]child_process['"]\)|os\.system\(|subprocess\.(?:Popen|run|call|check_output)|Runtime\.getRuntime\(\)\.exec)/;
|
|
58
58
|
const DYNAMIC_EVAL_REGEX = /\b(?:eval\s*\(|new\s+Function\s*\(|vm\.runIn[A-Za-z]+Context\b)/;
|
|
59
59
|
|
|
60
|
-
const NETWORK_REGEX = /\b(?:fetch\s*\(|axios\.[a-z]+\s*\(|got\s*\(|node-fetch|undici|https?\.request\s*\(|XMLHttpRequest|new\s+WebSocket|requests\.[a-z]+\s*\(|urllib(?:\.request)?|net\/http)/i;
|
|
60
|
+
const NETWORK_REGEX = /\b(?:fetch\s*\(|axios\.[a-z]+\s*\(|got\s*\(|node-fetch|undici|https?\.(?:request|get|post|put|delete)\s*\(|XMLHttpRequest|new\s+WebSocket|requests\.[a-z]+\s*\(|urllib(?:\.request)?|net\/http|httpx\.[a-z]+\s*\()/i;
|
|
61
61
|
const SHELL_NETWORK_REGEX = /(?:^|[\s;&|`$(])(?:curl|wget|Invoke-WebRequest)\s/m;
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
// Domains that are almost never legitimate destinations from production code.
|
|
64
|
+
// Three buckets: URL shorteners (data hiding), paste/webhook services
|
|
65
|
+
// (drop sites), and OAST/tunneling services (Burp Collaborator-style
|
|
66
|
+
// out-of-band callbacks used in dependency-confusion PoCs and credential
|
|
67
|
+
// staging). A real library would not call any of these.
|
|
68
|
+
const EXFIL_AND_CALLBACK_DOMAINS = [
|
|
69
|
+
// URL shorteners
|
|
64
70
|
"bit.ly",
|
|
65
71
|
"tinyurl.com",
|
|
66
72
|
"t.co/",
|
|
67
73
|
"goo.gl",
|
|
74
|
+
"is.gd",
|
|
75
|
+
"ow.ly",
|
|
76
|
+
// Paste / drop sites
|
|
68
77
|
"pastebin.com",
|
|
69
78
|
"hastebin",
|
|
79
|
+
"transfer.sh",
|
|
80
|
+
// Webhooks
|
|
70
81
|
"webhook.site",
|
|
71
82
|
"discord.com/api/webhooks",
|
|
72
|
-
"hooks.slack.com"
|
|
83
|
+
"hooks.slack.com",
|
|
84
|
+
"discordapp.com/api/webhooks",
|
|
85
|
+
// OAST / collaborator services (Burp, Caido, ProjectDiscovery)
|
|
86
|
+
"oast.live",
|
|
87
|
+
"oast.fun",
|
|
88
|
+
"oast.online",
|
|
89
|
+
"oast.pro",
|
|
90
|
+
"oast.me",
|
|
91
|
+
"oast.site",
|
|
92
|
+
"oastify.com",
|
|
93
|
+
"interact.sh",
|
|
94
|
+
"burpcollaborator.net",
|
|
95
|
+
// Pipe / request inspector services
|
|
96
|
+
"requestbin.com",
|
|
97
|
+
"requestbin.net",
|
|
98
|
+
"pipedream.net",
|
|
99
|
+
"pipedream.com",
|
|
100
|
+
"rce.ee",
|
|
101
|
+
// Tunneling / reverse proxies
|
|
102
|
+
"ngrok-free.app",
|
|
103
|
+
"ngrok.io",
|
|
104
|
+
"serveo.net",
|
|
105
|
+
"lhr.life",
|
|
106
|
+
"loca.lt",
|
|
107
|
+
"trycloudflare.com"
|
|
73
108
|
];
|
|
74
109
|
|
|
75
110
|
// Directive phrases targeting an LLM / auditor. Kept narrow on purpose — generic
|
|
@@ -538,7 +573,7 @@ function inspectExecNetworkCombinations(file, content, lower, findings) {
|
|
|
538
573
|
const hasDynamicEval = DYNAMIC_EVAL_REGEX.test(content);
|
|
539
574
|
const hasNetwork = NETWORK_REGEX.test(content) || SHELL_NETWORK_REGEX.test(content);
|
|
540
575
|
const hardcodedIp = findPublicIpInCode(content);
|
|
541
|
-
const shortener =
|
|
576
|
+
const shortener = EXFIL_AND_CALLBACK_DOMAINS.find((pattern) => lower.includes(pattern));
|
|
542
577
|
const hasBulkEnv = BULK_ENV_REGEXES.some((re) => re.test(content));
|
|
543
578
|
|
|
544
579
|
// HIGH: real exfil/loader signal — execution OR network plus a hardcoded IP /
|