@vltpkg/security-archive 1.3.8 → 1.5.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 +14 -1
- package/dist/index.d.ts +18 -14
- package/dist/index.js +65 -25
- package/dist/types.d.ts +27 -0
- package/dist/types.js +20 -0
- package/dist/update-expired.d.ts +2 -0
- package/dist/update-expired.js +18 -16
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -23,7 +23,9 @@ const graph = actual.load({
|
|
|
23
23
|
projectRoot: process.cwd(),
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
const archive = await SecurityArchive.start({
|
|
26
|
+
const archive = await SecurityArchive.start({
|
|
27
|
+
nodes: [...graph.nodes.values()],
|
|
28
|
+
})
|
|
27
29
|
|
|
28
30
|
if (archive.ok) {
|
|
29
31
|
for (const node of graph.nodes.values()) {
|
|
@@ -36,3 +38,14 @@ if (archive.ok) {
|
|
|
36
38
|
console.warn('Failed to start the SecurityArchive')
|
|
37
39
|
}
|
|
38
40
|
```
|
|
41
|
+
|
|
42
|
+
## Options
|
|
43
|
+
|
|
44
|
+
- `path`: sqlite db location. Defaults to the vlt XDG cache dir.
|
|
45
|
+
- `retries`: retry attempts on failed API requests. Defaults to `3`.
|
|
46
|
+
- `timeout`: max ms to wait for the API, retries included. Defaults to
|
|
47
|
+
`VLT_SECURITY_ARCHIVE_TIMEOUT` env or `30000`. Must be a positive
|
|
48
|
+
integer, other values are ignored. On timeout a warning is printed,
|
|
49
|
+
missing packages stay unscanned, `ok` is `false`, `timedOut` is
|
|
50
|
+
`true` and nothing is cached.
|
|
51
|
+
- `ttl`: ms to cache newly fetched entries for. Defaults to 3 hours.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,19 +3,6 @@ import type { DepID } from '@vltpkg/dep-id';
|
|
|
3
3
|
import type { PackageReportData, SecurityArchiveLike, SecurityArchiveRefreshOptions } from './types.ts';
|
|
4
4
|
export * from './types.ts';
|
|
5
5
|
export { npmRegistryURL, usesNpmRegistry } from './browser.ts';
|
|
6
|
-
export type JSONItemResponse = {
|
|
7
|
-
namespace?: `@{string}`;
|
|
8
|
-
name: string;
|
|
9
|
-
version: string;
|
|
10
|
-
score: {
|
|
11
|
-
overall: number;
|
|
12
|
-
license: number;
|
|
13
|
-
maintenance: number;
|
|
14
|
-
quality: number;
|
|
15
|
-
supplyChain: number;
|
|
16
|
-
vulnerability: number;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
6
|
export type DBReadEntry = {
|
|
20
7
|
depID: string;
|
|
21
8
|
now: number;
|
|
@@ -37,6 +24,14 @@ export type SecurityArchiveOptions = LRUCache.OptionsBase<DepID, PackageReportDa
|
|
|
37
24
|
* Number of retries attempts to reach the remote security API.
|
|
38
25
|
*/
|
|
39
26
|
retries?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Max ms to wait for the remote security API, incl. retries.
|
|
29
|
+
* Defaults to `VLT_SECURITY_ARCHIVE_TIMEOUT` env or
|
|
30
|
+
* {@link SecurityArchive.defaultTimeout}. Positive integers only,
|
|
31
|
+
* other values are ignored. On timeout, missing packages are left
|
|
32
|
+
* unscanned and a warning is printed.
|
|
33
|
+
*/
|
|
34
|
+
timeout?: number;
|
|
40
35
|
};
|
|
41
36
|
/**
|
|
42
37
|
* A database of security information for given packages from a list of nodes.
|
|
@@ -44,7 +39,8 @@ export type SecurityArchiveOptions = LRUCache.OptionsBase<DepID, PackageReportDa
|
|
|
44
39
|
* Using the SecurityArchive.refresh() method will update the local cache
|
|
45
40
|
* with information from the socket.dev APIs or load from the local storage
|
|
46
41
|
* if available. Information about package security is then available
|
|
47
|
-
* using the SecurityArchive.get() method.
|
|
42
|
+
* using the SecurityArchive.get() method. Remote requests are bounded
|
|
43
|
+
* by the `timeout` option.
|
|
48
44
|
*/
|
|
49
45
|
export declare class SecurityArchive extends LRUCache<DepID, PackageReportData> implements SecurityArchiveLike {
|
|
50
46
|
#private;
|
|
@@ -53,6 +49,10 @@ export declare class SecurityArchive extends LRUCache<DepID, PackageReportData>
|
|
|
53
49
|
* for all public registry packages from the initial list of nodes.
|
|
54
50
|
*/
|
|
55
51
|
ok: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* True if the last refresh() timed out waiting for the remote API.
|
|
54
|
+
*/
|
|
55
|
+
timedOut: boolean;
|
|
56
56
|
/**
|
|
57
57
|
* Creates a new security archive instance and starts the refresh process.
|
|
58
58
|
*/
|
|
@@ -65,6 +65,10 @@ export declare class SecurityArchive extends LRUCache<DepID, PackageReportData>
|
|
|
65
65
|
* By default, entries are cached for 3 hours.
|
|
66
66
|
*/
|
|
67
67
|
static get defaultTtl(): number;
|
|
68
|
+
/**
|
|
69
|
+
* By default, remote requests time out after 30 seconds.
|
|
70
|
+
*/
|
|
71
|
+
static get defaultTimeout(): number;
|
|
68
72
|
constructor(options?: SecurityArchiveOptions);
|
|
69
73
|
/**
|
|
70
74
|
* Get the report data for a node, keyed by its base {@link DepID}.
|
package/dist/index.js
CHANGED
|
@@ -9,25 +9,34 @@ import { asDepID, baseDepID } from '@vltpkg/dep-id';
|
|
|
9
9
|
import { error } from '@vltpkg/error-cause';
|
|
10
10
|
import { userAgent } from '@vltpkg/user-agent';
|
|
11
11
|
import { XDG } from '@vltpkg/xdg';
|
|
12
|
-
import { asPackageReportData } from "./types.js";
|
|
12
|
+
import { asPackageReportData, getItemScore } from "./types.js";
|
|
13
13
|
import { __CODE_SPLIT_SCRIPT_NAME } from "./update-expired.js";
|
|
14
14
|
import { usesNpmRegistry } from "./browser.js";
|
|
15
15
|
export * from "./types.js";
|
|
16
16
|
export { npmRegistryURL, usesNpmRegistry } from "./browser.js";
|
|
17
17
|
const SOCKET_API_V0_URL = 'https://api.socket.dev/v0/purl?alerts=true';
|
|
18
18
|
const SOCKET_PUBLIC_API_TOKEN = 'sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api';
|
|
19
|
+
// AbortSignal.timeout throws on <0/NaN and overflows to 1ms above 2^31-1
|
|
20
|
+
const asTimeout = (raw) => {
|
|
21
|
+
const n = Number(raw);
|
|
22
|
+
return Number.isInteger(n) && n > 0 && n <= 2_147_483_647 ?
|
|
23
|
+
n
|
|
24
|
+
: undefined;
|
|
25
|
+
};
|
|
19
26
|
/**
|
|
20
27
|
* A database of security information for given packages from a list of nodes.
|
|
21
28
|
*
|
|
22
29
|
* Using the SecurityArchive.refresh() method will update the local cache
|
|
23
30
|
* with information from the socket.dev APIs or load from the local storage
|
|
24
31
|
* if available. Information about package security is then available
|
|
25
|
-
* using the SecurityArchive.get() method.
|
|
32
|
+
* using the SecurityArchive.get() method. Remote requests are bounded
|
|
33
|
+
* by the `timeout` option.
|
|
26
34
|
*/
|
|
27
35
|
export class SecurityArchive extends LRUCache {
|
|
28
36
|
#expired = new Set();
|
|
29
37
|
#path;
|
|
30
38
|
#retries;
|
|
39
|
+
#timeout;
|
|
31
40
|
#nodesByName = new Map();
|
|
32
41
|
#nodesByID = new Map();
|
|
33
42
|
/**
|
|
@@ -35,6 +44,10 @@ export class SecurityArchive extends LRUCache {
|
|
|
35
44
|
* for all public registry packages from the initial list of nodes.
|
|
36
45
|
*/
|
|
37
46
|
ok = false;
|
|
47
|
+
/**
|
|
48
|
+
* True if the last refresh() timed out waiting for the remote API.
|
|
49
|
+
*/
|
|
50
|
+
timedOut = false;
|
|
38
51
|
/**
|
|
39
52
|
* Creates a new security archive instance and starts the refresh process.
|
|
40
53
|
*/
|
|
@@ -55,6 +68,12 @@ export class SecurityArchive extends LRUCache {
|
|
|
55
68
|
static get defaultTtl() {
|
|
56
69
|
return 1000 * 60 * 60 * 3;
|
|
57
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* By default, remote requests time out after 30 seconds.
|
|
73
|
+
*/
|
|
74
|
+
static get defaultTimeout() {
|
|
75
|
+
return 30_000;
|
|
76
|
+
}
|
|
58
77
|
constructor(options = {}) {
|
|
59
78
|
super({
|
|
60
79
|
max: _a.defaultMax,
|
|
@@ -65,6 +84,10 @@ export class SecurityArchive extends LRUCache {
|
|
|
65
84
|
this.#path =
|
|
66
85
|
options.path ?? new XDG('vlt').cache('security-archive.db');
|
|
67
86
|
this.#retries = options.retries ?? 3;
|
|
87
|
+
this.#timeout =
|
|
88
|
+
asTimeout(options.timeout) ??
|
|
89
|
+
asTimeout(process.env.VLT_SECURITY_ARCHIVE_TIMEOUT) ??
|
|
90
|
+
_a.defaultTimeout;
|
|
68
91
|
}
|
|
69
92
|
/**
|
|
70
93
|
* Get the report data for a node, keyed by its base {@link DepID}.
|
|
@@ -187,6 +210,7 @@ export class SecurityArchive extends LRUCache {
|
|
|
187
210
|
const payload = {
|
|
188
211
|
dbPath: this.#path,
|
|
189
212
|
retries: this.#retries,
|
|
213
|
+
timeout: this.#timeout,
|
|
190
214
|
ttl: _a.defaultTtl,
|
|
191
215
|
expired,
|
|
192
216
|
};
|
|
@@ -235,7 +259,7 @@ export class SecurityArchive extends LRUCache {
|
|
|
235
259
|
* Fetches security information from the socket.dev API.
|
|
236
260
|
* Returns a string of NDJSON data.
|
|
237
261
|
*/
|
|
238
|
-
async #retrieveRemoteData(queue) {
|
|
262
|
+
async #retrieveRemoteData(queue, signal) {
|
|
239
263
|
// fetch information from the socket.dev API
|
|
240
264
|
const req = await fetch(SOCKET_API_V0_URL, {
|
|
241
265
|
method: 'POST',
|
|
@@ -246,6 +270,7 @@ export class SecurityArchive extends LRUCache {
|
|
|
246
270
|
body: JSON.stringify({
|
|
247
271
|
components: Array.from(queue),
|
|
248
272
|
}),
|
|
273
|
+
signal,
|
|
249
274
|
});
|
|
250
275
|
// on missing valid auth or API, it should abort the retry logic
|
|
251
276
|
if (req.status === 404) {
|
|
@@ -258,6 +283,23 @@ export class SecurityArchive extends LRUCache {
|
|
|
258
283
|
const str = await req.text();
|
|
259
284
|
return str.trim() + '\n';
|
|
260
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Fetches remote data within the configured timeout, retries included.
|
|
288
|
+
* Returns `undefined` on timeout so that queued packages stay unscanned.
|
|
289
|
+
*/
|
|
290
|
+
async #fetchRemoteData(queue) {
|
|
291
|
+
const signal = AbortSignal.timeout(this.#timeout);
|
|
292
|
+
try {
|
|
293
|
+
return await pRetry(() => this.#retrieveRemoteData(queue, signal), { retries: this.#retries, signal });
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
if (!signal.aborted)
|
|
297
|
+
throw err;
|
|
298
|
+
this.timedOut = true;
|
|
299
|
+
// eslint-disable-next-line no-console
|
|
300
|
+
console.warn(`security-archive: timed out after ${this.#timeout}ms fetching security data; ${queue.size} package(s) left unscanned (use :scanned to exclude them). Set VLT_SECURITY_ARCHIVE_TIMEOUT=<ms> to wait longer.`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
261
303
|
/**
|
|
262
304
|
* Parses and load NDJSON data into the in-memory cache.
|
|
263
305
|
* Returns a set of dep ids that were successfully loaded.
|
|
@@ -270,30 +312,25 @@ export class SecurityArchive extends LRUCache {
|
|
|
270
312
|
if (!line.trim())
|
|
271
313
|
continue;
|
|
272
314
|
const data = JSON.parse(line + '}');
|
|
315
|
+
// skip the purlError and summary wrapper items the API may
|
|
316
|
+
// include in the stream, they do not describe a package
|
|
317
|
+
if (data._type)
|
|
318
|
+
continue;
|
|
273
319
|
const scope = data.namespace ? `${data.namespace}/` : '';
|
|
274
320
|
const name = `${scope}${data.name}`;
|
|
275
|
-
const node = this.#retrieveNodeByNameVersion(name, data.version);
|
|
321
|
+
const node = this.#retrieveNodeByNameVersion(name, String(data.version));
|
|
276
322
|
if (node) {
|
|
323
|
+
const score = getItemScore(data);
|
|
324
|
+
// a package that socket.dev has not finished analyzing yet
|
|
325
|
+
// comes back without a score, leave it out of the archive so
|
|
326
|
+
// that it gets requested again on the next run
|
|
327
|
+
if (!score)
|
|
328
|
+
continue;
|
|
277
329
|
const normalizedId = baseDepID(node.id);
|
|
278
|
-
fetchedDepIDs.add(
|
|
279
|
-
// Calculate average score from all score components
|
|
280
|
-
const scoreComponents = [
|
|
281
|
-
data.score.license,
|
|
282
|
-
data.score.maintenance,
|
|
283
|
-
data.score.quality,
|
|
284
|
-
data.score.supplyChain,
|
|
285
|
-
data.score.vulnerability,
|
|
286
|
-
];
|
|
287
|
-
const newAverageScore = Number((scoreComponents.reduce((sum, score) => sum + score, 0) /
|
|
288
|
-
scoreComponents.length).toFixed(2));
|
|
289
|
-
// Add average score to the score object
|
|
290
|
-
const scoreWithNewAverage = {
|
|
291
|
-
...data.score,
|
|
292
|
-
overall: newAverageScore,
|
|
293
|
-
};
|
|
330
|
+
fetchedDepIDs.add(normalizedId);
|
|
294
331
|
this.set(normalizedId, asPackageReportData({
|
|
295
332
|
...data,
|
|
296
|
-
score
|
|
333
|
+
score,
|
|
297
334
|
}));
|
|
298
335
|
}
|
|
299
336
|
else {
|
|
@@ -350,6 +387,7 @@ export class SecurityArchive extends LRUCache {
|
|
|
350
387
|
async refresh({ nodes }) {
|
|
351
388
|
// should start by clearing the current in-memory cache
|
|
352
389
|
this.clear();
|
|
390
|
+
this.timedOut = false;
|
|
353
391
|
const db = this.#openDatabase();
|
|
354
392
|
// indexes nodes by name and id for quick lookup
|
|
355
393
|
this.#nodesByName.clear();
|
|
@@ -367,10 +405,12 @@ export class SecurityArchive extends LRUCache {
|
|
|
367
405
|
const queue = this.#queueUpRequiredPackages();
|
|
368
406
|
// only reach for the remote API if there are packages queued up
|
|
369
407
|
if (queue.size > 0) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
408
|
+
const res = await this.#fetchRemoteData(queue);
|
|
409
|
+
// on timeout nothing is loaded nor cached
|
|
410
|
+
if (res !== undefined) {
|
|
411
|
+
const ids = this.#loadFromNDJSON(res);
|
|
412
|
+
this.#storeNewItemsToDatabase(db, ids);
|
|
413
|
+
}
|
|
374
414
|
}
|
|
375
415
|
// validates the refresh process was successful
|
|
376
416
|
this.#validateReportData();
|
package/dist/types.d.ts
CHANGED
|
@@ -89,3 +89,30 @@ export type PackageReportData = {
|
|
|
89
89
|
};
|
|
90
90
|
export declare const isPackageReportData: (o: unknown) => o is PackageReportData;
|
|
91
91
|
export declare const asPackageReportData: (o: unknown) => PackageReportData;
|
|
92
|
+
/**
|
|
93
|
+
* A single line of the NDJSON stream returned by the socket.dev
|
|
94
|
+
* batch purl API. Besides package artifacts, the stream can carry
|
|
95
|
+
* `purlError` and `summary` wrapper items, and a package that was
|
|
96
|
+
* published recently enough to not have been analyzed yet comes back
|
|
97
|
+
* as an artifact with no `score` object at all.
|
|
98
|
+
*/
|
|
99
|
+
export type JSONItemResponse = {
|
|
100
|
+
_type?: 'purlError' | 'summary';
|
|
101
|
+
namespace?: `@${string}`;
|
|
102
|
+
name?: string;
|
|
103
|
+
version?: string;
|
|
104
|
+
score?: {
|
|
105
|
+
overall?: number;
|
|
106
|
+
license: number;
|
|
107
|
+
maintenance: number;
|
|
108
|
+
quality: number;
|
|
109
|
+
supplyChain: number;
|
|
110
|
+
vulnerability: number;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Returns the score of a response item with its `overall` value
|
|
115
|
+
* recalculated as the average of the individual components, or
|
|
116
|
+
* `undefined` when the item is not a scored package artifact.
|
|
117
|
+
*/
|
|
118
|
+
export declare const getItemScore: (data: JSONItemResponse) => PackageScore | undefined;
|
package/dist/types.js
CHANGED
|
@@ -27,3 +27,23 @@ export const asPackageReportData = (o) => {
|
|
|
27
27
|
}
|
|
28
28
|
return o;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns the score of a response item with its `overall` value
|
|
32
|
+
* recalculated as the average of the individual components, or
|
|
33
|
+
* `undefined` when the item is not a scored package artifact.
|
|
34
|
+
*/
|
|
35
|
+
export const getItemScore = (data) => {
|
|
36
|
+
if (data._type || !data.score)
|
|
37
|
+
return undefined;
|
|
38
|
+
const { license, maintenance, quality, supplyChain, vulnerability, } = data.score;
|
|
39
|
+
const scoreComponents = [
|
|
40
|
+
license,
|
|
41
|
+
maintenance,
|
|
42
|
+
quality,
|
|
43
|
+
supplyChain,
|
|
44
|
+
vulnerability,
|
|
45
|
+
];
|
|
46
|
+
const overall = Number((scoreComponents.reduce((sum, score) => sum + score, 0) /
|
|
47
|
+
scoreComponents.length).toFixed(2));
|
|
48
|
+
return { ...data.score, overall };
|
|
49
|
+
};
|
package/dist/update-expired.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type UpdateExpiredPayload = {
|
|
|
9
9
|
dbPath: string;
|
|
10
10
|
/** Number of retries for fetching remote data */
|
|
11
11
|
retries: number;
|
|
12
|
+
/** Max ms for the remote request, incl. retries */
|
|
13
|
+
timeout: number;
|
|
12
14
|
/** TTL in ms to use for new entries */
|
|
13
15
|
ttl: number;
|
|
14
16
|
/** Expired entries to revalidate */
|
package/dist/update-expired.js
CHANGED
|
@@ -6,7 +6,7 @@ import pRetry, { AbortError } from 'p-retry';
|
|
|
6
6
|
import { asDepID, baseDepID } from '@vltpkg/dep-id';
|
|
7
7
|
import { error } from '@vltpkg/error-cause';
|
|
8
8
|
import { userAgent } from '@vltpkg/user-agent';
|
|
9
|
-
import { asPackageReportData } from "./types.js";
|
|
9
|
+
import { asPackageReportData, getItemScore } from "./types.js";
|
|
10
10
|
export const __CODE_SPLIT_SCRIPT_NAME = import.meta.filename;
|
|
11
11
|
const SOCKET_API_V0_URL = 'https://api.socket.dev/v0/purl?alerts=true';
|
|
12
12
|
const SOCKET_PUBLIC_API_TOKEN = 'sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api';
|
|
@@ -17,7 +17,8 @@ const isMain = (path) => path === __CODE_SPLIT_SCRIPT_NAME ||
|
|
|
17
17
|
/**
|
|
18
18
|
* Fetches security information from the socket.dev API.
|
|
19
19
|
*/
|
|
20
|
-
const retrieveRemoteData = async (queue, retries) => {
|
|
20
|
+
const retrieveRemoteData = async (queue, retries, timeout) => {
|
|
21
|
+
const signal = AbortSignal.timeout(timeout);
|
|
21
22
|
return pRetry(async () => {
|
|
22
23
|
const req = await fetch(SOCKET_API_V0_URL, {
|
|
23
24
|
method: 'POST',
|
|
@@ -28,6 +29,7 @@ const retrieveRemoteData = async (queue, retries) => {
|
|
|
28
29
|
body: JSON.stringify({
|
|
29
30
|
components: Array.from(queue),
|
|
30
31
|
}),
|
|
32
|
+
signal,
|
|
31
33
|
});
|
|
32
34
|
if (req.status === 404) {
|
|
33
35
|
throw new AbortError('Missing API');
|
|
@@ -39,7 +41,7 @@ const retrieveRemoteData = async (queue, retries) => {
|
|
|
39
41
|
}
|
|
40
42
|
const str = await req.text();
|
|
41
43
|
return str.trim() + '\n';
|
|
42
|
-
}, { retries });
|
|
44
|
+
}, { retries, signal });
|
|
43
45
|
};
|
|
44
46
|
/**
|
|
45
47
|
* Main entrypoint for the detached process.
|
|
@@ -68,7 +70,7 @@ export const main = async (input = process.stdin) => {
|
|
|
68
70
|
/* c8 ignore next */
|
|
69
71
|
input.on('error', reject);
|
|
70
72
|
});
|
|
71
|
-
const { dbPath, retries, ttl, expired } = payload;
|
|
73
|
+
const { dbPath, retries, timeout, ttl, expired } = payload;
|
|
72
74
|
if (!expired.length) {
|
|
73
75
|
return false;
|
|
74
76
|
}
|
|
@@ -82,7 +84,7 @@ export const main = async (input = process.stdin) => {
|
|
|
82
84
|
entryByNameVersion.set(`${entry.name}@${entry.version}`, entry);
|
|
83
85
|
}
|
|
84
86
|
// Fetch updated data
|
|
85
|
-
const res = await retrieveRemoteData(expiredQueue, retries);
|
|
87
|
+
const res = await retrieveRemoteData(expiredQueue, retries, timeout);
|
|
86
88
|
// Parse NDJSON response and collect results
|
|
87
89
|
const now = Date.now();
|
|
88
90
|
const results = [];
|
|
@@ -91,6 +93,10 @@ export const main = async (input = process.stdin) => {
|
|
|
91
93
|
if (!line.trim())
|
|
92
94
|
continue;
|
|
93
95
|
const data = JSON.parse(line + '}');
|
|
96
|
+
// skip the purlError and summary wrapper items the API may
|
|
97
|
+
// include in the stream, they do not describe a package
|
|
98
|
+
if (data._type)
|
|
99
|
+
continue;
|
|
94
100
|
const scope = data.namespace ? `${data.namespace}/` : '';
|
|
95
101
|
const name = `${scope}${data.name}`;
|
|
96
102
|
const key = `${name}@${data.version}`;
|
|
@@ -100,19 +106,15 @@ export const main = async (input = process.stdin) => {
|
|
|
100
106
|
console.warn(`security-archive: failed to find entry for ${key} found in the response.`);
|
|
101
107
|
continue;
|
|
102
108
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
data.score.vulnerability,
|
|
110
|
-
];
|
|
111
|
-
const newAverageScore = Number((scoreComponents.reduce((sum, score) => sum + score, 0) /
|
|
112
|
-
scoreComponents.length).toFixed(2));
|
|
109
|
+
const score = getItemScore(data);
|
|
110
|
+
// a package that socket.dev has not finished analyzing yet comes
|
|
111
|
+
// back without a score, keep the stale entry rather than replacing
|
|
112
|
+
// it with an invalid one
|
|
113
|
+
if (!score)
|
|
114
|
+
continue;
|
|
113
115
|
const reportData = asPackageReportData({
|
|
114
116
|
...data,
|
|
115
|
-
score
|
|
117
|
+
score,
|
|
116
118
|
});
|
|
117
119
|
results.push({
|
|
118
120
|
depID: baseDepID(asDepID(entry.depID)),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vltpkg/security-archive",
|
|
3
3
|
"description": "A database of security information of packages",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"url": "http://vlt.sh"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@vltpkg/dep-id": "1.
|
|
17
|
-
"@vltpkg/error-cause": "1.
|
|
18
|
-
"@vltpkg/spec": "1.
|
|
19
|
-
"@vltpkg/types": "1.
|
|
20
|
-
"@vltpkg/user-agent": "1.
|
|
21
|
-
"@vltpkg/xdg": "1.
|
|
16
|
+
"@vltpkg/dep-id": "1.5.0",
|
|
17
|
+
"@vltpkg/error-cause": "1.5.0",
|
|
18
|
+
"@vltpkg/spec": "1.5.0",
|
|
19
|
+
"@vltpkg/types": "1.5.0",
|
|
20
|
+
"@vltpkg/user-agent": "1.5.0",
|
|
21
|
+
"@vltpkg/xdg": "1.5.0",
|
|
22
22
|
"lru-cache": "^11.2.4",
|
|
23
23
|
"p-retry": "^7.1.1"
|
|
24
24
|
},
|