doc: pass the manifest explicitly to gpg --verify
What changed, and why it matters
This commit updates Core Lightning's release documentation to tell users and release managers to run gpg --verify with both the signature file and the manifest file named explicitly. The old one-argument form can silently succeed even if the .asc file is not a proper detached signature over the manifest, because gpg may verify only a message embedded inside the .asc file and never check SHA256SUMS. The change prevents a subtle but real verification bypass in the release process, though it is a documentation-only fix and does not change any code or tooling.
Merge the documentation change. Consider also updating any release scripts or CI templates that invoke gpg --verify to pass the manifest explicitly, and add a note to the next release announcement so users who verify binaries manually adopt the safer command.
Security signals we found
Verification bypass risk in release artifact validation
gpg --verify single-argument form can exit 0 without reading the intended manifest
Documentation-only hardening of release process
Social/operational attack surface: tricking maintainers or users into accepting a malformed .asc file
Evidence from the diff
The patch changes two Markdown documents that describe the release and reproducible-build verification workflow. Previously the instructions used gpg –verify SHA256SUMS.asc, which lets gpg infer the signed file. If the .asc file is an inline/clear-signed message rather than a detached signature, gpg verifies the embedded payload, prints a stderr warning, and exits 0 without ever reading SHA256SUMS. The new instructions pass SHA256SUMS as the second argument, forcing gpg to verify the detached signature against that exact file and fail if the .asc is not a detached signature over it. The commit also removes the sample output line gpg: assuming signed data in ‘SHA256SUMS’ because that assumption no longer occurs. No source code, build scripts, or cryptographic checks are modified.
Changed components
doc/contribute-to-core-lightning/release-checklist.mddoc/getting-started/advanced-setup/repro.mdInspect captured patch +9 / −6
### doc/contribute-to-core-lightning/release-checklist.md
@@ -82,7 +82,7 @@ Here's a checklist for the release process.
- Run `tools/build-release.sh --verify`. It will create reproducible images, verify checksums and sign.
- Send your signatures from `release/SHA256SUMS-v<VERSION>.asc` to release captain.
- Or follow [link](https://docs.corelightning.org/docs/repro#verifying-a-reproducible-build) for manual verification instructions.
-12. Append signatures shared by the team into the `SHA256SUMS-v<VERSION>.asc` file, verify with `gpg --verify SHA256SUMS-v<VERSION>.asc` and include the file in the draft release.
+12. Append signatures shared by the team into the `SHA256SUMS-v<VERSION>.asc` file, verify with `gpg --verify SHA256SUMS-v<VERSION>.asc SHA256SUMS-v<VERSION>` (always pass the manifest as the second argument, otherwise `gpg` may verify a payload embedded in the `.asc` and exit successfully without ever reading the checksums) and include the file in the draft release.
13. The GitHub action `Publish Python 🐍 distributions 📦 to PyPI and TestPyPI` should upload the pyln modules to pypi.org. However, this can also be done manually by running `uv run make pyln-release`. This process requires keys for each of the `pyln-client`, `pyln-proto`, and `pyln-testing` modules to be accessible to uv. You can set the key as an environment variable and build and publish each pyln release independently:
- `export UV_PUBLISH_TOKEN=<pyln-client token>`
- `uv run make pyln-release-client`
@@ -124,7 +124,7 @@ Here's a checklist for the release process.
10. Sign the release locally by running `tools/build-release.sh bin-Fedora bin-Ubuntu sign` which will sign the release contents and create `SHA256SUMS-v<VERSION>` and `SHA256SUMS-v<VERSION>.asc` in the release folder.
11. Validate that your local checksums `SHA256SUMS-v<VERSION>` match the Draft release's, then add your signatures to the draft release's signature `SHA256SUMS-v<VERSION>.asc` file.
12. Share the `SHA256SUMS-v<VERSION>` and `SHA256SUMS-v<VERSION>.asc` files with the team for verification and signing.
-13. Append the signatures received from the team to the `SHA256SUMS-v<VERSION>.asc` file. Verify the file using `gpg --verify SHA256SUMS-v<VERSION>.asc`. Then re-upload the file.
+13. Append the signatures received from the team to the `SHA256SUMS-v<VERSION>.asc` file. Verify the file using `gpg --verify SHA256SUMS-v<VERSION>.asc SHA256SUMS-v<VERSION>`; the manifest must be passed as the second argument, otherwise `gpg` may verify a payload embedded in the `.asc` and exit successfully without ever reading the checksums. Then re-upload the file.
14. Finalize and publish the release (change it from draft to public).
15. Ensure that the GitHub Actions for `Publish Python 🐍 distributions 📦 to PyPI and TestPyPI` and `Build and push multi-platform docker images` are functioning correctly. Check that the `PyPI` modules published on `https://pypi.org/project/pyln-*` and that the Docker image has been uploaded to Docker Hub.
16. Create a PR to merge updates from `update-versions` and `CHANGELOG.md` into `master` to keep it up-to-date for the next release.
### doc/getting-started/advanced-setup/repro.md
@@ -148,11 +148,13 @@ gpg -sb --armor SHA256SUMS
4. Then send the resulting `release/SHA256SUMS.asc` file to the release captain so it can be merged with the other signatures into `SHASUMS.asc`.
## Manual
-Co-maintainers and contributors wishing to add their own signature verify that the `SHA256SUMS` and `SHA256SUMS.asc` files created by the release captain matches their binaries before also signing the manifest:
+Co-maintainers and contributors wishing to add their own signature verify that the `SHA256SUMS` and `SHA256SUMS.asc` files created by the release captain matches their binaries before also signing the manifest.
+
+Always pass **both** files to `gpg --verify`: the signature first, then the file it is supposed to cover. See [Verifying a reproducible build](#verifying-a-reproducible-build) below for why the single-argument form is not sufficient.
```shell
cd release/
-gpg --verify SHA256SUMS.asc
+gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum -c SHA256SUMS
cat SHA256SUMS | gpg -sb --armor > SHA256SUMS.new
```
@@ -169,13 +171,14 @@ You can verify the reproducible build in two ways:
Assuming you have downloaded the binaries, the manifest and the signatures into the same directory, you can verify the signatures with the following:
```shell
-gpg --verify SHA256SUMS.asc
+gpg --verify SHA256SUMS.asc SHA256SUMS
```
+Pass both filenames explicitly. With a single argument `gpg` picks its verification mode from the packet structure of the `.asc` file: for a genuine detached signature it guesses the sibling `SHA256SUMS`, but for an inline (clear-signed or embedded) message it verifies only the payload carried inside the `.asc` itself. It never reads `SHA256SUMS` in that case, and although it prints `WARNING: not a detached signature; file 'SHA256SUMS' was NOT verified!`, it still exits with status 0 — so the warning is easy to miss by eye and invisible to any script that only checks the exit code. Naming the manifest as the second argument forces `gpg` to check the signatures against that exact file, and to fail outright if the `.asc` is not a detached signature over it.
+
And you should see a list of messages like the following:
```shell
-gpg: assuming signed data in 'SHA256SUMS'
gpg: Signature made Fr 08 Mai 2020 07:46:38 CEST
gpg: using RSA key 15EE8D6CAB0E7F0CF999BFCBD9200E6CD1ADB8F1
gpg: Good signature from "Rusty Russell <rusty@rustcorp.com.au>" [full]Why this scored 42/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.