@lateos/npm-scan 0.7.3 → 0.7.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.
- package/README.md +2 -2
- package/backend/siem/ecs.js +41 -0
- package/backend/siem/index.js +10 -1
- package/backend/siem/qradar.js +57 -0
- package/backend/siem/sentinel.js +28 -0
- package/cli/cli.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npx @lateos/npm-scan scan lodash
|
|
|
21
21
|
- **SBOM Output** — CycloneDX 1.5 and SPDX 2.3 with findings mapped as vulnerabilities
|
|
22
22
|
- **NIST 800-161 Compliance** — HTML report includes control traceability matrix (SR-2.1 → SR-11.4)
|
|
23
23
|
- **EU CRA Compliance** — report maps findings to Cyber Resilience Act articles and Annex I requirements
|
|
24
|
-
- **SIEM Export** — CEF
|
|
24
|
+
- **SIEM Export** — Splunk CEF, Elastic ECS, Microsoft Sentinel, IBM QRadar formats (premium)
|
|
25
25
|
- **EU CRA Compliance** — report maps findings to Cyber Resilience Act articles (premium)
|
|
26
26
|
- **License Key Gating** — premium features locked behind signed license keys
|
|
27
27
|
- **REST API** — FastAPI-based API with webhooks, auth, scan management (premium)
|
|
@@ -47,7 +47,7 @@ npm-scan report -i <id> --sbom spdx Generate SPDX SBOM
|
|
|
47
47
|
npm-scan report -i <id> --html Generate HTML report (with NIST table)
|
|
48
48
|
npm-scan report -i <id> --nist Print NIST 800-161 compliance table
|
|
49
49
|
npm-scan report -i <id> --cra Print EU CRA compliance table
|
|
50
|
-
npm-scan report -i <id> --siem
|
|
50
|
+
npm-scan report -i <id> --siem <fmt> Generate SIEM output (cef|ecs|sentinel|qradar) (premium)
|
|
51
51
|
npm-scan report --html Generate HTML report for all scans
|
|
52
52
|
npm-scan report --nist Print NIST compliance for all scans
|
|
53
53
|
npm-scan report --cra Print EU CRA compliance for all scans (premium)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function generateECS(scans) {
|
|
2
|
+
const events = [];
|
|
3
|
+
for (const s of scans) {
|
|
4
|
+
for (const f of (s.findings || [])) {
|
|
5
|
+
const atkId = f.atk_id || f.id;
|
|
6
|
+
const sevMap = { critical: 100, high: 80, medium: 50, low: 20 };
|
|
7
|
+
events.push({
|
|
8
|
+
'@timestamp': new Date().toISOString(),
|
|
9
|
+
event: {
|
|
10
|
+
kind: 'alert',
|
|
11
|
+
category: 'threat',
|
|
12
|
+
type: ['indicator', 'threat'],
|
|
13
|
+
action: 'npm-scan-detected',
|
|
14
|
+
severity: sevMap[f.severity] || 50,
|
|
15
|
+
},
|
|
16
|
+
message: `[${atkId}] ${f.severity.toUpperCase()}: ${f.description || f.title || 'Unknown finding'}`,
|
|
17
|
+
log: { level: f.severity },
|
|
18
|
+
observer: {
|
|
19
|
+
vendor: 'Lateos',
|
|
20
|
+
product: 'npm-scan',
|
|
21
|
+
version: process.env.npm_package_version || '0.7.0',
|
|
22
|
+
},
|
|
23
|
+
labels: {
|
|
24
|
+
package: s.package_name || 'unknown',
|
|
25
|
+
version: s.version || 'unknown',
|
|
26
|
+
atk_id: atkId,
|
|
27
|
+
severity: f.severity,
|
|
28
|
+
},
|
|
29
|
+
vulnerability: {
|
|
30
|
+
classification: 'npm-supply-chain',
|
|
31
|
+
reference: `https://npm-scan.io/atk/${atkId}`,
|
|
32
|
+
id: atkId,
|
|
33
|
+
description: f.description || f.title || null,
|
|
34
|
+
enumeration: 'ATK',
|
|
35
|
+
},
|
|
36
|
+
file: f.evidence ? { name: f.evidence } : undefined,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return events.map(e => JSON.stringify(e)).join('\n');
|
|
41
|
+
}
|
package/backend/siem/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { generateCEF } from './cef.js';
|
|
2
|
+
import { generateECS } from './ecs.js';
|
|
3
|
+
import { generateSentinel } from './sentinel.js';
|
|
4
|
+
import { generateQRadar } from './qradar.js';
|
|
2
5
|
|
|
3
6
|
export function generateSIEM(scans, format = 'cef') {
|
|
4
7
|
switch (format) {
|
|
5
8
|
case 'cef':
|
|
6
9
|
return generateCEF(scans);
|
|
10
|
+
case 'ecs':
|
|
11
|
+
return generateECS(scans);
|
|
12
|
+
case 'sentinel':
|
|
13
|
+
return generateSentinel(scans);
|
|
14
|
+
case 'qradar':
|
|
15
|
+
return generateQRadar(scans);
|
|
7
16
|
default:
|
|
8
|
-
throw new Error(`Unknown SIEM format: ${format}`);
|
|
17
|
+
throw new Error(`Unknown SIEM format: ${format}. Supported: cef, ecs, sentinel, qradar`);
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export function generateQRadar(scans) {
|
|
2
|
+
const events = [];
|
|
3
|
+
for (const s of scans) {
|
|
4
|
+
for (const f of (s.findings || [])) {
|
|
5
|
+
const atkId = f.atk_id || f.id;
|
|
6
|
+
events.push({
|
|
7
|
+
source: 'npm-scan',
|
|
8
|
+
version: process.env.npm_package_version || '0.7.0',
|
|
9
|
+
devicetime: new Date().toISOString(),
|
|
10
|
+
devicepayload: [
|
|
11
|
+
s.package_name || 'unknown',
|
|
12
|
+
s.version || 'unknown',
|
|
13
|
+
atkId,
|
|
14
|
+
f.severity,
|
|
15
|
+
f.title || f.description || '',
|
|
16
|
+
f.evidence || '',
|
|
17
|
+
].join('\t'),
|
|
18
|
+
devicevendor: 'Lateos',
|
|
19
|
+
devicename: 'npm-scan',
|
|
20
|
+
deviceproduct: 'npm-scan',
|
|
21
|
+
atk_id: atkId,
|
|
22
|
+
severity: f.severity,
|
|
23
|
+
package_name: s.package_name || 'unknown',
|
|
24
|
+
package_version: s.version || 'unknown',
|
|
25
|
+
finding_title: f.title || f.description || '',
|
|
26
|
+
finding_description: f.description || f.title || '',
|
|
27
|
+
evidence: f.evidence || '',
|
|
28
|
+
mitigation: f.mitigation || '',
|
|
29
|
+
raw_category: 'NPM Supply Chain Threat',
|
|
30
|
+
qid: _qrQid(f.severity),
|
|
31
|
+
category: _qrCategory(f.severity),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return events.map(e => JSON.stringify(e)).join('\n');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const QID_MAP = {
|
|
39
|
+
critical: 90050001,
|
|
40
|
+
high: 90050002,
|
|
41
|
+
medium: 90050003,
|
|
42
|
+
low: 90050004,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function _qrQid(severity) {
|
|
46
|
+
return QID_MAP[severity] || 90050003;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function _qrCategory(severity) {
|
|
50
|
+
const map = {
|
|
51
|
+
critical: 'Critical Severity Malware',
|
|
52
|
+
high: 'High Severity Malware',
|
|
53
|
+
medium: 'Medium Severity Malware',
|
|
54
|
+
low: 'Low Severity Malware',
|
|
55
|
+
};
|
|
56
|
+
return map[severity] || 'Medium Severity Malware';
|
|
57
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function generateSentinel(scans) {
|
|
2
|
+
const events = [];
|
|
3
|
+
for (const s of scans) {
|
|
4
|
+
for (const f of (s.findings || [])) {
|
|
5
|
+
const atkId = f.atk_id || f.id;
|
|
6
|
+
events.push({
|
|
7
|
+
TimeGenerated: new Date().toISOString(),
|
|
8
|
+
Computer: process.env.COMPUTERNAME || process.env.HOSTNAME || 'npm-scan-host',
|
|
9
|
+
SourceSystem: 'npm-scan',
|
|
10
|
+
DeviceVendor: 'Lateos',
|
|
11
|
+
DeviceProduct: 'npm-scan',
|
|
12
|
+
DeviceVersion: process.env.npm_package_version || '0.7.0',
|
|
13
|
+
SeverityLevel: f.severity,
|
|
14
|
+
Severity: f.severity.toUpperCase(),
|
|
15
|
+
EventType: 'npm-supply-chain-threat',
|
|
16
|
+
ATKId: atkId,
|
|
17
|
+
FindingTitle: f.title || f.description || '',
|
|
18
|
+
FindingDescription: f.description || f.title || '',
|
|
19
|
+
Evidence: f.evidence || '',
|
|
20
|
+
PackageName: s.package_name || 'unknown',
|
|
21
|
+
PackageVersion: s.version || 'unknown',
|
|
22
|
+
Mitigation: f.mitigation || '',
|
|
23
|
+
ThreatClassification: 'npm-supply-chain',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return JSON.stringify(events, null, 2);
|
|
28
|
+
}
|
package/cli/cli.js
CHANGED
|
@@ -60,7 +60,7 @@ program
|
|
|
60
60
|
.option('--html', 'HTML report')
|
|
61
61
|
.option('--nist', 'NIST 800-161 compliance report')
|
|
62
62
|
.option('--cra', 'EU CRA compliance report')
|
|
63
|
-
.option('--siem <format>', 'SIEM format (cef)')
|
|
63
|
+
.option('--siem <format>', 'SIEM format (cef|ecs|sentinel|qradar)')
|
|
64
64
|
.option('-l, --license-key <key>', 'Premium license')
|
|
65
65
|
.action(async (options) => {
|
|
66
66
|
const licenseKey = options.licenseKey || process.env.NPM_SCAN_LICENSE_KEY;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lateos/npm-scan",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Powerful npm supply chain security scanner - detects malicious packages (Shai-Hulud style), behavioral analysis, SBOM, and compliance reporting.",
|
|
5
5
|
"main": "backend/index.js",
|
|
6
6
|
"bin": {
|