You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: pin extracted-tree hash instead of archive hash
Rework the plugin lockfile to hash the extracted $id-$version/ directory
(the code Nextflow actually loads and executes) rather than the downloaded
archive. Hashing the unpacked tree lets a single, content-addressed check
cover both integrity surfaces:
- supply chain / registry compromise / silent drift (a tampered archive
extracts to a different tree), and
- cache poisoning of the executed code (a lower-trust user editing already
-extracted files on a shared cache) — detected regardless of directory
ownership or permissions, with no ownership heuristic and therefore no
false-positive warnings on legitimate shared caches.
This supersedes the archive-hash approach and the directory-ownership guard
proposed in #7308: it is stronger (catches modifications an ownership check
misses) and quieter (silent on any healthy cache; output only on a genuine
mismatch).
Verification runs once per plugin in load0(), before loading, on both cold
and warm caches. The retained-archive machinery and the "archive absent"
case are removed (the extracted tree is always present when a plugin loads).
Full re-hash on every load is acceptable for now; the ADR documents a local
fingerprint-cache optimisation (gated on a private, non-writable cache) as a
measure-first follow-up for large plugins.
Assisted-by: Claude Opus 4.8 (via Claude Code)
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Copy file name to clipboardExpand all lines: docs/plugins/using-plugins.mdx
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,21 +64,21 @@ The plugin cache is shared across pipelines and is not access-controlled. On mul
64
64
65
65
<AddedInVersionversion="26.07" />
66
66
67
-
A `plugins.lock` file pins the exact plugin artifacts a pipeline expects. For each plugin it records the`sha512`checksum of the plugin archive, keyed by `id@version`. The file is meant to be committed to the pipeline repository so that everyone running the pipeline resolves the same plugin artifacts.
67
+
A `plugins.lock` file pins the exact plugin code a pipeline expects. For each plugin it records a`sha512`hash of the **extracted plugin directory** — the code Nextflow actually loads and runs — keyed by `id@version`. The file is meant to be committed to the pipeline repository so that everyone running the pipeline executes the same plugin code.
68
68
69
69
The lockfile is populated automatically, like `go.sum` or `package-lock.json` — there is no separate command. To enable it, create an empty file in the pipeline directory and run the pipeline once:
70
70
71
71
```bash
72
72
touch plugins.lock
73
73
```
74
74
75
-
The first time each plugin is downloaded, its archive checksum is added to `plugins.lock`. Review the resulting file and commit it. On subsequent runs Nextflow verifies each pluginagainst the committed checksum. When no `plugins.lock` file is present, the feature is dormant and has no effect.
75
+
The first time each plugin is loaded, its hash is added to `plugins.lock`. Review the resulting file and commit it. On subsequent runs Nextflow re-hashes each plugin's extracted directory and verifies it against the committed hash. When no `plugins.lock` file is present, the feature is dormant and has no effect.
76
76
77
-
Verification is fully offline: Nextflow re-computes the checksum of the plugin archive from a copy retained in the local cache and compares it to the lock entry, without contacting the plugin registry. An existing entry is never rewritten automatically — if a plugin archive legitimately changes, delete its entry and run again to re-pin it.
77
+
Verification is fully offline — it re-hashes the files already in the local cache and never contacts the plugin registry. Because it hashes the extracted code rather than the download, it detects both a tampered or compromised download and a plugin directory that was modified after extraction (for example by another user on a shared cache), independently of file ownership or permissions. An existing entry is never rewritten automatically — if a plugin legitimately changes, delete its entry and run again to re-pin it.
78
78
79
-
Use [`NXF_PLUGINS_LOCK_MODE`][using-plugins-env-vars] to control what happens on a checksum mismatch: `warn` (default) logs a warning and continues, `strict` aborts the run, and `off` skips verification. A plugin whose retained archive is missing (for example, a cache populated before this feature existed) cannot be verified offline; it is reported but never aborts the run, and is never re-downloaded just to verify it.
79
+
Use [`NXF_PLUGINS_LOCK_MODE`][using-plugins-env-vars] to control what happens on a mismatch: `warn` (default) logs a warning and continues, `strict` aborts the run, and `off` skips verification.
80
80
81
-
The lockfile complements, but does not replace, the private-cache guidance above: the cache isolation prevents untrusted artifacts from being loaded, while the lockfile ensures the artifacts that are loaded match what the pipeline pinned.
81
+
The lockfile complementsthe private-cache guidance above: keeping the cache private prevents untrusted code from being written in the first place, while the lockfile detects any change to the plugin code that is actually loaded.
Copy file name to clipboardExpand all lines: docs/reference/env-vars.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -214,7 +214,7 @@ The path where the plugin archives are loaded and stored (default: `$NXF_HOME/pl
214
214
215
215
<AddedInVersionversion="26.07" />
216
216
217
-
Controls how Nextflow reacts when a downloaded plugin artifact does not match the entry recorded in the `plugins.lock` file: `warn` logs a warning once per plugin and continues, `strict` aborts the run, and `off` skips verification silently (default: `warn`). Verification is dormant when no `plugins.lock` file is present.
217
+
Controls how Nextflow reacts when a plugin's extracted directory does not match the hash recorded in the `plugins.lock` file: `warn` logs a warning once per plugin and continues, `strict` aborts the run, and `off` skips verification silently (default: `warn`). Verification is dormant when no `plugins.lock` file is present.
0 commit comments