@lateos/npm-scan 1.0.0 → 1.1.1
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.de.md +3 -98
- package/README.fr.md +3 -98
- package/README.ja.md +3 -98
- package/README.md +2 -122
- package/README.zh.md +3 -98
- package/backend/cra.js +113 -21
- package/backend/db.js +18 -10
- package/backend/detectors/atk-001-lifecycle.js +5 -5
- package/backend/detectors/atk-002-obfusc.js +126 -47
- package/backend/detectors/atk-003-creds.js +8 -4
- package/backend/detectors/atk-004-persist.js +3 -3
- package/backend/detectors/atk-005-exfil.js +8 -4
- package/backend/detectors/atk-006-depconf.js +3 -3
- package/backend/detectors/atk-007-typosquat.js +64 -10
- package/backend/detectors/atk-008-tarball-tamper.js +6 -6
- package/backend/detectors/atk-009-dormant-trigger.js +9 -5
- package/backend/detectors/atk-010-sandbox-evasion.js +25 -10
- package/backend/detectors/atk-011-transitive-prop.js +14 -13
- package/backend/detectors/axios-poisoning/d1-version-fingerprint.js +4 -4
- package/backend/detectors/axios-poisoning/d2-decoy-dep.js +5 -1
- package/backend/detectors/axios-poisoning/d3-postinstall-rat.js +64 -19
- package/backend/detectors/axios-poisoning/index.js +77 -60
- package/backend/detectors/config/thresholds.js +48 -3
- package/backend/detectors/cve-2026-48710-badhost/codePattern.js +26 -9
- package/backend/detectors/cve-2026-48710-badhost/findings.js +8 -4
- package/backend/detectors/cve-2026-48710-badhost/index.js +1 -1
- package/backend/detectors/cve-2026-48710-badhost/manifest.js +127 -39
- package/backend/detectors/cve-2026-48710-badhost/transitive.js +87 -28
- package/backend/detectors/hf-impersonation/index.js +94 -31
- package/backend/detectors/hf-impersonation/jaro-winkler.js +33 -12
- package/backend/detectors/hf-impersonation/known-orgs.js +15 -3
- package/backend/detectors/hf-impersonation/simhash.js +2 -2
- package/backend/detectors/index.js +181 -34
- package/backend/detectors/lib/ast-patterns.js +4 -1
- package/backend/detectors/lib/entropy-analyzer.js +12 -4
- package/backend/detectors/megalodon/d1-workflow-scan.js +40 -16
- package/backend/detectors/megalodon/d2-credential-harvest.js +12 -5
- package/backend/detectors/megalodon/d3-publish-velocity.js +17 -11
- package/backend/detectors/megalodon/d4-publisher-drift.js +48 -16
- package/backend/detectors/megalodon/d5-bot-commit-identity.js +1 -1
- package/backend/detectors/megalodon/d6-date-anachronism.js +1 -1
- package/backend/detectors/megalodon/index.js +35 -25
- package/backend/detectors/mini-shai-hulud/d1-burst-publish.js +3 -1
- package/backend/detectors/mini-shai-hulud/d2-sibling-compromise.js +22 -10
- package/backend/detectors/mini-shai-hulud/d3-slsa-mismatch.js +30 -10
- package/backend/detectors/mini-shai-hulud/d4-maintainer-anomaly.js +17 -13
- package/backend/detectors/mini-shai-hulud/d5-ioc-check.js +12 -4
- package/backend/detectors/mini-shai-hulud/d6-token-exfil.js +6 -2
- package/backend/detectors/mini-shai-hulud/index.js +63 -26
- package/backend/detectors/msh-supplement/d2-persistence.js +30 -12
- package/backend/detectors/msh-supplement/d3-geo-killswitch.js +20 -8
- package/backend/detectors/msh-supplement/d4-c2-deaddrop.js +19 -5
- package/backend/detectors/msh-supplement/index.js +78 -63
- package/backend/detectors/node-ipc-compromise/d1-version-blocklist.js +4 -2
- package/backend/detectors/node-ipc-compromise/d10-unauthorized-publisher.js +9 -5
- package/backend/detectors/node-ipc-compromise/d11-blast-radius.js +7 -3
- package/backend/detectors/node-ipc-compromise/d2-tarball-hash.js +9 -4
- package/backend/detectors/node-ipc-compromise/d3-cjs-payload-injection.js +7 -5
- package/backend/detectors/node-ipc-compromise/d4-injected-payload-hash.js +4 -2
- package/backend/detectors/node-ipc-compromise/d5-dns-c2-pattern.js +13 -10
- package/backend/detectors/node-ipc-compromise/d7-dns-txt-exfil.js +3 -1
- package/backend/detectors/node-ipc-compromise/d8-runtime-trigger.js +5 -2
- package/backend/detectors/node-ipc-compromise/index.js +21 -15
- package/backend/detectors/tier1-binary-embed.js +109 -41
- package/backend/detectors/tier1-cloud-imds.js +57 -37
- package/backend/detectors/tier1-encrypted-c2.js +198 -0
- package/backend/detectors/tier1-infostealer.js +121 -68
- package/backend/detectors/tier1-lifecycle-hook.js +63 -23
- package/backend/detectors/tier1-maintainer-compromise.js +157 -0
- package/backend/detectors/tier1-metadata-spoof.js +92 -42
- package/backend/detectors/tier1-multistage-postinstall.js +46 -19
- package/backend/detectors/tier1-obfuscation-heuristics.js +45 -17
- package/backend/detectors/tier1-self-propagation.js +115 -0
- package/backend/detectors/tier1-slsa-attestation.js +1 -1
- package/backend/detectors/tier1-transitive-deps.js +182 -0
- package/backend/detectors/tier1-typosquat.js +129 -50
- package/backend/detectors/tier1-version-anomaly.js +77 -41
- package/backend/detectors/tier1-version-confusion.js +79 -59
- package/backend/detectors/trapdoor/d1-campaign-marker.js +3 -1
- package/backend/detectors/trapdoor/d2-payload-fingerprint.js +1 -1
- package/backend/detectors/trapdoor/d3-publisher-blocklist.js +4 -3
- package/backend/detectors/trapdoor/d4-gists-exfil.js +4 -2
- package/backend/detectors/trapdoor/d5-ai-poisoning.js +5 -3
- package/backend/detectors/trapdoor/d6-lure-name.js +12 -7
- package/backend/detectors/trapdoor/d7-crypto-primitives.js +2 -2
- package/backend/detectors/trapdoor/d8-xor-key.js +7 -2
- package/backend/detectors/trapdoor/d9-cred-validation.js +4 -5
- package/backend/detectors/trapdoor/index.js +19 -14
- package/backend/detectors/typosquat-vpmdhaj/d1-maintainer.js +32 -8
- package/backend/detectors/typosquat-vpmdhaj/d2-preinstall-loader.js +5 -3
- package/backend/detectors/typosquat-vpmdhaj/d3-cred-exfil.js +34 -12
- package/backend/detectors/typosquat-vpmdhaj/index.js +78 -59
- package/backend/detectors.test.js +78 -19
- package/backend/fetch.js +37 -29
- package/backend/index.js +1 -1
- package/backend/license.js +20 -4
- package/backend/lockfile.js +60 -36
- package/backend/pdf.js +107 -28
- package/backend/policy.js +183 -56
- package/backend/provenance.js +28 -3
- package/backend/report.js +136 -70
- package/backend/sbom.js +33 -27
- package/backend/scripts/analyze-false-positives.js +14 -8
- package/backend/scripts/analyze-validation.js +27 -21
- package/backend/scripts/detect-false-positives.js +20 -10
- package/backend/scripts/fetch-top-packages.js +197 -49
- package/backend/scripts/validate-d10-d13.js +103 -0
- package/backend/scripts/validate-detectors.js +26 -17
- package/backend/siem/cef.js +23 -21
- package/backend/siem/ecs.js +3 -3
- package/backend/siem/index.js +1 -1
- package/backend/siem/qradar.js +3 -3
- package/backend/siem/sentinel.js +2 -2
- package/backend/tests-d5-enhanced.test.js +13 -12
- package/backend/tests-d6-version-anomaly.test.js +17 -8
- package/backend/tests-d6.test.js +24 -14
- package/backend/tests-d6c.test.js +27 -14
- package/backend/tests-d7-obfuscation.test.js +9 -12
- package/backend/tests.test.js +182 -83
- package/backend/vsix-scan/detectors/activation-event-risk.js +36 -19
- package/backend/vsix-scan/detectors/burst-publish.js +14 -7
- package/backend/vsix-scan/detectors/exfil-pattern.js +7 -3
- package/backend/vsix-scan/detectors/known-ioc.js +23 -8
- package/backend/vsix-scan/detectors/orphan-commit-fetch.js +11 -7
- package/backend/vsix-scan/detectors/publisher-anomaly.js +24 -10
- package/backend/vsix-scan/index.js +97 -41
- package/backend/vsix-scan/marketplace-client.js +29 -13
- package/cli/cli.js +154 -64
- package/package.json +12 -3
|
@@ -8,7 +8,7 @@ describe('D6a — tier1-version-confusion', () => {
|
|
|
8
8
|
test('D6a: exact sentinel 99.99.99 → HIGH, confidenceScore >= 80', async () => {
|
|
9
9
|
const pkg = { name: 'internal-utils', version: '99.99.99' };
|
|
10
10
|
const findings = await detectors.runAll(pkg);
|
|
11
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
11
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
12
12
|
assert(match, 'Expected TIER1-VERSION-CONFUSION finding');
|
|
13
13
|
assert.equal(match.confidence, 'HIGH');
|
|
14
14
|
assert(match.confidenceScore >= 80, `confidenceScore ${match.confidenceScore} < 80`);
|
|
@@ -17,7 +17,7 @@ describe('D6a — tier1-version-confusion', () => {
|
|
|
17
17
|
test('D6a: exact sentinel 9.9.9 → MEDIUM, confidenceScore >= 60', async () => {
|
|
18
18
|
const pkg = { name: 'corp-auth', version: '9.9.9' };
|
|
19
19
|
const findings = await detectors.runAll(pkg);
|
|
20
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
20
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
21
21
|
assert(match, 'Expected TIER1-VERSION-CONFUSION finding');
|
|
22
22
|
assert.equal(match.confidence, 'MEDIUM');
|
|
23
23
|
assert(match.confidenceScore >= 60, `confidenceScore ${match.confidenceScore} < 60`);
|
|
@@ -26,7 +26,7 @@ describe('D6a — tier1-version-confusion', () => {
|
|
|
26
26
|
test('D6a: high-version heuristic 99.5.8 → MEDIUM, confidenceScore >= 60', async () => {
|
|
27
27
|
const pkg = { name: 'internal-payments', version: '99.5.8' };
|
|
28
28
|
const findings = await detectors.runAll(pkg);
|
|
29
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
29
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
30
30
|
assert(match, 'Expected TIER1-VERSION-CONFUSION finding');
|
|
31
31
|
assert.equal(match.confidence, 'MEDIUM');
|
|
32
32
|
assert(match.confidenceScore >= 60, `confidenceScore ${match.confidenceScore} < 60`);
|
|
@@ -35,21 +35,21 @@ describe('D6a — tier1-version-confusion', () => {
|
|
|
35
35
|
test('D6a: heuristic does not fire on legitimate high patch, e.g. 1.99.0', async () => {
|
|
36
36
|
const pkg = { name: 'some-lib', version: '1.99.0' };
|
|
37
37
|
const findings = await detectors.runAll(pkg);
|
|
38
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
38
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
39
39
|
assert(!match);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test('D6a: no finding on legitimate semver 4.17.21', async () => {
|
|
43
43
|
const pkg = { name: 'lodash', version: '4.17.21' };
|
|
44
44
|
const findings = await detectors.runAll(pkg);
|
|
45
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
45
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
46
46
|
assert(!match);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
test('D6a: no finding on KNOWN_REPUTABLE_PACKAGES regardless of version', async () => {
|
|
50
50
|
const pkg = { name: 'react', version: '99.99.99' };
|
|
51
51
|
const findings = await detectors.runAll(pkg);
|
|
52
|
-
const match = findings.find(f => f.id === 'TIER1-VERSION-CONFUSION');
|
|
52
|
+
const match = findings.find((f) => f.id === 'TIER1-VERSION-CONFUSION');
|
|
53
53
|
assert(!match);
|
|
54
54
|
});
|
|
55
55
|
});
|
|
@@ -58,18 +58,30 @@ describe('D6a — tier1-version-confusion', () => {
|
|
|
58
58
|
|
|
59
59
|
describe('D6c — tier1-cloud-imds', () => {
|
|
60
60
|
test('D6c: detects GCP metadata endpoint in JS file', async () => {
|
|
61
|
-
const jsFiles = [
|
|
61
|
+
const jsFiles = [
|
|
62
|
+
{
|
|
63
|
+
path: 'index.js',
|
|
64
|
+
content:
|
|
65
|
+
'fetch("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")',
|
|
66
|
+
},
|
|
67
|
+
];
|
|
62
68
|
const findings = await detectors.runAll({ name: 'test-pkg' }, jsFiles);
|
|
63
|
-
const match = findings.find(f => f.id === 'TIER1-CLOUD-IMDS');
|
|
69
|
+
const match = findings.find((f) => f.id === 'TIER1-CLOUD-IMDS');
|
|
64
70
|
assert(match, 'Expected TIER1-CLOUD-IMDS finding');
|
|
65
71
|
assert.equal(match.confidence, 'HIGH');
|
|
66
72
|
assert(match.confidenceScore >= 80, `confidenceScore ${match.confidenceScore} < 80`);
|
|
67
73
|
});
|
|
68
74
|
|
|
69
75
|
test('D6c: detects Azure IMDS endpoint in JS file', async () => {
|
|
70
|
-
const jsFiles = [
|
|
76
|
+
const jsFiles = [
|
|
77
|
+
{
|
|
78
|
+
path: 'app.js',
|
|
79
|
+
content:
|
|
80
|
+
'axios.get("http://169.254.169.254/metadata/instance", { headers: { Metadata: "true" } })',
|
|
81
|
+
},
|
|
82
|
+
];
|
|
71
83
|
const findings = await detectors.runAll({ name: 'test-pkg' }, jsFiles);
|
|
72
|
-
const match = findings.find(f => f.id === 'TIER1-CLOUD-IMDS');
|
|
84
|
+
const match = findings.find((f) => f.id === 'TIER1-CLOUD-IMDS');
|
|
73
85
|
assert(match, 'Expected TIER1-CLOUD-IMDS finding');
|
|
74
86
|
assert.equal(match.confidence, 'HIGH');
|
|
75
87
|
assert(match.confidenceScore >= 80, `confidenceScore ${match.confidenceScore} < 80`);
|
|
@@ -80,11 +92,12 @@ describe('D6c — tier1-cloud-imds', () => {
|
|
|
80
92
|
name: 'malicious-pkg',
|
|
81
93
|
version: '1.0.0',
|
|
82
94
|
scripts: {
|
|
83
|
-
postinstall:
|
|
95
|
+
postinstall:
|
|
96
|
+
'node -e "require(\\"http\\").get(\\"http://metadata.google.internal/computeMetadata/v1/\\")"',
|
|
84
97
|
},
|
|
85
98
|
};
|
|
86
99
|
const findings = await detectors.runAll(pkg);
|
|
87
|
-
const match = findings.find(f => f.id === 'TIER1-CLOUD-IMDS');
|
|
100
|
+
const match = findings.find((f) => f.id === 'TIER1-CLOUD-IMDS');
|
|
88
101
|
assert(match, 'Expected TIER1-CLOUD-IMDS finding');
|
|
89
102
|
assert.equal(match.confidence, 'HIGH');
|
|
90
103
|
assert(match.confidenceScore >= 80, `confidenceScore ${match.confidenceScore} < 80`);
|
|
@@ -93,14 +106,14 @@ describe('D6c — tier1-cloud-imds', () => {
|
|
|
93
106
|
test('D6c: no finding on clean JS with no IMDS patterns', async () => {
|
|
94
107
|
const jsFiles = [{ path: 'clean.js', content: 'const x = 1 + 1;' }];
|
|
95
108
|
const findings = await detectors.runAll({ name: 'test-pkg' }, jsFiles);
|
|
96
|
-
const match = findings.find(f => f.id === 'TIER1-CLOUD-IMDS');
|
|
109
|
+
const match = findings.find((f) => f.id === 'TIER1-CLOUD-IMDS');
|
|
97
110
|
assert(!match);
|
|
98
111
|
});
|
|
99
112
|
|
|
100
113
|
test('D6c: no finding when 169.254.169.254 appears without /metadata path', async () => {
|
|
101
114
|
const jsFiles = [{ path: 'docs.js', content: '// link-local range starts at 169.254.0.0' }];
|
|
102
115
|
const findings = await detectors.runAll({ name: 'test-pkg' }, jsFiles);
|
|
103
|
-
const match = findings.find(f => f.id === 'TIER1-CLOUD-IMDS');
|
|
116
|
+
const match = findings.find((f) => f.id === 'TIER1-CLOUD-IMDS');
|
|
104
117
|
assert(!match);
|
|
105
118
|
});
|
|
106
119
|
});
|
|
@@ -4,29 +4,27 @@ import * as detectors from './detectors/index.js';
|
|
|
4
4
|
|
|
5
5
|
describe('D7: Obfuscation Heuristics', () => {
|
|
6
6
|
test('D7: flags heavily obfuscated postinstall script', async () => {
|
|
7
|
-
const obfuscated =
|
|
8
|
-
`var _0x=["eval","fromCharCode","charCodeAt"];for(var i=0;i<999;i++){var x=String.fromCharCode(i);if(i>500){eval(atob("Y29uc3QgeCA9ICdtYWxpY2lvdXMnO2V2YWwoeCk7Y29uc3QgeSA9ICdiYWNrZG9vcic7ZXZhbCh5KTs="))}}var _0xe="\\x65\\x76\\x61\\x6c\\x28\\x61\\x74\\x6f\\x62\\x28\\x22\\x59\\x6d\\x39\\x75\\x62\\x47\\x38\\x67"`;
|
|
7
|
+
const obfuscated = `var _0x=["eval","fromCharCode","charCodeAt"];for(var i=0;i<999;i++){var x=String.fromCharCode(i);if(i>500){eval(atob("Y29uc3QgeCA9ICdtYWxpY2lvdXMnO2V2YWwoeCk7Y29uc3QgeSA9ICdiYWNrZG9vcic7ZXZhbCh5KTs="))}}var _0xe="\\x65\\x76\\x61\\x6c\\x28\\x61\\x74\\x6f\\x62\\x28\\x22\\x59\\x6d\\x39\\x75\\x62\\x47\\x38\\x67"`;
|
|
9
8
|
const pkg = {
|
|
10
9
|
name: 'malicious-pkg',
|
|
11
10
|
version: '1.0.0',
|
|
12
11
|
scripts: { postinstall: obfuscated },
|
|
13
12
|
};
|
|
14
13
|
const findings = await detectors.runAll(pkg);
|
|
15
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
14
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
16
15
|
assert(match, 'Expected TIER1-OBFUSCATION-HEURISTICS finding');
|
|
17
16
|
assert(match.confidenceScore >= 75, `confidenceScore ${match.confidenceScore} < 75`);
|
|
18
17
|
});
|
|
19
18
|
|
|
20
19
|
test('D7: detects XOR cipher pattern in preinstall script', async () => {
|
|
21
|
-
const xorCode =
|
|
22
|
-
`var _0xk=[0x66,0x6c,0x61,0x67];var _0xd="LzdHJKdUp4VWt5S292RXBsb3Zlck5pZ2h0U2VjcmV0S2V5Rm9yRW50cm9weUJvb3N0";let r='';for(let i=0;i<str.length;i++){r+=String.fromCharCode(str.charCodeAt(i)^_0xk[i%4]);if(i>50){eval(atob("RGV0ZWN0ZWQ="))}}`;
|
|
20
|
+
const xorCode = `var _0xk=[0x66,0x6c,0x61,0x67];var _0xd="LzdHJKdUp4VWt5S292RXBsb3Zlck5pZ2h0U2VjcmV0S2V5Rm9yRW50cm9weUJvb3N0";let r='';for(let i=0;i<str.length;i++){r+=String.fromCharCode(str.charCodeAt(i)^_0xk[i%4]);if(i>50){eval(atob("RGV0ZWN0ZWQ="))}}`;
|
|
23
21
|
const pkg = {
|
|
24
22
|
name: 'suspicious-pkg',
|
|
25
23
|
version: '1.0.0',
|
|
26
24
|
scripts: { preinstall: xorCode },
|
|
27
25
|
};
|
|
28
26
|
const findings = await detectors.runAll(pkg);
|
|
29
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
27
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
30
28
|
assert(match, 'Expected TIER1-OBFUSCATION-HEURISTICS finding');
|
|
31
29
|
assert(match.confidenceScore >= 70, `confidenceScore ${match.confidenceScore} < 70`);
|
|
32
30
|
});
|
|
@@ -43,20 +41,19 @@ describe('D7: Obfuscation Heuristics', () => {
|
|
|
43
41
|
scripts: { postinstall: normalCode },
|
|
44
42
|
};
|
|
45
43
|
const findings = await detectors.runAll(pkg);
|
|
46
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
44
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
47
45
|
assert(!match, 'Should not flag normal palindrome function');
|
|
48
46
|
});
|
|
49
47
|
|
|
50
48
|
test('D7: flags high entropy in postinstall script', async () => {
|
|
51
|
-
const highEntropyCode =
|
|
52
|
-
`var x="T3NobmFJc0VudHJvcHlCb29zdGVkV2l0aEJhc2U2NFBheWxvYWRUaGF0U2hvdWxkQmVQbGVudHlPZkNoYXJhY3RlcnNGb3JIaWdoRW50cm9weVNjb3JlQW5kSXRTaG91bGRCZU9mVmVyeUhpZ2hRdWFsaXR5VG9NYWtlVGhlVGVzdFBhc3NBbmRJdFNob3VsZEJlT2ZNaXhlZENhc2VXaXRoTnVtYmVyc0FuZFNwZWNpYWxDaGFyYWN0ZXJzRm9yTWF4RW50cm9weQ==";`;
|
|
49
|
+
const highEntropyCode = `var x="T3NobmFJc0VudHJvcHlCb29zdGVkV2l0aEJhc2U2NFBheWxvYWRUaGF0U2hvdWxkQmVQbGVudHlPZkNoYXJhY3RlcnNGb3JIaWdoRW50cm9weVNjb3JlQW5kSXRTaG91bGRCZU9mVmVyeUhpZ2hRdWFsaXR5VG9NYWtlVGhlVGVzdFBhc3NBbmRJdFNob3VsZEJlT2ZNaXhlZENhc2VXaXRoTnVtYmVyc0FuZFNwZWNpYWxDaGFyYWN0ZXJzRm9yTWF4RW50cm9weQ==";`;
|
|
53
50
|
const pkg = {
|
|
54
51
|
name: 'high-entropy-pkg',
|
|
55
52
|
version: '1.0.0',
|
|
56
53
|
scripts: { postinstall: highEntropyCode },
|
|
57
54
|
};
|
|
58
55
|
const findings = await detectors.runAll(pkg);
|
|
59
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
56
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
60
57
|
assert(match, 'Expected TIER1-OBFUSCATION-HEURISTICS finding');
|
|
61
58
|
assert(match.confidenceScore >= 55, `confidenceScore ${match.confidenceScore} < 55`);
|
|
62
59
|
});
|
|
@@ -74,7 +71,7 @@ describe('D7: Obfuscation Heuristics', () => {
|
|
|
74
71
|
scripts: { postinstall: cleanCode },
|
|
75
72
|
};
|
|
76
73
|
const findings = await detectors.runAll(pkg);
|
|
77
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
74
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
78
75
|
assert(!match, 'Should not flag clean build script');
|
|
79
76
|
});
|
|
80
77
|
|
|
@@ -85,7 +82,7 @@ describe('D7: Obfuscation Heuristics', () => {
|
|
|
85
82
|
scripts: { postinstall: 'eval(atob("dmFyIHg9J21hbGljaW91cyc7"))' },
|
|
86
83
|
};
|
|
87
84
|
const findings = await detectors.runAll(pkg);
|
|
88
|
-
const match = findings.find(f => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
85
|
+
const match = findings.find((f) => f.id === 'TIER1-OBFUSCATION-HEURISTICS');
|
|
89
86
|
assert(!match);
|
|
90
87
|
});
|
|
91
88
|
});
|