feat: sign releases and publish SBOMs#33
Conversation
| cosign) | ||
| VERSION="${COSIGN_VERSION:-v3.0.6}" | ||
| URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/cosign-${OS_NAME}-${ARCH_NAME}" | ||
| download "${URL}" "${INSTALL_DIR}/cosign" | ||
| chmod +x "${INSTALL_DIR}/cosign" |
There was a problem hiding this comment.
cosign binary downloaded without integrity verification
The cosign binary is fetched over HTTPS and made executable immediately, with no checksum or signature check. If the GitHub release asset is tampered with or the CDN is compromised, the binary used to sign every subsequent release artifact would be malicious — undermining the entire signing chain. Sigstore publishes cosign-checksums.txt alongside each release; verifying the SHA-256 of the downloaded binary against that file (or a pinned hash in this repo) would close this gap.
| cosign) | |
| VERSION="${COSIGN_VERSION:-v3.0.6}" | |
| URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/cosign-${OS_NAME}-${ARCH_NAME}" | |
| download "${URL}" "${INSTALL_DIR}/cosign" | |
| chmod +x "${INSTALL_DIR}/cosign" | |
| cosign) | |
| VERSION="${COSIGN_VERSION:-v3.0.6}" | |
| CHECKSUM_URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/cosign-checksums.txt" | |
| BINARY="cosign-${OS_NAME}-${ARCH_NAME}" | |
| URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/${BINARY}" | |
| download "${URL}" "${TMP_DIR}/${BINARY}" | |
| download "${CHECKSUM_URL}" "${TMP_DIR}/cosign-checksums.txt" | |
| (cd "${TMP_DIR}" && grep "${BINARY}" cosign-checksums.txt | sha256sum --check --status) | |
| cp "${TMP_DIR}/${BINARY}" "${INSTALL_DIR}/cosign" | |
| chmod +x "${INSTALL_DIR}/cosign" | |
| ;; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/release/install-tool.sh
Line: 50-54
Comment:
**cosign binary downloaded without integrity verification**
The cosign binary is fetched over HTTPS and made executable immediately, with no checksum or signature check. If the GitHub release asset is tampered with or the CDN is compromised, the binary used to sign every subsequent release artifact would be malicious — undermining the entire signing chain. Sigstore publishes `cosign-checksums.txt` alongside each release; verifying the SHA-256 of the downloaded binary against that file (or a pinned hash in this repo) would close this gap.
```suggestion
cosign)
VERSION="${COSIGN_VERSION:-v3.0.6}"
CHECKSUM_URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/cosign-checksums.txt"
BINARY="cosign-${OS_NAME}-${ARCH_NAME}"
URL="https://github.com/sigstore/cosign/releases/download/${VERSION}/${BINARY}"
download "${URL}" "${TMP_DIR}/${BINARY}"
download "${CHECKSUM_URL}" "${TMP_DIR}/cosign-checksums.txt"
(cd "${TMP_DIR}" && grep "${BINARY}" cosign-checksums.txt | sha256sum --check --status)
cp "${TMP_DIR}/${BINARY}" "${INSTALL_DIR}/cosign"
chmod +x "${INSTALL_DIR}/cosign"
;;
```
How can I resolve this? If you propose a fix, please make it concise.| - apk add --no-cache bash curl openssh-client rsync git gnupg github-cli | ||
| - apk add --no-cache bash curl openssh-client rsync git github-cli | ||
| - curl -Ls https://cli.doppler.com/install.sh | sh | ||
| - | |
There was a problem hiding this comment.
curl | sh installer runs before signing secrets are injected
curl -Ls https://cli.doppler.com/install.sh | sh executes an unverified remote script in the same shell session that subsequently calls doppler run ... -- bash scripts/release/sign-release-assets.sh. A compromised or MITMed installer could plant a doppler shim on PATH or create bash hooks that exfiltrate COSIGN_PRIVATE_KEY and COSIGN_PASSWORD the moment doppler run injects them. The same pattern appears in the smoke-published-release step (line ~53). Pinning the Doppler CLI to a known version and verifying its checksum before execution, or pre-baking it into the CI image, would remove this risk.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .woodpecker.yml
Line: 33
Comment:
**`curl | sh` installer runs before signing secrets are injected**
`curl -Ls https://cli.doppler.com/install.sh | sh` executes an unverified remote script in the same shell session that subsequently calls `doppler run ... -- bash scripts/release/sign-release-assets.sh`. A compromised or MITMed installer could plant a `doppler` shim on `PATH` or create bash hooks that exfiltrate `COSIGN_PRIVATE_KEY` and `COSIGN_PASSWORD` the moment `doppler run` injects them. The same pattern appears in the `smoke-published-release` step (line ~53). Pinning the Doppler CLI to a known version and verifying its checksum before execution, or pre-baking it into the CI image, would remove this risk.
How can I resolve this? If you propose a fix, please make it concise.
Summary
Testing
Closes #27
Greptile Summary
This PR introduces SBOM generation (via Syft, SPDX JSON format) for each release archive and the source tree, detached Cosign signatures for archives, SBOMs, and
SHA256SUMS, and publishes the release public key (profitctl-release-cosign.pub) to GitHub Releases. The Woodpecker pipeline gainsgenerate-sboms.sh,sign-release-assets.sh, and asmoke-published-releasestage that downloads and re-verifies the published artifacts end-to-end.Confidence Score: 4/5
Do not merge until the cosign bootstrap verification and the curl | sh signing-step risk are addressed.
Two P1 security findings: the cosign binary is used to sign every release artifact yet is itself fetched without any integrity check, and the Doppler CLI installer runs as an unverified remote script immediately before signing secrets are injected. Either issue could silently compromise the release signing chain. The remaining finding is P2 style.
scripts/release/install-tool.sh (cosign download, lines 50–54) and .woodpecker.yml (curl | sh in publish and smoke steps)
Security Review
install-tool.sh, lines 50–54): Thecosignbinary is downloaded from GitHub and made executable without checksum verification. Compromise of this binary would silently invalidate the entire signing chain.curl | shin privileged CI steps (.woodpecker.yml, lines 33 and ~53): The Doppler CLI installer runs as an unverified remote script immediately before signing secrets are injected, creating a PATH-shim / hook injection vector for credential exfiltration.Important Files Changed
gh release upload; two early-exit error messages are missing the>&2redirect, inconsistent with the rest of the codebase..gitanddistdirectories.Sequence Diagram
sequenceDiagram participant WP as Woodpecker CI participant BA as build-and-package step participant PV as publish-release-and-vps step participant SM as smoke-published-release step participant GH as GitHub Releases WP->>BA: trigger on tag v*.*.* BA->>BA: install-tool.sh syft BA->>BA: build-artifacts.sh BA->>BA: create-checksums.sh (SHA256SUMS) BA->>BA: generate-sboms.sh (*.spdx.json) WP->>PV: artifacts passed via dist/TAG/ PV->>PV: install-tool.sh cosign PV->>PV: doppler run → sign-release-assets.sh Note over PV: signs *.tar.gz, *.zip, *.spdx.json, SHA256SUMS PV->>GH: publish-github-release.sh WP->>SM: after publish SM->>SM: install-tool.sh cosign SM->>GH: gh release download SM->>SM: verify-release-assets.sh SM->>SM: extract + smoke test binary SM-->>WP: smoke passedComments Outside Diff (1)
scripts/release/publish-github-release.sh, line 6-12 (link)Both early-exit
echocalls write to stdout instead of stderr, which is inconsistent with every other error message in the release scripts and breaks any caller that redirects stdout.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat: sign releases and publish sboms" | Re-trigger Greptile