hashicorp/packer · error

bundle-based Rekor or timestamp verification requires keyles

Error message

bundle-based Rekor or timestamp verification requires keyless_identity and keyless_oidc_issuer

What it means

Keyless bundle verification must check the expected OIDC identity and issuer against the Fulcio certificate. This error means cfg.KeylessIdentity or cfg.KeylessOIDCIssuer is empty while bundle-based keyless verification was requested.

Source

Thrown at internal/attestation/verify.go:290

	return &statement, nil
}

func requiresSigstoreBundle(policy VerificationPolicy) bool {
	return policy.RequireTransparencyLog || policy.RequireObserverTimestamp
}

func verifySigstoreBundleEvidenceImpl(envelope Envelope, cfg BackendConfig, policy VerificationPolicy) error {
	if strings.TrimSpace(policy.SigstoreBundlePath) == "" {
		return fmt.Errorf("bundle-based Rekor or timestamp verification requires -bundle")
	}

	if normalizeVerificationMode(cfg, envelope) != SigningModeKeyless && !envelopeHasCertificate(envelope) {
		return fmt.Errorf("bundle-based Rekor or timestamp verification currently requires a keyless attestation")
	}

	if strings.TrimSpace(cfg.KeylessIdentity) == "" || strings.TrimSpace(cfg.KeylessOIDCIssuer) == "" {
		return fmt.Errorf("bundle-based Rekor or timestamp verification requires keyless_identity and keyless_oidc_issuer")
	}

	trustedMaterial, err := loadKeylessTrustedMaterial(cfg)
	if err != nil {
		return fmt.Errorf("load keyless trusted root: %w", err)
	}

	bundle, err := loadSigstoreBundle(policy.SigstoreBundlePath)
	if err != nil {
		return fmt.Errorf("load Sigstore bundle %q: %w", policy.SigstoreBundlePath, err)
	}

	if err := ensureBundleMatchesEnvelope(bundle, envelope); err != nil {
		return err
	}

	verifierOptions := []sigstoreverify.VerifierOption{}
	if policy.RequireTransparencyLog {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Set both cfg.KeylessIdentity (expected SAN identity) and cfg.KeylessOIDCIssuer (expected OIDC issuer URL) before verification.
  2. For GitHub Actions, use the identity from the token (e.g. repo owner/repo ref) and issuer https://token.actions.githubusercontent.com.
  3. Double-check for whitespace-only values; the check trims strings, so " " still counts as missing.
  4. If the certificate allows multiple identities (SAN extensions), configure the identity option that matches how it was signed.

Example fix

// before
cfg := BackendConfig{Mode: SigningModeKeyless} // identity/issuer missing
// after
cfg := BackendConfig{Mode: SigningModeKeyless, KeylessIdentity: "https://github.com/org/repo/.github/workflows/release.yml@refs/tags/v1.0.0", KeylessOIDCIssuer: "https://token.actions.githubusercontent.com"}
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(cfg.KeylessIdentity) == "" || strings.TrimSpace(cfg.KeylessOIDCIssuer) == "" {
	return fmt.Errorf("keyless_identity and keyless_oidc_issuer must be set for bundle verification")
}

Try / catch

err := VerifyAttestation(...)
if err != nil && strings.Contains(err.Error(), "requires keyless_identity and keyless_oidc_issuer") {
	// surface a config error telling the user which flags to set
}

Prevention

When it happens

Trigger: verifySigstoreBundleEvidenceImpl invoked with a keyless (or certificate-bearing) envelope and a bundle path, but BackendConfig.KeylessIdentity and/or KeylessOIDCIssuer left unset.

Common situations: Forgetting to pass keyless_identity/keyless_oidc_issuer flags or config fields; CI tokens from a new provider whose issuer URL was never configured; partially migrated verification configs after switching from key to keyless signing.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/60fc5111b21683fb. Report an issue: GitHub.