mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-01 19:35:22 -04:00
docs: clarify store trust boundary (#12268)
This commit is contained in:
7
.changeset/store-discl.md
Normal file
7
.changeset/store-discl.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/cli.common-cli-options-help": patch
|
||||||
|
"@pnpm/installing.commands": patch
|
||||||
|
"pnpm": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Clarified in CLI help that the pnpm store is trusted shared state and store integrity checks are corruption detection, not a tamper boundary for untrusted store writers.
|
||||||
@@ -16,7 +16,7 @@ export const OPTIONS = {
|
|||||||
name: '--prefer-offline',
|
name: '--prefer-offline',
|
||||||
},
|
},
|
||||||
storeDir: {
|
storeDir: {
|
||||||
description: 'The directory in which all the packages are saved on the disk',
|
description: 'The directory in which all packages are saved on disk. Use a shared store only with trusted users and jobs',
|
||||||
name: '--store-dir <dir>',
|
name: '--store-dir <dir>',
|
||||||
},
|
},
|
||||||
virtualStoreDir: {
|
virtualStoreDir: {
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ by any dependencies, so it is an emulation of a flat node_modules',
|
|||||||
name: '--ignore-workspace',
|
name: '--ignore-workspace',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "If false, doesn't check whether packages in the store were mutated",
|
description: 'If false, skips store integrity checks. These checks detect accidental corruption, not tampering by untrusted users with write access to the store',
|
||||||
name: '--[no-]verify-store-integrity',
|
name: '--[no-]verify-store-integrity',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -387,7 +387,9 @@ pub struct Config {
|
|||||||
/// true to hoist them for you.
|
/// true to hoist them for you.
|
||||||
pub shamefully_hoist: bool,
|
pub shamefully_hoist: bool,
|
||||||
|
|
||||||
/// The location where all the packages are saved on the disk.
|
/// The location where all packages are saved on disk. Share a
|
||||||
|
/// writable store only between mutually trusted users, jobs, and
|
||||||
|
/// processes.
|
||||||
#[default(_code = "default_store_dir::<Host>()")]
|
#[default(_code = "default_store_dir::<Host>()")]
|
||||||
pub store_dir: StoreDir,
|
pub store_dir: StoreDir,
|
||||||
|
|
||||||
@@ -792,6 +794,9 @@ pub struct Config {
|
|||||||
/// lookup skips that verification entirely and trusts the index — a
|
/// lookup skips that verification entirely and trusts the index — a
|
||||||
/// missing blob is discovered lazily at link time instead.
|
/// missing blob is discovered lazily at link time instead.
|
||||||
///
|
///
|
||||||
|
/// This is corruption detection for a trusted store, not a tamper
|
||||||
|
/// boundary for a store writable by untrusted users or jobs.
|
||||||
|
///
|
||||||
/// Matches pnpm's `verifyStoreIntegrity` camelCase key in
|
/// Matches pnpm's `verifyStoreIntegrity` camelCase key in
|
||||||
/// `pnpm-workspace.yaml` (same `true` default as pnpm's
|
/// `pnpm-workspace.yaml` (same `true` default as pnpm's
|
||||||
/// `installing/deps-installer/src/install/extendInstallOptions.ts`).
|
/// `installing/deps-installer/src/install/extendInstallOptions.ts`).
|
||||||
@@ -1152,6 +1157,8 @@ pub struct Config {
|
|||||||
/// verification gate to memoize past results in
|
/// verification gate to memoize past results in
|
||||||
/// `<cache_dir>/lockfile-verified.jsonl`, and by the npm verifier
|
/// `<cache_dir>/lockfile-verified.jsonl`, and by the npm verifier
|
||||||
/// to mirror full-metadata responses for conditional GETs.
|
/// to mirror full-metadata responses for conditional GETs.
|
||||||
|
/// Share a writable cache only between mutually trusted users,
|
||||||
|
/// jobs, and processes.
|
||||||
///
|
///
|
||||||
/// Mirrors pnpm's
|
/// Mirrors pnpm's
|
||||||
/// [`cacheDir`](https://github.com/pnpm/pnpm/blob/2a9bd897bf/config/reader/src/Config.ts#L159);
|
/// [`cacheDir`](https://github.com/pnpm/pnpm/blob/2a9bd897bf/config/reader/src/Config.ts#L159);
|
||||||
|
|||||||
@@ -270,6 +270,10 @@ fn build_side_effects_maps(
|
|||||||
/// fails, so operators can see *which* package file invalidated the
|
/// fails, so operators can see *which* package file invalidated the
|
||||||
/// store-index row in the log.
|
/// store-index row in the log.
|
||||||
///
|
///
|
||||||
|
/// **Trust boundary.** This verification is for corruption detection
|
||||||
|
/// in a trusted local store. It is not a tamper boundary for a store
|
||||||
|
/// writable by untrusted users or jobs.
|
||||||
|
///
|
||||||
/// **Locking discipline.** The fast path (`is_modified == false`, i.e.
|
/// **Locking discipline.** The fast path (`is_modified == false`, i.e.
|
||||||
/// the file's mtime is within 100 ms of the recorded `checked_at`)
|
/// the file's mtime is within 100 ms of the recorded `checked_at`)
|
||||||
/// runs lock-free — it never touches the file's bytes and never
|
/// runs lock-free — it never touches the file's bytes and never
|
||||||
|
|||||||
@@ -168,8 +168,9 @@ function verifyFile (
|
|||||||
}
|
}
|
||||||
return passed
|
return passed
|
||||||
}
|
}
|
||||||
// If a file was not edited, we are skipping integrity check.
|
// Fast path for trusted stores: if metadata says the file is unchanged, skip the
|
||||||
// We assume that nobody will manually remove a file in the store and create a new one.
|
// digest read. Store integrity verification detects corruption; it does not make
|
||||||
|
// a store writable by untrusted users safe.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user