Skip to content

feat: harden self-update trust with cosign-signed checksum manifest#144

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/harden-self-update-trust
Draft

feat: harden self-update trust with cosign-signed checksum manifest#144
Copilot wants to merge 4 commits intomainfrom
copilot/harden-self-update-trust

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 11, 2026

bb update trusted sha256sums.txt without authentication — an attacker who could swap release artifacts could also swap the checksum file, defeating the integrity check entirely.

Changes

Release pipeline

  • Installs cosign via sigstore/cosign-installer@v3
  • After generating sha256sums.txt, signs it with cosign sign-blob --key using a COSIGN_PRIVATE_KEY Actions secret
  • Uploads sha256sums.txt.sig as an additional release artifact

Updater (runner.go)

  • Embeds an ECDSA P-256 public key (embeddedCosignPublicKeyPEM) compiled into the binary
  • Update flow is now: find sha256sums.txt.sig → download → verify ECDSA signature against embedded key → only then parse and trust the checksum file
  • verifyChecksumSignature() uses only Go stdlib (crypto/ecdsa, crypto/x509, encoding/pem) — no new dependencies
  • Result gains SignatureAssetName/SignatureVerified; human output shows signature sha256sums.txt.sig (verified)
  • Dependencies.ChecksumPublicKeyPEM allows tests to inject a test key without touching the embedded constant

Tests

  • New testKeyPair helper generates fresh ECDSA P-256 key pairs and produces cosign-format signatures inline
  • All update-path test cases updated to carry sha256sums.txt.sig assets and valid signatures
  • New TestVerifyChecksumSignature covers: valid, wrong key, tampered content, malformed base64, invalid PEM
  • New runner error cases: missing_signature_asset, signature_download_failure, invalid_signature, malformed_signature

Setup required

Two Actions secrets must be configured to activate signing:

Secret Value
COSIGN_PRIVATE_KEY EC private key PEM (standard or cosign-encrypted)
COSIGN_PASSWORD Passphrase (leave empty for unencrypted keys)

The embeddedCosignPublicKeyPEM constant in runner.go must match the private key used in CI. To rotate: generate a new key pair, update the constant, update the secret, cut a release.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • invalid-url-that-does-not-exist.local
    • Triggering command: /tmp/go-build479556031/b355/hook.test /tmp/go-build479556031/b355/hook.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 go_.�� ache/go/1.24.13/x64/src/os/user .cfg ate.test =0,multipathtcp=git nternal/cli/cmd/rev-parse SPGCdsl/0qV5eYI5--show-toplevel ate.test ache�� /opt/hostedtoolcache/go/1.24.13/x64/src/runtime/--log-target 1868047/b175/ ux_amd64/vet -pthread -Wl,--no-gc-sectrev-parse -fmessage-length--show-toplevel ux_amd64/vet (dns block)
  • login-json.local
    • Triggering command: /tmp/go-build479556031/b302/auth.test /tmp/go-build479556031/b302/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 conf�� x64/src/os/user _MHy/2B4ahMNRoA9-nolocalimports ux_amd64/vet (dns block)
    • Triggering command: /tmp/go-build803342620/b304/auth.test /tmp/go-build803342620/b304/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 _ _ _ _ _ _ --print-diagnostics-summary --print-metrics-summary -o /tmp/go-build862652771/b118/_pkg_.a -trimpath x64/pkg/tool/linux_amd64/compile -p github.com/mark3-f -lang=go1.23 x64/pkg/tool/linux_amd64/compile (dns block)
    • Triggering command: /tmp/go-build3404619558/b304/auth.test /tmp/go-build3404619558/b304/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 remo�� 2145bea0:internal/cli/update.go k/bitbucket-server-cli/bitbucket-server-cli/internal/services/reposettings/service_test.go /usr/bin/git REDACTED -nolocalimports -importcfg git rev-�� --show-toplevel /home/REDACTED/work/bitbucket-server-cli/bitbucket-server-cli/internal/mcp/tools_branch.go git x64/src/net mxfl/fl1TLN58PjN-c /usr/local/.ghcugit status --porcelain --ignore-submodules | head -n 10 /opt/hostedtoolcache/go/1.24.13/x64/pkg/tool/linux_amd64/vet (dns block)
  • resolved.local
    • Triggering command: /tmp/go-build479556031/b302/auth.test /tmp/go-build479556031/b302/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 conf�� x64/src/os/user _MHy/2B4ahMNRoA9-nolocalimports ux_amd64/vet (dns block)
    • Triggering command: /tmp/go-build803342620/b304/auth.test /tmp/go-build803342620/b304/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 _ _ _ _ _ _ --print-diagnostics-summary --print-metrics-summary -o /tmp/go-build862652771/b118/_pkg_.a -trimpath x64/pkg/tool/linux_amd64/compile -p github.com/mark3-f -lang=go1.23 x64/pkg/tool/linux_amd64/compile (dns block)
    • Triggering command: /tmp/go-build3404619558/b304/auth.test /tmp/go-build3404619558/b304/auth.test -test.paniconexit0 -test.timeout=10m0s -test.count=1 remo�� 2145bea0:internal/cli/update.go k/bitbucket-server-cli/bitbucket-server-cli/internal/services/reposettings/service_test.go /usr/bin/git REDACTED -nolocalimports -importcfg git rev-�� --show-toplevel /home/REDACTED/work/bitbucket-server-cli/bitbucket-server-cli/internal/mcp/tools_branch.go git x64/src/net mxfl/fl1TLN58PjN-c /usr/local/.ghcugit status --porcelain --ignore-submodules | head -n 10 /opt/hostedtoolcache/go/1.24.13/x64/pkg/tool/linux_amd64/vet (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI and others added 3 commits April 11, 2026 19:15
- Add ECDSA P-256 public key embedded in binary (embeddedCosignPublicKeyPEM)
- Add verifyChecksumSignature() using Go stdlib crypto/ecdsa; no new deps
- Runner now downloads sha256sums.txt.sig and verifies it before trusting checksums
- Result struct gains SignatureAssetName/SignatureVerified fields
- Human output shows signature verification status
- Release workflow installs cosign and signs sha256sums.txt → sha256sums.txt.sig
- Tests updated: new key-pair helpers, all update paths include signature assets

Agent-Logs-Url: https://github.com/vriesdemichael/bitbucket-server-cli/sessions/052ffbeb-281e-414d-bb15-39b44f9d4c46

Co-authored-by: vriesdemichael <9072548+vriesdemichael@users.noreply.github.com>
Co-authored-by: vriesdemichael <9072548+vriesdemichael@users.noreply.github.com>
Copilot AI changed the title [WIP] Harden self-update trust with signed checksum manifest feat: harden self-update trust with cosign-signed checksum manifest Apr 11, 2026
Copilot AI requested a review from vriesdemichael April 11, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden self-update trust with signed checksum manifest

2 participants