@lateos/npm-scan 0.14.0 → 0.15.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
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
4
4
|
[](LICENSING.md)
|
|
5
5
|
[](package.json)
|
|
6
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
7
|
+
[](https://github.com/lateos-ai/npm-scan)
|
|
8
8
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
9
9
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
10
10
|
|
|
@@ -71,6 +71,7 @@ Attackers have moved past simple typosquatting. They now ship **obfuscated prein
|
|
|
71
71
|
| 🛡️ | **Zero telemetry** | No data leaves your machine. No cloud. No callbacks. |
|
|
72
72
|
| 💾 | **Local scan history** | SQLite-backed persistence, zero external dependencies |
|
|
73
73
|
| 🪝 | **Pre-commit hook** | Block threats before commit — one-liner install, scans `package-lock.json` changes |
|
|
74
|
+
| 📎 | **Yarn + pnpm support** | `scan-lockfile` parses `yarn.lock` and `pnpm-lock.yaml` alongside `package-lock.json` |
|
|
74
75
|
|
|
75
76
|
---
|
|
76
77
|
|
|
@@ -190,12 +191,16 @@ npm-scan scan --file path/to/malicious-package.tgz
|
|
|
190
191
|
### Scan a lockfile
|
|
191
192
|
|
|
192
193
|
```bash
|
|
193
|
-
# Scan the current project's dependencies
|
|
194
|
+
# Scan the current project's dependencies (auto-detects npm/yarn/pnpm)
|
|
194
195
|
npm-scan scan-lockfile
|
|
195
196
|
|
|
196
197
|
# Scan a specific lockfile
|
|
197
198
|
npm-scan scan-lockfile -f ./path/to/package-lock.json
|
|
198
199
|
|
|
200
|
+
# Scan yarn.lock or pnpm-lock.yaml
|
|
201
|
+
npm-scan scan-lockfile -f ./yarn.lock --yarn
|
|
202
|
+
npm-scan scan-lockfile -f ./pnpm-lock.yaml --pnpm
|
|
203
|
+
|
|
199
204
|
# Fail CI/CD on high or critical findings (exit code 1)
|
|
200
205
|
npm-scan scan-lockfile --fail-on high
|
|
201
206
|
|
|
@@ -211,7 +216,7 @@ npm-scan scan-lockfile --watch
|
|
|
211
216
|
# Watch with faster debounce (500ms) — great for dev workflows
|
|
212
217
|
npm-scan scan-lockfile --watch --debounce 500
|
|
213
218
|
|
|
214
|
-
# Watch monorepo (all
|
|
219
|
+
# Watch monorepo (all lockfiles — npm/yarn/pnpm — in workspace)
|
|
215
220
|
npm-scan scan-lockfile --watch --monorepo
|
|
216
221
|
|
|
217
222
|
# Output only risk score (0-10) for dashboards/thresholds
|
|
@@ -686,8 +691,12 @@ node --test test/detectors-corpus.test.js
|
|
|
686
691
|
- `test/detectors-corpus.test.js` — 33 malicious + 50 clean tarball integration (offline)
|
|
687
692
|
- `test/fetch.test.js` — tarball extraction, temp directory cleanup
|
|
688
693
|
- `test/policy-edge-cases.test.js` — edge cases in suppress, override, load validation
|
|
694
|
+
- `test/policy.test.js` — policy YAML/JSON load, apply, suppress, severity override tests
|
|
689
695
|
- `test/report-snapshots.test.js` — HTML/text/CRA/PDF format assertions
|
|
696
|
+
- `test/report.test.js` — SARIF, CSV, STIG, risk score format tests
|
|
697
|
+
- `test/lockfile.test.js` — npm/yarn/pnpm parser, auto-detect, ATK-007/011 lockfile tests
|
|
690
698
|
- `test/cli.test.js` — commander integration tests (help, version, scan, report, error handling)
|
|
699
|
+
- `test/cli-lockfile.test.js` — scan-lockfile CLI options, yarn/pnpm/monorepo/watch tests
|
|
691
700
|
|
|
692
701
|
### Need help?
|
|
693
702
|
|
package/backend/license.js
CHANGED
|
@@ -78,6 +78,10 @@ export function validateLicense(key, feature = '*') {
|
|
|
78
78
|
|
|
79
79
|
export function isFeatureEnabled(feature, licenseKey = process.env.NPM_SCAN_LICENSE_KEY) {
|
|
80
80
|
try {
|
|
81
|
+
if (!licenseKey) {
|
|
82
|
+
const unlocked = feature === 'scan' || ALLOWED_UNLOCKED.includes(feature);
|
|
83
|
+
if (unlocked) return true;
|
|
84
|
+
}
|
|
81
85
|
validateLicense(licenseKey, feature);
|
|
82
86
|
return true;
|
|
83
87
|
} catch {
|
package/backend/lockfile.js
CHANGED
|
@@ -126,10 +126,10 @@ function parseYarnLockfile(content, filePath) {
|
|
|
126
126
|
if (bodyTrim.startsWith('version ')) {
|
|
127
127
|
const vMatch = bodyTrim.match(/^version ['"]([^'"]+)['"]/);
|
|
128
128
|
if (vMatch) version = vMatch[1];
|
|
129
|
-
} else if (bodyTrim.
|
|
130
|
-
const rMatch = bodyTrim.match(
|
|
129
|
+
} else if (bodyTrim.match(/^\s*resolved\s+(.+)/)) {
|
|
130
|
+
const rMatch = bodyTrim.match(/^\s*resolved\s+(.+)/);
|
|
131
131
|
if (rMatch) {
|
|
132
|
-
resolved = rMatch[1];
|
|
132
|
+
resolved = rMatch[1].trim().replace(/^['"]|['"]$/g, '');
|
|
133
133
|
if (resolved.startsWith('https://registry.yarnpkg.com/')) {
|
|
134
134
|
resolved = resolved.replace('https://registry.yarnpkg.com/', 'https://registry.npmjs.org/');
|
|
135
135
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lateos/npm-scan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Modern npm supply chain security scanner — detects obfuscated payloads, credential stealers, conditional triggers, sandbox evasion, and worm-like propagation. 11 attack types, SBOM, NIST/EU CRA compliance reporting.",
|
|
5
5
|
"main": "backend/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "test-project",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"lockfileVersion": 3,
|
|
5
|
+
"packages": {
|
|
6
|
+
"": {
|
|
7
|
+
"name": "test-project",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"lodash": "^4.17.21",
|
|
11
|
+
"axios": "^1.6.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@babel/core": "^7.23.0"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"node_modules/lodash": {
|
|
18
|
+
"name": "lodash",
|
|
19
|
+
"version": "4.17.21",
|
|
20
|
+
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
21
|
+
"integrity": "sha512-v2kDEeDAnj4p1hhL6Ogrgu4BSWwg8cD2fRIouDAiqwu+iNl1IvyMex9jG9j8OpNp1zntnv/headququbit",
|
|
22
|
+
"dependencies": {}
|
|
23
|
+
},
|
|
24
|
+
"node_modules/axios": {
|
|
25
|
+
"name": "axios",
|
|
26
|
+
"version": "1.6.8",
|
|
27
|
+
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
|
|
28
|
+
"integrity": "sha512-j2xvyqwsdd456789abcdef",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"form-data": "4.0.0",
|
|
31
|
+
"proxy-from-env": "1.1.0"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"node_modules/axios/node_modules/form-data": {
|
|
35
|
+
"version": "4.0.0",
|
|
36
|
+
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
|
37
|
+
"integrity": "sha512-444567890123456"
|
|
38
|
+
},
|
|
39
|
+
"node_modules/@babel/core": {
|
|
40
|
+
"name": "@babel/core",
|
|
41
|
+
"version": "7.23.9",
|
|
42
|
+
"resolved": "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz",
|
|
43
|
+
"integrity": "sha512-5q+M1iEJCOrGJs9NxzG3p3z7w2cJK/QuoRoI2pOJhtcNQjl9y7w6w4At5ZQHZdwqd+5N5G1lULu7I6pXVBw==",
|
|
44
|
+
"dev": true,
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@babel/generator": "^7.23.6",
|
|
47
|
+
"@babel/parser": "^7.23.9"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"node_modules/reakt": {
|
|
51
|
+
"name": "reakt",
|
|
52
|
+
"version": "18.2.0",
|
|
53
|
+
"resolved": "https://registry.yarnpkg.com/reakt/-/reakt-18.2.0.tgz",
|
|
54
|
+
"integrity": "sha-abcdabcd1234defghi",
|
|
55
|
+
"optional": true,
|
|
56
|
+
"dependencies": {}
|
|
57
|
+
},
|
|
58
|
+
"node_modules/express": {
|
|
59
|
+
"name": "express",
|
|
60
|
+
"version": "4.18.2",
|
|
61
|
+
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
|
62
|
+
"integrity": "sha512-abcdabcd1234abcdefghi",
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"accepts": "~1.3.8",
|
|
65
|
+
"body-parser": "1.20.2"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
lodash@^4.17.21:
|
|
2
2
|
version "4.17.21"
|
|
3
|
-
resolved "https://registry.
|
|
3
|
+
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz"
|
|
4
4
|
integrity sha512-Vythumb
|
|
5
5
|
dependencies: {}
|
|
6
6
|
dev false
|
|
7
|
-
optional
|
|
7
|
+
optional true
|
|
8
8
|
|
|
9
9
|
axios@^1.6.0:
|
|
10
10
|
version "1.6.8"
|
|
11
|
-
resolved "https://registry.
|
|
12
|
-
integrity
|
|
11
|
+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz"
|
|
12
|
+
integrity sha-j2xvyqwsdd456789abcdef
|
|
13
13
|
dependencies:
|
|
14
14
|
form-data "4.0.0"
|
|
15
15
|
proxy-from-env "1.1.0"
|
|
@@ -30,6 +30,7 @@ axios@^1.6.0:
|
|
|
30
30
|
gensync "^1.0.0-beta.2"
|
|
31
31
|
json5 "^2.2.3"
|
|
32
32
|
semver "^6.3.1"
|
|
33
|
+
rimraf "^3.0.2"
|
|
33
34
|
dev true
|
|
34
35
|
optional false
|
|
35
36
|
|
|
@@ -45,7 +46,7 @@ axios@^1.6.0:
|
|
|
45
46
|
dev false
|
|
46
47
|
optional false
|
|
47
48
|
|
|
48
|
-
reakt@^18.2.0
|
|
49
|
+
reakt@^18.2.0:
|
|
49
50
|
version "18.2.0"
|
|
50
51
|
resolved "https://registry.yarnpkg.com/reakt/-/reakt-18.2.0.tgz"
|
|
51
52
|
integrity sha512-abcdabcd1234defghi
|
|
@@ -53,7 +54,7 @@ reakt@^18.2.0, reakt@^18.2.0::version=18.2.0:
|
|
|
53
54
|
dev false
|
|
54
55
|
optional true
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
express@npm:expres@^4.18.2:
|
|
57
58
|
version "4.18.2"
|
|
58
59
|
resolved "https://registry.npmjs.org/expres-4.18.2.tgz"
|
|
59
60
|
integrity sha512-abcdabcd1234abcdefghi
|
|
@@ -92,7 +93,7 @@ reakt@^18.2.0, reakt@^18.2.0::version=18.2.0:
|
|
|
92
93
|
dev false
|
|
93
94
|
optional false
|
|
94
95
|
|
|
95
|
-
"my-scope-plugin@npm:my-scope-plugin@^1.0.0"
|
|
96
|
+
"my-scope-plugin@npm:my-scope-plugin@^1.0.0":
|
|
96
97
|
version "1.0.0"
|
|
97
98
|
resolved "https://registry.npmjs.org/my-scope-plugin-1.0.0.tgz"
|
|
98
99
|
integrity sha512-abcdefghijk123456789abcdef
|