dependency-radar 0.7.0 → 0.8.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 +108 -7
- package/dist/aggregator.js +35 -9
- package/dist/cli.js +347 -39
- package/dist/compare.js +79 -0
- package/dist/failOn.js +16 -2
- package/dist/findings.js +166 -0
- package/dist/generated/spdx.js +3 -0
- package/dist/nodeEngine.js +181 -0
- package/dist/outputFormats.js +185 -0
- package/dist/report-assets.js +2 -2
- package/dist/report.js +137 -71
- package/dist/runners/importGraphRunner.js +9 -5
- package/dist/runners/lockfileGraph.js +144 -1
- package/dist/runners/lockfileSignals.js +303 -0
- package/dist/runners/npmLs.js +15 -0
- package/dist/schema.js +107 -0
- package/dist/utils.js +62 -3
- package/dist/why.js +69 -0
- package/dist/workspaceFilter.js +25 -0
- package/package.json +5 -4
- package/dist/runners/depcheckRunner.js +0 -23
- package/dist/runners/licenseChecker.js +0 -33
- package/dist/runners/madgeRunner.js +0 -29
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderSarif = renderSarif;
|
|
4
|
+
exports.renderCycloneDx = renderCycloneDx;
|
|
5
|
+
exports.renderSpdx = renderSpdx;
|
|
6
|
+
exports.defaultOutputName = defaultOutputName;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
function purl(dep) {
|
|
9
|
+
const encodedName = dep.package.name.startsWith('@')
|
|
10
|
+
? `%40${dep.package.name
|
|
11
|
+
.slice(1)
|
|
12
|
+
.split('/')
|
|
13
|
+
.map(encodeURIComponent)
|
|
14
|
+
.join('/')}`
|
|
15
|
+
: encodeURIComponent(dep.package.name);
|
|
16
|
+
return `pkg:npm/${encodedName}@${encodeURIComponent(dep.package.version)}`;
|
|
17
|
+
}
|
|
18
|
+
function findingLevel(finding) {
|
|
19
|
+
if (finding.severity === 'error')
|
|
20
|
+
return 'error';
|
|
21
|
+
if (finding.severity === 'warning')
|
|
22
|
+
return 'warning';
|
|
23
|
+
return 'note';
|
|
24
|
+
}
|
|
25
|
+
function renderSarif(data) {
|
|
26
|
+
const findings = data.findings || [];
|
|
27
|
+
const rules = new Map();
|
|
28
|
+
for (const finding of findings) {
|
|
29
|
+
if (rules.has(finding.category))
|
|
30
|
+
continue;
|
|
31
|
+
rules.set(finding.category, {
|
|
32
|
+
id: finding.category,
|
|
33
|
+
name: finding.category,
|
|
34
|
+
shortDescription: { text: `Dependency Radar ${finding.category} finding` },
|
|
35
|
+
helpUri: 'https://www.dependency-radar.com'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return JSON.stringify({
|
|
39
|
+
version: '2.1.0',
|
|
40
|
+
$schema: 'https://json.schemastore.org/sarif-2.1.0.json',
|
|
41
|
+
runs: [
|
|
42
|
+
{
|
|
43
|
+
tool: {
|
|
44
|
+
driver: {
|
|
45
|
+
name: 'Dependency Radar',
|
|
46
|
+
informationUri: 'https://www.dependency-radar.com',
|
|
47
|
+
semanticVersion: data.dependencyRadarVersion,
|
|
48
|
+
rules: Array.from(rules.values())
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
results: findings.map((finding) => ({
|
|
52
|
+
ruleId: finding.category,
|
|
53
|
+
level: findingLevel(finding),
|
|
54
|
+
message: { text: `${finding.title}: ${finding.message}` },
|
|
55
|
+
properties: {
|
|
56
|
+
dependencyRadarFindingId: finding.id,
|
|
57
|
+
packageId: finding.packageId,
|
|
58
|
+
packageName: finding.packageName,
|
|
59
|
+
packageVersion: finding.packageVersion,
|
|
60
|
+
recommendation: finding.recommendation,
|
|
61
|
+
evidence: finding.evidence
|
|
62
|
+
},
|
|
63
|
+
locations: [sarifLocation(finding)]
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}, null, 2);
|
|
68
|
+
}
|
|
69
|
+
function sarifLocation(finding) {
|
|
70
|
+
const extra = finding;
|
|
71
|
+
return {
|
|
72
|
+
physicalLocation: {
|
|
73
|
+
artifactLocation: { uri: extra.sourceFile || extra.sourcePath || 'package.json' },
|
|
74
|
+
region: { startLine: extra.startLine || 1 }
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function licenseIds(dep) {
|
|
79
|
+
const declared = dep.compliance.license.declared;
|
|
80
|
+
const inferred = dep.compliance.license.inferred;
|
|
81
|
+
if ((declared === null || declared === void 0 ? void 0 : declared.valid) && declared.spdxId)
|
|
82
|
+
return [{ license: { id: declared.spdxId } }];
|
|
83
|
+
if (inferred === null || inferred === void 0 ? void 0 : inferred.spdxId)
|
|
84
|
+
return [{ license: { id: inferred.spdxId } }];
|
|
85
|
+
return [{ license: { name: 'UNKNOWN' } }];
|
|
86
|
+
}
|
|
87
|
+
function renderCycloneDx(data) {
|
|
88
|
+
const dependencies = Object.values(data.dependencies || {});
|
|
89
|
+
return JSON.stringify({
|
|
90
|
+
bomFormat: 'CycloneDX',
|
|
91
|
+
specVersion: '1.5',
|
|
92
|
+
version: 1,
|
|
93
|
+
metadata: {
|
|
94
|
+
timestamp: data.generatedAt,
|
|
95
|
+
tools: [{ vendor: 'Dependency Radar', name: 'dependency-radar', version: data.dependencyRadarVersion }],
|
|
96
|
+
component: {
|
|
97
|
+
type: 'application',
|
|
98
|
+
name: data.project.name || data.project.projectDir,
|
|
99
|
+
version: data.project.version || '0.0.0'
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
components: dependencies.map((dep) => ({
|
|
103
|
+
type: 'library',
|
|
104
|
+
'bom-ref': dep.package.id,
|
|
105
|
+
name: dep.package.name,
|
|
106
|
+
version: dep.package.version,
|
|
107
|
+
purl: purl(dep),
|
|
108
|
+
licenses: licenseIds(dep),
|
|
109
|
+
externalReferences: [
|
|
110
|
+
{ type: 'distribution', url: dep.package.links.npm },
|
|
111
|
+
...(dep.package.links.repository ? [{ type: 'vcs', url: dep.package.links.repository }] : []),
|
|
112
|
+
...(dep.package.links.homepage ? [{ type: 'website', url: dep.package.links.homepage }] : [])
|
|
113
|
+
]
|
|
114
|
+
})),
|
|
115
|
+
dependencies: dependencies.map((dep) => ({
|
|
116
|
+
ref: dep.package.id,
|
|
117
|
+
dependsOn: subDependencyRefs(dep)
|
|
118
|
+
}))
|
|
119
|
+
}, null, 2);
|
|
120
|
+
}
|
|
121
|
+
function subDependencyRefs(dep) {
|
|
122
|
+
return Object.values(dep.graph.subDeps || {})
|
|
123
|
+
.flatMap((group) => Object.values(group || {}))
|
|
124
|
+
.filter((entry) => Array.isArray(entry) && entry.length >= 2 && (entry[1] === null || typeof entry[1] === 'string'))
|
|
125
|
+
.map((entry) => entry[1])
|
|
126
|
+
.filter((resolved) => Boolean(resolved));
|
|
127
|
+
}
|
|
128
|
+
function spdxNamespace(data) {
|
|
129
|
+
const stable = JSON.stringify({
|
|
130
|
+
name: data.project.name || 'dependency-radar',
|
|
131
|
+
version: data.project.version || '0.0.0',
|
|
132
|
+
generatedAt: data.generatedAt,
|
|
133
|
+
dependencies: Object.keys(data.dependencies || {}).sort()
|
|
134
|
+
});
|
|
135
|
+
return `https://www.dependency-radar.com/spdx/${(0, crypto_1.createHash)('sha256').update(stable).digest('hex').slice(0, 24)}`;
|
|
136
|
+
}
|
|
137
|
+
function renderSpdx(data) {
|
|
138
|
+
const dependencies = Object.values(data.dependencies || {});
|
|
139
|
+
const packages = dependencies.map((dep) => {
|
|
140
|
+
const declared = dep.compliance.license.declared;
|
|
141
|
+
const inferred = dep.compliance.license.inferred;
|
|
142
|
+
const license = (declared === null || declared === void 0 ? void 0 : declared.valid) && declared.spdxId
|
|
143
|
+
? declared.spdxId
|
|
144
|
+
: (inferred === null || inferred === void 0 ? void 0 : inferred.spdxId) || 'NOASSERTION';
|
|
145
|
+
return {
|
|
146
|
+
SPDXID: `SPDXRef-Package-${dep.package.id.replace(/[^A-Za-z0-9.-]/g, '-')}`,
|
|
147
|
+
name: dep.package.name,
|
|
148
|
+
versionInfo: dep.package.version,
|
|
149
|
+
downloadLocation: dep.package.links.npm,
|
|
150
|
+
filesAnalyzed: false,
|
|
151
|
+
licenseConcluded: license,
|
|
152
|
+
licenseDeclared: license,
|
|
153
|
+
externalRefs: [
|
|
154
|
+
{
|
|
155
|
+
referenceCategory: 'PACKAGE-MANAGER',
|
|
156
|
+
referenceType: 'purl',
|
|
157
|
+
referenceLocator: purl(dep)
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
return JSON.stringify({
|
|
163
|
+
spdxVersion: 'SPDX-2.3',
|
|
164
|
+
dataLicense: 'CC0-1.0',
|
|
165
|
+
SPDXID: 'SPDXRef-DOCUMENT',
|
|
166
|
+
name: `${data.project.name || 'dependency-radar'} dependency report`,
|
|
167
|
+
documentNamespace: spdxNamespace(data),
|
|
168
|
+
creationInfo: {
|
|
169
|
+
created: data.generatedAt,
|
|
170
|
+
creators: [`Tool: dependency-radar-${data.dependencyRadarVersion}`]
|
|
171
|
+
},
|
|
172
|
+
packages
|
|
173
|
+
}, null, 2);
|
|
174
|
+
}
|
|
175
|
+
function defaultOutputName(format) {
|
|
176
|
+
if (format === 'html')
|
|
177
|
+
return 'dependency-radar.html';
|
|
178
|
+
if (format === 'json')
|
|
179
|
+
return 'dependency-radar.json';
|
|
180
|
+
if (format === 'sarif')
|
|
181
|
+
return 'dependency-radar.sarif';
|
|
182
|
+
if (format === 'cyclonedx')
|
|
183
|
+
return 'dependency-radar.cdx.json';
|
|
184
|
+
return 'dependency-radar.spdx.json';
|
|
185
|
+
}
|