@vltpkg/package-info 1.0.0-rc.24 → 1.0.0-rc.26

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.
Files changed (2) hide show
  1. package/dist/index.js +44 -4
  2. package/package.json +15 -14
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { asPackument, isIntegrity } from '@vltpkg/types';
9
9
  import ssri from 'ssri';
10
10
  import { Monorepo } from '@vltpkg/workspaces';
11
11
  import { XDG } from '@vltpkg/xdg';
12
- import { randomBytes } from 'node:crypto';
12
+ import { createHash, randomBytes } from 'node:crypto';
13
13
  import { mkdir, readFile, rm, stat, symlink, unlink, writeFile, } from 'node:fs/promises';
14
14
  import { basename, dirname, resolve as pathResolve, relative, } from 'node:path';
15
15
  import { create as tarC } from 'tar';
@@ -67,7 +67,11 @@ export class PackageInfoClient {
67
67
  spec = Spec.parse(spec, this.options);
68
68
  const { from = this.#projectRoot, integrity, resolved } = options;
69
69
  const f = spec.final;
70
- const r = integrity && resolved ?
70
+ // Track whether integrity/resolved came from the caller (e.g. lockfile)
71
+ // vs freshly resolved. We only verify tarball integrity on net-new
72
+ // installs (fresh resolution), not when replaying from lockfile.
73
+ const fromLockfile = !!(integrity && resolved);
74
+ const r = fromLockfile ?
71
75
  { resolved, integrity, spec }
72
76
  : await this.resolve(spec, options);
73
77
  switch (f.type) {
@@ -114,8 +118,28 @@ export class PackageInfoClient {
114
118
  response.checkIntegrity({ spec, url: resolved })) {
115
119
  this.#trustedIntegrities.set(r.resolved, response.integrity);
116
120
  }
121
+ const buf = response.buffer();
122
+ // Verify tarball integrity against the manifest's dist.integrity.
123
+ // This is a supply-chain security measure: the registry may not
124
+ // validate integrity, so we do it client-side on every fresh
125
+ // download. Skip when integrity came from lockfile/cache (it was
126
+ // already verified on first install).
127
+ if (r.integrity && !fromLockfile) {
128
+ const hash = createHash('sha512');
129
+ hash.update(buf);
130
+ const computed = `sha512-${hash.digest('base64')}`;
131
+ if (computed !== r.integrity) {
132
+ throw error('Tarball integrity check failed', {
133
+ code: 'EINTEGRITY',
134
+ spec,
135
+ url: r.resolved,
136
+ wanted: r.integrity,
137
+ found: computed,
138
+ });
139
+ }
140
+ }
117
141
  try {
118
- await this.tarPool.unpack(response.buffer(), target);
142
+ await this.tarPool.unpack(buf, target);
119
143
  }
120
144
  catch (er) {
121
145
  throw this.#resolveError(spec, options, 'tar unpack failed', { cause: er });
@@ -292,7 +316,23 @@ export class PackageInfoClient {
292
316
  response.checkIntegrity({ spec, url: tarball })) {
293
317
  this.#trustedIntegrities.set(tarball, response.integrity);
294
318
  }
295
- return response.buffer();
319
+ const buf = response.buffer();
320
+ // Verify tarball integrity against the manifest's dist.integrity.
321
+ if (integrity) {
322
+ const hash = createHash('sha512');
323
+ hash.update(buf);
324
+ const computed = `sha512-${hash.digest('base64')}`;
325
+ if (computed !== integrity) {
326
+ throw error('Tarball integrity check failed', {
327
+ code: 'EINTEGRITY',
328
+ spec,
329
+ url: tarball,
330
+ wanted: integrity,
331
+ found: computed,
332
+ });
333
+ }
334
+ }
335
+ return buf;
296
336
  }
297
337
  case 'git': {
298
338
  const { remoteURL, gitRemote, gitCommittish, gitSelectorParsed, } = f;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/package-info",
3
3
  "description": "Resolve and fetch package metadata and tarballs",
4
- "version": "1.0.0-rc.24",
4
+ "version": "1.0.0-rc.26",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -9,19 +9,20 @@
9
9
  },
10
10
  "author": {
11
11
  "name": "vlt technology inc.",
12
- "email": "support@vlt.sh"
12
+ "email": "support@vlt.sh",
13
+ "url": "http://vlt.sh"
13
14
  },
14
15
  "dependencies": {
15
- "@vltpkg/error-cause": "1.0.0-rc.24",
16
- "@vltpkg/git": "1.0.0-rc.24",
17
- "@vltpkg/package-json": "1.0.0-rc.24",
18
- "@vltpkg/pick-manifest": "1.0.0-rc.24",
19
- "@vltpkg/registry-client": "1.0.0-rc.24",
20
- "@vltpkg/spec": "1.0.0-rc.24",
21
- "@vltpkg/tar": "1.0.0-rc.24",
22
- "@vltpkg/types": "1.0.0-rc.24",
23
- "@vltpkg/workspaces": "1.0.0-rc.24",
24
- "@vltpkg/xdg": "1.0.0-rc.24",
16
+ "@vltpkg/error-cause": "1.0.0-rc.26",
17
+ "@vltpkg/git": "1.0.0-rc.26",
18
+ "@vltpkg/package-json": "1.0.0-rc.26",
19
+ "@vltpkg/pick-manifest": "1.0.0-rc.26",
20
+ "@vltpkg/registry-client": "1.0.0-rc.26",
21
+ "@vltpkg/spec": "1.0.0-rc.26",
22
+ "@vltpkg/tar": "1.0.0-rc.26",
23
+ "@vltpkg/types": "1.0.0-rc.26",
24
+ "@vltpkg/workspaces": "1.0.0-rc.26",
25
+ "@vltpkg/xdg": "1.0.0-rc.26",
25
26
  "ssri": "^13.0.0",
26
27
  "tar": "^7.5.2"
27
28
  },
@@ -30,8 +31,8 @@
30
31
  "@types/node": "^22.19.2",
31
32
  "@types/pacote": "^11.1.8",
32
33
  "@vltpkg/benchmark": "0.0.0",
33
- "@vltpkg/cache-unzip": "1.0.0-rc.24",
34
- "@vltpkg/vlt-json": "1.0.0-rc.24",
34
+ "@vltpkg/cache-unzip": "1.0.0-rc.26",
35
+ "@vltpkg/vlt-json": "1.0.0-rc.26",
35
36
  "eslint": "^9.39.1",
36
37
  "pacote": "^21.0.4",
37
38
  "prettier": "^3.7.4",