Skip to content

Restore detached signatures, broken by a cosign default - #393

Merged
fstubner merged 1 commit into
mainfrom
fix/cosign-sidecar-signing
Sep 11, 2026
Merged

Restore detached signatures, broken by a cosign default#393
fstubner merged 1 commit into
mainfrom
fix/cosign-sidecar-signing

Conversation

@fstubner

Copy link
Copy Markdown
Owner

All 15 matrix legs of the v0.3.1 release failed at signing, on every platform, before a single asset was uploaded.

Flag --output-signature has been deprecated, please use --bundle
WARNING: --output-signature is deprecated when using --new-bundle-format
Error: signing netscli-linux-x86_64: create bundle file: open : no such file or directory

Note the empty path. --new-bundle-format defaults to true in cosign v3. With it on, cosign ignores --output-signature and --output-certificate and writes a single bundle to --bundle instead — which nothing here sets. So it opened the empty string and died, uniformly.

Nothing in this repo caused it

Dependabot moved sigstore/cosign-installer from @v3 to @v4.1.2 in #166. The action default cosign-release moved with it, from cosign v2.5.2 to v3.0.6. The action version and the cosign version are different things, and only the former appeared in the diff. No release was cut between that bump and v0.3.1, so the first time the new binary ever ran was the release itself.

The fix

Both sign steps, CLI and GUI:

Change Why
--new-bundle-format=false Restores v2 behaviour. Confirmed against v3.0.6 sign_blob.go: the bundle write is guarded by if ko.BundlePath != "", detached files are written under their own checks, so with no --bundle it takes the sidecar path.
cosign-release: v3.0.6 Pins the binary explicitly, so signing format stops depending on an installer default that already changed under us once without appearing in a diff.

Why sidecars, not bundles

.sig + .pem are what packaging/README.md and the published install guide tell people to pass to cosign verify-blob, and v0.2.6 shipped 64 assets as .sha256/.sig/.pem triples. Migrating to the bundle format is defensible but rewrites published verification instructions — its own change, not an incident fix.

Verification

cosign is not installed locally, so CI on this PR proves nothingrelease.yml is not exercised by it. The proof is re-dispatching the release. Verified statically instead: YAML parses, both sign-blob calls carry the flag, both installers carry the pin, and the diff is those six non-comment lines and nothing else.

Current state

v0.3.1 is public, tagged, marked latest, notes intact — and has zero assets. The registry fan-out never ran, so crates.io, AUR, Homebrew, Scoop and winget are all still untouched.

Every one of the 15 matrix legs in the v0.3.1 release failed at signing,
on every platform, with:

  Flag --output-signature has been deprecated, please use --bundle
  WARNING: --output-signature is deprecated when using --new-bundle-format
  Error: signing netscli-linux-x86_64: create bundle file: open : no such
         file or directory

Note the empty path. `--new-bundle-format` defaults to TRUE in cosign v3.
With it on, cosign ignores --output-signature and --output-certificate and
writes a single bundle to --bundle instead -- which nothing here sets. So
it opened the empty string and died, uniformly, before a single asset was
uploaded.

Nothing in this repository changed to cause it. Dependabot moved
sigstore/cosign-installer from @V3 to @v4.1.2 in #166, and the action's
default `cosign-release` moved with it, from cosign v2.5.2 to v3.0.6. The
action version and the cosign version are different things and only the
former appeared in the diff. No release was cut between that bump and
v0.3.1, so the first time the new binary ever ran was the release itself.

Two changes, both to release.yml, in both the CLI and GUI sign steps:

  --new-bundle-format=false   restores the v2 behaviour. Confirmed against
                              v3.0.6's sign_blob.go: the bundle write is
                              guarded by `if ko.BundlePath != ""`, and the
                              detached files are written under their own
                              checks, so with no --bundle it takes the
                              sidecar path.

  cosign-release: v3.0.6      pins the binary explicitly, so the signing
                              format stops depending on an installer
                              default that already changed under us once
                              without appearing in a diff.

Sidecars are kept rather than migrating to bundles because `.sig` + `.pem`
are what packaging/README.md and the published install guide tell people
to pass to `cosign verify-blob`, and v0.2.6 shipped 64 assets as
.sha256/.sig/.pem triples. Moving to the bundle format is defensible, but
it rewrites published verification instructions and belongs in its own
change, not in an incident fix.

Not verified locally: cosign is not installed here, so CI is the only
proof. Verified statically instead -- YAML parses, both sign-blob calls
carry the flag, both installers carry the pin, and the diff touches
nothing but those six lines.
@fstubner
fstubner merged commit ab467ed into main Sep 11, 2026
15 checks passed
fstubner added a commit that referenced this pull request Sep 11, 2026
…395)

#393 diagnosed the v0.3.1 signing failure as cosign v3's bundle-format
default and set `--new-bundle-format=false`. That was wrong, and the
re-dispatched release failed at the same step on every leg that reached
it:

  Error: must provide --new-bundle-format or --bundle where applicable
  with --signing-config or --use-signing-config

The gate is signcommon/common.go at v3.0.6, lines 660-661:

  if (useSigningConfig || signingConfigPath != "") &&
      !newBundleFormat && bundlePath == "" {
    return fmt.Errorf("must provide --new-bundle-format or --bundle ...")

It needs both halves false. `--new-bundle-format=false` satisfies one and
leaves `useSigningConfig` standing, which defaults to TRUE in v3
(options/signblob.go:111). So the real v3 change behind this was the
signing config defaulting on, not the bundle format.

Add `--use-signing-config=false` to both sign steps. It is the only gate
that applies: the neighbouring checks at :649 (service URLs) and :656
(tlog-upload) also require a signing config, and the checks at :693-708
all require newBundleFormat true, which stays false here.

`--new-bundle-format=false` is kept on its own account -- with it true,
cosign writes a bundle to --bundle, unset here, instead of the detached
files.

Sidecar output is reachable with both off: sign_blob.go closes its
`if ko.BundlePath != ""` block at line 229, before the outputSignature
(231) and outputCertificate (250) writes. Read as code, not inferred from
a grep -- doing exactly that is how #393 shipped wrong.

Also rewrites both step comments, which stated the #393 diagnosis as fact
and would otherwise have preserved it in the file.

Not verified by CI: no CI job runs release.yml. The proof is a dispatch.
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.

1 participant