@pnpm/deps.compliance.commands 1000.0.0 → 1101.0.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/lib/audit/audit.d.ts +3 -2
- package/lib/audit/audit.js +37 -34
- package/lib/audit/fix.d.ts +7 -2
- package/lib/audit/fix.js +39 -13
- package/lib/audit/fixWithUpdate.d.ts +1 -0
- package/lib/audit/fixWithUpdate.js +18 -2
- package/lib/audit/ignore.d.ts +1 -1
- package/lib/audit/ignore.js +26 -13
- package/lib/licenses/licensesList.d.ts +2 -2
- package/lib/sbom/sbom.d.ts +2 -2
- package/package.json +34 -32
package/lib/audit/audit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Config, type UniversalOptions } from '@pnpm/config.reader';
|
|
1
|
+
import { type Config, type ConfigContext, type UniversalOptions } from '@pnpm/config.reader';
|
|
2
2
|
import { type AuditReport } from '@pnpm/deps.compliance.audit';
|
|
3
3
|
import { type InstallCommandOptions } from '@pnpm/installing.commands';
|
|
4
4
|
import type { Registries } from '@pnpm/types';
|
|
@@ -7,6 +7,7 @@ export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
|
7
7
|
export declare function cliOptionsTypes(): Record<string, unknown>;
|
|
8
8
|
export declare const shorthands: Record<string, string>;
|
|
9
9
|
export declare const commandNames: string[];
|
|
10
|
+
export declare const recursiveByDefault = true;
|
|
10
11
|
export declare function help(): string;
|
|
11
12
|
export type AuditOptions = Pick<UniversalOptions, 'dir'> & {
|
|
12
13
|
fix?: boolean | 'override' | 'update';
|
|
@@ -16,7 +17,7 @@ export type AuditOptions = Pick<UniversalOptions, 'dir'> & {
|
|
|
16
17
|
registries: Registries;
|
|
17
18
|
ignore?: string[];
|
|
18
19
|
ignoreUnfixable?: boolean;
|
|
19
|
-
} & Pick<Config, 'auditConfig' | 'auditLevel' | 'ca' | 'cert' | 'httpProxy' | 'httpsProxy' | 'key' | 'localAddress' | 'maxSockets' | 'noProxy' | 'strictSsl' | 'fetchRetries' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'fetchRetryFactor' | 'fetchTimeout' | 'production' | 'dev' | 'overrides' | 'optional' | '
|
|
20
|
+
} & Pick<Config, 'auditConfig' | 'auditLevel' | 'minimumReleaseAge' | 'ca' | 'cert' | 'httpProxy' | 'httpsProxy' | 'key' | 'localAddress' | 'maxSockets' | 'noProxy' | 'strictSsl' | 'fetchRetries' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'fetchRetryFactor' | 'fetchTimeout' | 'production' | 'dev' | 'overrides' | 'optional' | 'configByUri' | 'virtualStoreDirMaxLength' | 'workspaceDir'> & Pick<ConfigContext, 'rootProjectManifest' | 'rootProjectManifestDir'> & InstallCommandOptions;
|
|
20
21
|
export declare function handler(opts: AuditOptions): Promise<{
|
|
21
22
|
exitCode: number;
|
|
22
23
|
output: string;
|
package/lib/audit/audit.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import { docsUrl, TABLE_OPTIONS } from '@pnpm/cli.utils';
|
|
2
2
|
import { types as allTypes } from '@pnpm/config.reader';
|
|
3
3
|
import { WANTED_LOCKFILE } from '@pnpm/constants';
|
|
4
|
-
import { audit } from '@pnpm/deps.compliance.audit';
|
|
4
|
+
import { audit, normalizeGhsaId } from '@pnpm/deps.compliance.audit';
|
|
5
5
|
import { PnpmError } from '@pnpm/error';
|
|
6
6
|
import { update } from '@pnpm/installing.commands';
|
|
7
7
|
import { readEnvLockfile, readWantedLockfile } from '@pnpm/lockfile.fs';
|
|
8
8
|
import { createGetAuthHeaderByURI } from '@pnpm/network.auth-header';
|
|
9
9
|
import { table } from '@zkochan/table';
|
|
10
10
|
import chalk, {} from 'chalk';
|
|
11
|
-
import {
|
|
11
|
+
import { pick, pickBy } from 'ramda';
|
|
12
12
|
import { renderHelp } from 'render-help';
|
|
13
13
|
import { fix } from './fix.js';
|
|
14
14
|
import { fixWithUpdate } from './fixWithUpdate.js';
|
|
15
15
|
import { ignore } from './ignore.js';
|
|
16
16
|
const AUDIT_LEVEL_NUMBER = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
info: 0,
|
|
18
|
+
low: 1,
|
|
19
|
+
moderate: 2,
|
|
20
|
+
high: 3,
|
|
21
|
+
critical: 4,
|
|
21
22
|
};
|
|
22
23
|
const AUDIT_COLOR = {
|
|
24
|
+
info: chalk.dim,
|
|
23
25
|
low: chalk.bold,
|
|
24
26
|
moderate: chalk.bold.yellow,
|
|
25
27
|
high: chalk.bold.red,
|
|
@@ -46,7 +48,7 @@ export function rcOptionsTypes() {
|
|
|
46
48
|
'production',
|
|
47
49
|
'registry',
|
|
48
50
|
], allTypes),
|
|
49
|
-
'audit-level': ['low', 'moderate', 'high', 'critical'],
|
|
51
|
+
'audit-level': ['info', 'low', 'moderate', 'high', 'critical'],
|
|
50
52
|
// For fix, use String instead of a list of allowed string values.
|
|
51
53
|
// Otherwise, an unexpected value will get coerced to true because of the Boolean type.
|
|
52
54
|
fix: [String, Boolean],
|
|
@@ -69,6 +71,7 @@ export const shorthands = {
|
|
|
69
71
|
P: '--production',
|
|
70
72
|
};
|
|
71
73
|
export const commandNames = ['audit'];
|
|
74
|
+
export const recursiveByDefault = true;
|
|
72
75
|
export function help() {
|
|
73
76
|
return renderHelp({
|
|
74
77
|
description: 'Checks for known security issues with the installed packages.',
|
|
@@ -85,7 +88,7 @@ export function help() {
|
|
|
85
88
|
name: '--json',
|
|
86
89
|
},
|
|
87
90
|
{
|
|
88
|
-
description: 'Only print advisories with severity greater than or equal to one of the following: low|moderate|high|critical. Default: low',
|
|
91
|
+
description: 'Only print advisories with severity greater than or equal to one of the following: info|low|moderate|high|critical. Default: low',
|
|
89
92
|
name: '--audit-level <severity>',
|
|
90
93
|
},
|
|
91
94
|
{
|
|
@@ -107,11 +110,11 @@ export function help() {
|
|
|
107
110
|
name: '--ignore-registry-errors',
|
|
108
111
|
},
|
|
109
112
|
{
|
|
110
|
-
description: 'Ignore a vulnerability by
|
|
113
|
+
description: 'Ignore a vulnerability by its GitHub advisory ID (e.g. GHSA-xxxx-xxxx-xxxx)',
|
|
111
114
|
name: '--ignore <vulnerability>',
|
|
112
115
|
},
|
|
113
116
|
{
|
|
114
|
-
description: 'Ignore all
|
|
117
|
+
description: 'Ignore all vulnerabilities for which no fix exists',
|
|
115
118
|
name: '--ignore-unfixable',
|
|
116
119
|
},
|
|
117
120
|
],
|
|
@@ -135,10 +138,10 @@ export async function handler(opts) {
|
|
|
135
138
|
optionalDependencies: opts.optional !== false,
|
|
136
139
|
};
|
|
137
140
|
let auditReport;
|
|
138
|
-
const getAuthHeader = createGetAuthHeaderByURI(
|
|
141
|
+
const getAuthHeader = createGetAuthHeaderByURI(opts.configByUri, opts.registries?.default);
|
|
139
142
|
try {
|
|
140
143
|
auditReport = await audit(lockfile, getAuthHeader, {
|
|
141
|
-
|
|
144
|
+
dispatcherOptions: {
|
|
142
145
|
ca: opts.ca,
|
|
143
146
|
cert: opts.cert,
|
|
144
147
|
httpProxy: opts.httpProxy,
|
|
@@ -152,7 +155,6 @@ export async function handler(opts) {
|
|
|
152
155
|
},
|
|
153
156
|
envLockfile,
|
|
154
157
|
include,
|
|
155
|
-
lockfileDir,
|
|
156
158
|
registry: opts.registries.default,
|
|
157
159
|
retry: {
|
|
158
160
|
factor: opts.fetchRetryFactor,
|
|
@@ -161,7 +163,6 @@ export async function handler(opts) {
|
|
|
161
163
|
retries: opts.fetchRetries,
|
|
162
164
|
},
|
|
163
165
|
timeout: opts.fetchTimeout,
|
|
164
|
-
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
|
165
166
|
});
|
|
166
167
|
}
|
|
167
168
|
catch (err) { // eslint-disable-line
|
|
@@ -188,26 +189,34 @@ export async function handler(opts) {
|
|
|
188
189
|
}
|
|
189
190
|
if (fixMethod === 'update') {
|
|
190
191
|
const result = await fixWithUpdate(auditReport, { ...opts, include });
|
|
192
|
+
let output = formatFixWithUpdateOutput(result, auditReport);
|
|
193
|
+
if (result.addedAgeExcludes.length > 0) {
|
|
194
|
+
output += `\n${result.addedAgeExcludes.length} entries were added to minimumReleaseAgeExclude to allow installing the patched versions:\n${result.addedAgeExcludes.join('\n')}\n`;
|
|
195
|
+
}
|
|
191
196
|
return {
|
|
192
197
|
exitCode: result.remaining.length > 0 ? 1 : 0,
|
|
193
|
-
output
|
|
198
|
+
output,
|
|
194
199
|
};
|
|
195
200
|
}
|
|
196
201
|
if (fixMethod === 'override') {
|
|
197
|
-
const
|
|
198
|
-
if (Object.values(
|
|
202
|
+
const { vulnOverrides, addedAgeExcludes } = await fix(auditReport, opts);
|
|
203
|
+
if (Object.values(vulnOverrides).length === 0) {
|
|
199
204
|
return {
|
|
200
205
|
exitCode: 0,
|
|
201
206
|
output: 'No fixes were made',
|
|
202
207
|
};
|
|
203
208
|
}
|
|
204
|
-
|
|
205
|
-
exitCode: 0,
|
|
206
|
-
output: `${Object.values(newOverrides).length} overrides were added to package.json to fix vulnerabilities.
|
|
209
|
+
let output = `${Object.values(vulnOverrides).length} overrides were added to pnpm-workspace.yaml to fix vulnerabilities.
|
|
207
210
|
Run "pnpm install" to apply the fixes.
|
|
208
211
|
|
|
209
212
|
The added overrides:
|
|
210
|
-
${JSON.stringify(
|
|
213
|
+
${JSON.stringify(vulnOverrides, null, 2)}`;
|
|
214
|
+
if (addedAgeExcludes.length > 0) {
|
|
215
|
+
output += `\n\n${addedAgeExcludes.length} entries were added to minimumReleaseAgeExclude to allow installing the patched versions:\n${addedAgeExcludes.join('\n')}`;
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
exitCode: 0,
|
|
219
|
+
output,
|
|
211
220
|
};
|
|
212
221
|
}
|
|
213
222
|
if (opts.ignore !== undefined || opts.ignoreUnfixable) {
|
|
@@ -235,6 +244,7 @@ ${newIgnores.join('\n')}`,
|
|
|
235
244
|
}
|
|
236
245
|
const vulnerabilities = auditReport.metadata.vulnerabilities;
|
|
237
246
|
const ignoredVulnerabilities = {
|
|
247
|
+
info: 0,
|
|
238
248
|
low: 0,
|
|
239
249
|
moderate: 0,
|
|
240
250
|
high: 0,
|
|
@@ -243,19 +253,12 @@ ${newIgnores.join('\n')}`,
|
|
|
243
253
|
const totalVulnerabilityCount = Object.values(vulnerabilities)
|
|
244
254
|
.reduce((sum, vulnerabilitiesCount) => sum + vulnerabilitiesCount, 0);
|
|
245
255
|
const ignoreGhsas = opts.auditConfig?.ignoreGhsas;
|
|
246
|
-
if (ignoreGhsas) {
|
|
256
|
+
if (ignoreGhsas?.length) {
|
|
257
|
+
// Compare GHSA ids after normalizing so stored entries with varying
|
|
258
|
+
// casing still match the canonical form on the advisory.
|
|
259
|
+
const ignoreSet = new Set(ignoreGhsas.map(normalizeGhsaId));
|
|
247
260
|
auditReport.advisories = pickBy(({ github_advisory_id: githubAdvisoryId, severity }) => {
|
|
248
|
-
if (!
|
|
249
|
-
return true;
|
|
250
|
-
}
|
|
251
|
-
ignoredVulnerabilities[severity] += 1;
|
|
252
|
-
return false;
|
|
253
|
-
}, auditReport.advisories);
|
|
254
|
-
}
|
|
255
|
-
const ignoreCves = opts.auditConfig?.ignoreCves;
|
|
256
|
-
if (ignoreCves) {
|
|
257
|
-
auditReport.advisories = pickBy(({ cves, severity }) => {
|
|
258
|
-
if (cves.length === 0 || difference(cves, ignoreCves).length > 0) {
|
|
261
|
+
if (!ignoreSet.has(normalizeGhsaId(githubAdvisoryId))) {
|
|
259
262
|
return true;
|
|
260
263
|
}
|
|
261
264
|
ignoredVulnerabilities[severity] += 1;
|
|
@@ -280,7 +283,7 @@ ${newIgnores.join('\n')}`,
|
|
|
280
283
|
[AUDIT_COLOR[advisory.severity](advisory.severity), chalk.bold(advisory.title)],
|
|
281
284
|
['Package', advisory.module_name],
|
|
282
285
|
['Vulnerable versions', advisory.vulnerable_versions],
|
|
283
|
-
['Patched versions', advisory.patched_versions],
|
|
286
|
+
['Patched versions', advisory.patched_versions ?? '(unknown)'],
|
|
284
287
|
[
|
|
285
288
|
'Paths',
|
|
286
289
|
(paths.length > MAX_PATHS_COUNT
|
package/lib/audit/fix.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AuditAdvisory, type AuditReport } from '@pnpm/deps.compliance.audit';
|
|
2
2
|
import type { AuditOptions } from './audit.js';
|
|
3
|
-
export
|
|
3
|
+
export interface FixResult {
|
|
4
|
+
vulnOverrides: Record<string, string>;
|
|
5
|
+
addedAgeExcludes: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function fix(auditReport: AuditReport, opts: AuditOptions): Promise<FixResult>;
|
|
8
|
+
export declare function createMinimumReleaseAgeExcludes(advisories: AuditAdvisory[]): string[];
|
package/lib/audit/fix.js
CHANGED
|
@@ -1,26 +1,52 @@
|
|
|
1
1
|
import { writeSettings } from '@pnpm/config.writer';
|
|
2
|
-
import {
|
|
2
|
+
import { normalizeGhsaId } from '@pnpm/deps.compliance.audit';
|
|
3
|
+
import semver from 'semver';
|
|
3
4
|
export async function fix(auditReport, opts) {
|
|
4
|
-
const
|
|
5
|
+
const fixableAdvisories = getFixableAdvisories(Object.values(auditReport.advisories), opts.auditConfig?.ignoreGhsas);
|
|
6
|
+
const vulnOverrides = createOverrides(fixableAdvisories);
|
|
5
7
|
if (Object.values(vulnOverrides).length === 0)
|
|
6
|
-
return vulnOverrides;
|
|
8
|
+
return { vulnOverrides, addedAgeExcludes: [] };
|
|
9
|
+
const addedAgeExcludes = opts.minimumReleaseAge ? createMinimumReleaseAgeExcludes(fixableAdvisories) : [];
|
|
7
10
|
await writeSettings({
|
|
8
11
|
updatedOverrides: vulnOverrides,
|
|
12
|
+
addedMinimumReleaseAgeExcludes: addedAgeExcludes.length > 0 ? addedAgeExcludes : undefined,
|
|
9
13
|
rootProjectManifest: opts.rootProjectManifest,
|
|
10
14
|
rootProjectManifestDir: opts.rootProjectManifestDir,
|
|
11
15
|
workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir,
|
|
12
16
|
});
|
|
13
|
-
return vulnOverrides;
|
|
17
|
+
return { vulnOverrides, addedAgeExcludes };
|
|
14
18
|
}
|
|
15
|
-
function
|
|
16
|
-
if (
|
|
17
|
-
|
|
19
|
+
function getFixableAdvisories(advisories, ignoreGhsas) {
|
|
20
|
+
if (ignoreGhsas) {
|
|
21
|
+
// Normalize on both sides so ignore entries match regardless of casing.
|
|
22
|
+
const ignored = new Set(ignoreGhsas.map(normalizeGhsaId));
|
|
23
|
+
advisories = advisories.filter(({ github_advisory_id: ghsaId }) => !ghsaId || !ignored.has(normalizeGhsaId(ghsaId)));
|
|
18
24
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
// Only advisories with a known patched range can produce an override.
|
|
26
|
+
// patched_versions is undefined when the range couldn't be inferred from
|
|
27
|
+
// vulnerable_versions — no override is possible in that case.
|
|
28
|
+
return advisories.filter(({ patched_versions: patchedVersions }) => patchedVersions != null);
|
|
29
|
+
}
|
|
30
|
+
function createOverrides(advisories) {
|
|
31
|
+
const entries = [];
|
|
32
|
+
for (const advisory of advisories) {
|
|
33
|
+
if (!advisory.patched_versions)
|
|
34
|
+
continue;
|
|
35
|
+
entries.push([`${advisory.module_name}@${advisory.vulnerable_versions}`, advisory.patched_versions]);
|
|
36
|
+
}
|
|
37
|
+
return Object.fromEntries(entries);
|
|
38
|
+
}
|
|
39
|
+
export function createMinimumReleaseAgeExcludes(advisories) {
|
|
40
|
+
const excludes = new Set();
|
|
41
|
+
for (const advisory of advisories) {
|
|
42
|
+
const patchedVersions = advisory.patched_versions;
|
|
43
|
+
if (!patchedVersions)
|
|
44
|
+
continue;
|
|
45
|
+
const minVersion = semver.minVersion(patchedVersions);
|
|
46
|
+
if (minVersion) {
|
|
47
|
+
excludes.add(`${advisory.module_name}@${minVersion.version}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return Array.from(excludes);
|
|
25
51
|
}
|
|
26
52
|
//# sourceMappingURL=fix.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { writeSettings } from '@pnpm/config.writer';
|
|
1
2
|
import { WANTED_LOCKFILE } from '@pnpm/constants';
|
|
2
3
|
import { PnpmError } from '@pnpm/error';
|
|
3
4
|
import { update } from '@pnpm/installing.commands';
|
|
4
5
|
import { readWantedLockfile } from '@pnpm/lockfile.fs';
|
|
5
6
|
import semver from 'semver';
|
|
7
|
+
import { createMinimumReleaseAgeExcludes } from './fix.js';
|
|
6
8
|
import { lockfileToPackages } from './lockfileToPackages.js';
|
|
7
9
|
export async function fixWithUpdate(auditReport, opts) {
|
|
8
10
|
const vulnerabilitiesByPackage = new Map();
|
|
@@ -58,8 +60,22 @@ export async function fixWithUpdate(auditReport, opts) {
|
|
|
58
60
|
return allVulnerabilities;
|
|
59
61
|
},
|
|
60
62
|
};
|
|
63
|
+
// Add minimum patched versions to minimumReleaseAgeExclude so the resolver
|
|
64
|
+
// can install them even when minimumReleaseAge would otherwise block them.
|
|
65
|
+
const addedAgeExcludes = opts.minimumReleaseAge ? createMinimumReleaseAgeExcludes(Object.values(auditReport.advisories)) : [];
|
|
66
|
+
const updateOpts = { ...opts };
|
|
67
|
+
if (addedAgeExcludes.length > 0) {
|
|
68
|
+
const existing = updateOpts.minimumReleaseAgeExclude ?? [];
|
|
69
|
+
updateOpts.minimumReleaseAgeExclude = [...existing, ...addedAgeExcludes];
|
|
70
|
+
await writeSettings({
|
|
71
|
+
addedMinimumReleaseAgeExcludes: addedAgeExcludes,
|
|
72
|
+
rootProjectManifest: opts.rootProjectManifest,
|
|
73
|
+
rootProjectManifestDir: opts.rootProjectManifestDir,
|
|
74
|
+
workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
61
77
|
await update.handler({
|
|
62
|
-
...
|
|
78
|
+
...updateOpts,
|
|
63
79
|
packageVulnerabilityAudit,
|
|
64
80
|
}, []);
|
|
65
81
|
const lockfileDir = opts.lockfileDir ?? opts.dir;
|
|
@@ -105,6 +121,6 @@ export async function fixWithUpdate(auditReport, opts) {
|
|
|
105
121
|
fixed.push(...unfixableIds);
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
|
-
return { fixed, remaining };
|
|
124
|
+
return { fixed, remaining, addedAgeExcludes };
|
|
109
125
|
}
|
|
110
126
|
//# sourceMappingURL=fixWithUpdate.js.map
|
package/lib/audit/ignore.d.ts
CHANGED
package/lib/audit/ignore.js
CHANGED
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
import { writeSettings } from '@pnpm/config.writer';
|
|
2
|
+
import { normalizeGhsaId } from '@pnpm/deps.compliance.audit';
|
|
3
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
4
|
import { difference } from 'ramda';
|
|
3
5
|
export async function ignore(opts) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
// GHSA IDs are canonically uppercase; normalize on read/write so a stored
|
|
7
|
+
// "ghsa-..." or uppercase user input both match the derived id at filter
|
|
8
|
+
// time.
|
|
9
|
+
const currentGhsas = (opts?.auditConfig?.ignoreGhsas ?? []).map(normalizeGhsaId);
|
|
10
|
+
const currentUniqueGhsas = new Set(currentGhsas);
|
|
11
|
+
const advisoriesWithNoResolutions = filterAdvisoriesWithNoResolutions(Object.values(opts.auditReport.advisories));
|
|
7
12
|
if (opts.ignoreUnfixable) {
|
|
8
|
-
|
|
9
|
-
advisory.
|
|
10
|
-
|
|
13
|
+
for (const advisory of advisoriesWithNoResolutions) {
|
|
14
|
+
if (!advisory.github_advisory_id) {
|
|
15
|
+
throw new PnpmError('AUDIT_MISSING_GHSA', `Cannot ignore advisory ${advisory.id} (${advisory.module_name}): the registry did not provide a GHSA id or a resolvable url.`);
|
|
16
|
+
}
|
|
17
|
+
currentUniqueGhsas.add(normalizeGhsaId(advisory.github_advisory_id));
|
|
18
|
+
}
|
|
11
19
|
}
|
|
12
|
-
else {
|
|
13
|
-
opts.ignore
|
|
20
|
+
else if (opts.ignore) {
|
|
21
|
+
for (const ghsa of opts.ignore) {
|
|
22
|
+
currentUniqueGhsas.add(normalizeGhsaId(ghsa));
|
|
23
|
+
}
|
|
14
24
|
}
|
|
15
|
-
const
|
|
16
|
-
const
|
|
25
|
+
const newIgnoreGhsas = currentUniqueGhsas.size > 0 ? Array.from(currentUniqueGhsas) : undefined;
|
|
26
|
+
const diffGhsas = difference(newIgnoreGhsas ?? [], currentGhsas);
|
|
17
27
|
await writeSettings({
|
|
18
28
|
...opts,
|
|
19
29
|
updatedSettings: {
|
|
20
30
|
auditConfig: {
|
|
21
31
|
...opts.auditConfig,
|
|
22
|
-
|
|
32
|
+
ignoreGhsas: newIgnoreGhsas,
|
|
23
33
|
},
|
|
24
34
|
},
|
|
25
35
|
});
|
|
26
|
-
return [...
|
|
36
|
+
return [...diffGhsas];
|
|
27
37
|
}
|
|
38
|
+
// Advisories for which no override can be produced — patched_versions is
|
|
39
|
+
// undefined when pnpm couldn't infer a patched range from vulnerable_versions.
|
|
40
|
+
// That is the only "no fix available" signal the bulk endpoint provides.
|
|
28
41
|
function filterAdvisoriesWithNoResolutions(advisories) {
|
|
29
|
-
return advisories.filter(({ patched_versions: patchedVersions }) => patchedVersions
|
|
42
|
+
return advisories.filter(({ patched_versions: patchedVersions }) => patchedVersions == null);
|
|
30
43
|
}
|
|
31
44
|
//# sourceMappingURL=ignore.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Config } from '@pnpm/config.reader';
|
|
1
|
+
import type { Config, ConfigContext } from '@pnpm/config.reader';
|
|
2
2
|
import type { LicensesCommandResult } from './LicensesCommandResult.js';
|
|
3
3
|
export type LicensesCommandOptions = {
|
|
4
4
|
compatible?: boolean;
|
|
5
5
|
long?: boolean;
|
|
6
6
|
recursive?: boolean;
|
|
7
7
|
json?: boolean;
|
|
8
|
-
} & Pick<Config, 'dev' | 'dir' | 'lockfileDir' | 'registries' | 'optional' | 'production' | 'storeDir' | 'virtualStoreDir' | 'modulesDir' | 'pnpmHomeDir' | '
|
|
8
|
+
} & Pick<Config, 'dev' | 'dir' | 'lockfileDir' | 'registries' | 'optional' | 'production' | 'storeDir' | 'virtualStoreDir' | 'modulesDir' | 'pnpmHomeDir' | 'supportedArchitectures' | 'virtualStoreDirMaxLength'> & Pick<ConfigContext, 'selectedProjectsGraph' | 'rootProjectManifest' | 'rootProjectManifestDir'> & Partial<Pick<Config, 'userConfig'>>;
|
|
9
9
|
export declare function licensesList(opts: LicensesCommandOptions): Promise<LicensesCommandResult>;
|
package/lib/sbom/sbom.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type Config } from '@pnpm/config.reader';
|
|
1
|
+
import { type Config, type ConfigContext } from '@pnpm/config.reader';
|
|
2
2
|
export type SbomCommandOptions = {
|
|
3
3
|
sbomFormat?: string;
|
|
4
4
|
sbomType?: string;
|
|
5
5
|
lockfileOnly?: boolean;
|
|
6
6
|
sbomAuthors?: string;
|
|
7
7
|
sbomSupplier?: string;
|
|
8
|
-
} & Pick<Config, 'dev' | 'dir' | 'lockfileDir' | 'registries' | 'optional' | 'production' | 'storeDir' | 'virtualStoreDir' | 'modulesDir' | 'pnpmHomeDir' | '
|
|
8
|
+
} & Pick<Config, 'dev' | 'dir' | 'lockfileDir' | 'registries' | 'optional' | 'production' | 'storeDir' | 'virtualStoreDir' | 'modulesDir' | 'pnpmHomeDir' | 'virtualStoreDirMaxLength'> & Pick<ConfigContext, 'selectedProjectsGraph' | 'rootProjectManifest' | 'rootProjectManifestDir'> & Partial<Pick<Config, 'userConfig'>>;
|
|
9
9
|
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
10
10
|
export declare const cliOptionsTypes: () => Record<string, unknown>;
|
|
11
11
|
export declare const shorthands: Record<string, string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/deps.compliance.commands",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1101.0.0",
|
|
4
4
|
"description": "pnpm commands for audit, licenses, and sbom",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -33,41 +33,43 @@
|
|
|
33
33
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
34
34
|
"render-help": "^2.0.0",
|
|
35
35
|
"semver": "^7.7.2",
|
|
36
|
-
"@pnpm/cli.command": "
|
|
37
|
-
"@pnpm/cli.common-cli-options-help": "
|
|
38
|
-
"@pnpm/cli.utils": "
|
|
39
|
-
"@pnpm/
|
|
40
|
-
"@pnpm/
|
|
41
|
-
"@pnpm/
|
|
42
|
-
"@pnpm/
|
|
43
|
-
"@pnpm/deps.compliance.license-scanner": "
|
|
44
|
-
"@pnpm/
|
|
45
|
-
"@pnpm/
|
|
46
|
-
"@pnpm/
|
|
47
|
-
"@pnpm/
|
|
48
|
-
"@pnpm/
|
|
49
|
-
"@pnpm/lockfile.utils": "
|
|
50
|
-
"@pnpm/lockfile.
|
|
51
|
-
"@pnpm/
|
|
52
|
-
"@pnpm/
|
|
53
|
-
"@pnpm/
|
|
54
|
-
"@pnpm/
|
|
55
|
-
"@pnpm/
|
|
36
|
+
"@pnpm/cli.command": "1100.0.0",
|
|
37
|
+
"@pnpm/cli.common-cli-options-help": "1100.0.0",
|
|
38
|
+
"@pnpm/cli.utils": "1100.0.1",
|
|
39
|
+
"@pnpm/cli.meta": "1100.0.1",
|
|
40
|
+
"@pnpm/config.reader": "1100.0.1",
|
|
41
|
+
"@pnpm/deps.compliance.audit": "1101.0.0",
|
|
42
|
+
"@pnpm/constants": "1100.0.0",
|
|
43
|
+
"@pnpm/deps.compliance.license-scanner": "1100.0.1",
|
|
44
|
+
"@pnpm/lockfile.fs": "1100.0.1",
|
|
45
|
+
"@pnpm/deps.compliance.sbom": "1100.0.1",
|
|
46
|
+
"@pnpm/lockfile.types": "1100.0.1",
|
|
47
|
+
"@pnpm/error": "1100.0.0",
|
|
48
|
+
"@pnpm/installing.commands": "1100.0.1",
|
|
49
|
+
"@pnpm/lockfile.utils": "1100.0.1",
|
|
50
|
+
"@pnpm/lockfile.walker": "1100.0.1",
|
|
51
|
+
"@pnpm/network.auth-header": "1100.0.1",
|
|
52
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.1",
|
|
53
|
+
"@pnpm/store.path": "1100.0.0",
|
|
54
|
+
"@pnpm/config.writer": "1100.0.1",
|
|
55
|
+
"@pnpm/types": "1101.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@pnpm/registry-mock": "
|
|
59
|
-
"@types/ramda": "0.
|
|
58
|
+
"@pnpm/registry-mock": "6.0.0",
|
|
59
|
+
"@types/ramda": "0.31.1",
|
|
60
60
|
"@types/semver": "7.7.1",
|
|
61
61
|
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
|
62
62
|
"load-json-file": "^7.0.1",
|
|
63
63
|
"nock": "13.3.4",
|
|
64
64
|
"read-yaml-file": "^3.0.0",
|
|
65
65
|
"tempy": "3.0.0",
|
|
66
|
-
"@pnpm/deps.compliance.commands": "
|
|
67
|
-
"@pnpm/pkg-manifest.reader": "
|
|
68
|
-
"@pnpm/
|
|
69
|
-
"@pnpm/
|
|
70
|
-
"@pnpm/
|
|
66
|
+
"@pnpm/deps.compliance.commands": "1101.0.0",
|
|
67
|
+
"@pnpm/pkg-manifest.reader": "1100.0.1",
|
|
68
|
+
"@pnpm/prepare": "1100.0.1",
|
|
69
|
+
"@pnpm/testing.command-defaults": "1100.0.0",
|
|
70
|
+
"@pnpm/test-fixtures": "1100.0.0",
|
|
71
|
+
"@pnpm/testing.mock-agent": "1100.0.1",
|
|
72
|
+
"@pnpm/workspace.projects-filter": "1100.0.1"
|
|
71
73
|
},
|
|
72
74
|
"engines": {
|
|
73
75
|
"node": ">=22.13"
|
|
@@ -77,9 +79,9 @@
|
|
|
77
79
|
},
|
|
78
80
|
"scripts": {
|
|
79
81
|
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
82
|
+
"test": "pn compile && pn .test",
|
|
83
|
+
"compile": "tsgo --build && pn lint --fix",
|
|
84
|
+
"update-responses": "node test/audit/utils/responses/update.ts",
|
|
85
|
+
".test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules --disable-warning=ExperimentalWarning --disable-warning=DEP0169\" jest"
|
|
84
86
|
}
|
|
85
87
|
}
|