@lateos/npm-scan 0.16.0 → 0.16.4

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.
@@ -0,0 +1,98 @@
1
+ import { scanMaintainerAnomaly } from './d1-maintainer.js';
2
+ import { scanPreinstallLoader } from './d2-preinstall-loader.js';
3
+ import { scanCredExfil } from './d3-cred-exfil.js';
4
+ import { attachProvenance } from '../../provenance.js';
5
+
6
+ const RULE_SEVERITY = { D1: 'critical', D2: 'critical', D3: 'critical' };
7
+ const SEVERITY_ORDER = ['critical', 'high', 'medium', 'low', 'info', 'none'];
8
+
9
+ function highestSeverity(severities) {
10
+ for (const s of SEVERITY_ORDER) if (severities.includes(s)) return s;
11
+ return 'none';
12
+ }
13
+
14
+ export async function scan(pkgJson, files = [], registryMeta = null, allFiles = null) {
15
+ const pkgName = pkgJson?.name || 'unknown';
16
+ const pkgVersion = pkgJson?.version || '0.0.0';
17
+ const fileList = allFiles || files || [];
18
+
19
+ const d1Result = scanMaintainerAnomaly(pkgJson, registryMeta);
20
+ if (d1Result.stopCondition) {
21
+ const evidence = attachProvenance({
22
+ rule: 'TSQ-MAINT-001',
23
+ campaign: 'TYPOSQUAT_VPMDHAJ',
24
+ triggeredChecks: ['D1'],
25
+ maintainer: d1Result.maintainer,
26
+ suspiciousAliases: d1Result.suspiciousAliases,
27
+ action: 'BLOCK',
28
+ }, {
29
+ ruleId: 'TSQ-MAINT-001',
30
+ ruleName: 'Maintainer & Package Alias Anomalies',
31
+ severity: 'CRITICAL',
32
+ campaignName: 'Mass Typosquatting (vpmdhaj)',
33
+ pkgName,
34
+ pkgVersion,
35
+ triggered: true,
36
+ severity: 'critical',
37
+ indicators: [{ type: 'blocked_maintainer', value: d1Result.maintainer }, ...d1Result.suspiciousAliases.map(a => ({ type: 'suspicious_alias', value: a }))],
38
+ ruleProvenanceUrl: 'https://github.com/lateos/npm-scan/blob/main/backend/detectors/typosquat-vpmdhaj/d1-maintainer.js',
39
+ campaignSourceUrl: 'https://security.researcher.org/supply-chain-report',
40
+ });
41
+
42
+ return [{
43
+ id: 'TYPOSQUAT_VPMDHAJ',
44
+ severity: 'critical',
45
+ title: 'Mass Typosquatting campaign (vpmdhaj) — blocked maintainer',
46
+ description: d1Result.reason,
47
+ evidence: JSON.stringify(evidence),
48
+ mitigation: 'BLOCK IMMEDIATELY. Do not install packages from maintainer vpmdhaj. Audit all packages from your lockfile for this maintainer. Check for typosquatting of popular packages.',
49
+ stopCondition: true,
50
+ }];
51
+ }
52
+
53
+ const d2Result = scanPreinstallLoader(pkgJson);
54
+ const d3Result = scanCredExfil(fileList, pkgJson);
55
+
56
+ const results = {
57
+ D1: d1Result,
58
+ D2: d2Result,
59
+ D3: d3Result,
60
+ };
61
+
62
+ const triggered = Object.entries(results)
63
+ .filter(([_, r]) => r.triggered)
64
+ .map(([id]) => id);
65
+
66
+ if (triggered.length === 0) return [];
67
+
68
+ const severity = highestSeverity(triggered.map(id => RULE_SEVERITY[id]));
69
+
70
+ const evidence = attachProvenance({
71
+ campaign: 'TYPOSQUAT_VPMDHAJ',
72
+ triggeredChecks: triggered,
73
+ details: Object.fromEntries(
74
+ Object.entries(results).filter(([_, r]) => r.triggered)
75
+ ),
76
+ }, {
77
+ ruleId: 'TYPOSQUAT_VPMDHAJ',
78
+ ruleName: 'Mass Typosquatting Campaign Detection',
79
+ severity: severity.toUpperCase(),
80
+ campaignName: 'Mass Typosquatting (vpmdhaj)',
81
+ pkgName,
82
+ pkgVersion,
83
+ triggered: true,
84
+ severity,
85
+ indicators: triggered.map(id => ({ type: `rule_${id}`, value: RULE_SEVERITY[id] })),
86
+ ruleProvenanceUrl: 'https://github.com/lateos/npm-scan/blob/main/backend/detectors/typosquat-vpmdhaj/',
87
+ campaignSourceUrl: 'https://security.researcher.org/supply-chain-report',
88
+ });
89
+
90
+ return [{
91
+ id: 'TYPOSQUAT_VPMDHAJ',
92
+ severity,
93
+ title: 'Mass Typosquatting campaign (vpmdhaj)',
94
+ description: `${triggered.length} signal(s): ${triggered.join(', ')}`,
95
+ evidence: JSON.stringify(evidence),
96
+ mitigation: 'Block install immediately. Revoke any npm tokens. Rotate CI/CD secrets. Audit all packages from maintainer vpmdhaj. If credential exfiltration detected: rotate AWS IAM keys, Vault tokens, and GitHub tokens immediately. Verify CloudTrail/audit logs for unauthorized access.',
97
+ }];
98
+ }
@@ -0,0 +1,79 @@
1
+ import { createHash, createHmac } from 'crypto';
2
+
3
+ const PROVENANCE_VERSION = 'aureus-v1.7';
4
+
5
+ const HMAC_KEY = process.env.AUREUS_HMAC_KEY || '@lateos/npm-scan:provenance:v1';
6
+
7
+ export function hashContent(content) {
8
+ return createHash('sha256').update(JSON.stringify(content)).digest('hex');
9
+ }
10
+
11
+ export function signManifest(manifest, key = HMAC_KEY) {
12
+ return createHmac('sha256', key).update(JSON.stringify(manifest)).digest('hex');
13
+ }
14
+
15
+ export function buildDetectionRule({ ruleId, ruleName, severity, cveReferences = [], campaignName }) {
16
+ return {
17
+ rule_id: ruleId,
18
+ rule_name: ruleName,
19
+ severity,
20
+ cve_references: cveReferences,
21
+ campaign_name: campaignName,
22
+ };
23
+ }
24
+
25
+ export function buildScanMetadata({ scannerVersion, packageAnalyzed }) {
26
+ return {
27
+ scan_timestamp: new Date().toISOString(),
28
+ scanner_version: scannerVersion || '@lateos/npm-scan',
29
+ pipeline_version: PROVENANCE_VERSION,
30
+ package_analyzed: packageAnalyzed,
31
+ };
32
+ }
33
+
34
+ export function buildDetectionResult({ triggered, severity, indicators = [] }) {
35
+ return {
36
+ triggered,
37
+ severity,
38
+ indicators,
39
+ };
40
+ }
41
+
42
+ export function buildAuditTrail({ detectionLogic, ruleProvenanceUrl, campaignSourceUrl }) {
43
+ const contentHash = hashContent(detectionLogic);
44
+ const manifest = { contentHash, ruleProvenanceUrl, campaignSourceUrl, generatedAt: new Date().toISOString() };
45
+ return {
46
+ content_hash: contentHash,
47
+ rule_provenance_url: ruleProvenanceUrl,
48
+ campaign_source_url: campaignSourceUrl,
49
+ hmac_signature: signManifest(manifest),
50
+ _manifest: manifest,
51
+ };
52
+ }
53
+
54
+ export function buildDetectionRecord({ rule, scanMetadata, detectionResult, auditTrail }) {
55
+ return {
56
+ detection_rule: rule,
57
+ scan_metadata: scanMetadata,
58
+ detection_result: detectionResult,
59
+ audit_trail: auditTrail,
60
+ };
61
+ }
62
+
63
+ export function attachProvenance(evidence, { ruleId, ruleName, severity, campaignName, pkgName, pkgVersion, triggered, indicators, ruleProvenanceUrl, campaignSourceUrl }) {
64
+ const rule = buildDetectionRule({ ruleId, ruleName, severity, campaignName });
65
+ const scanMetadata = buildScanMetadata({
66
+ scannerVersion: '@lateos/npm-scan',
67
+ packageAnalyzed: `${pkgName}@${pkgVersion}`,
68
+ });
69
+ const detectionResult = buildDetectionResult({ triggered, severity, indicators });
70
+ const auditTrail = buildAuditTrail({
71
+ detectionLogic: { rule, indicators },
72
+ ruleProvenanceUrl,
73
+ campaignSourceUrl,
74
+ });
75
+ const record = buildDetectionRecord({ rule, scanMetadata, detectionResult, auditTrail });
76
+ return { ...evidence, _provenance: record };
77
+ }
78
+
79
+ export { PROVENANCE_VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lateos/npm-scan",
3
- "version": "0.16.0",
3
+ "version": "0.16.4",
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": {