hashicorp/packer · error

static certificate provider is missing a certificate

Error message

static certificate provider is missing a certificate

What it means

staticCertificateProvider.GetCertificate returns this when its certDER field is empty. The provider exists to replay an already-issued Fulcio certificate into sigstore-go's Bundle call instead of requesting a new one; an empty DER means the signer was constructed without a certificate. It is an internal invariant guard, so users hitting it directly indicates a misconstructed signer or provider.

Source

Thrown at internal/attestation/sign_keyless.go:296

		certificate, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("parse keyless certificate: %w", err)
		}

		return certificate, nil
	}

	return nil, fmt.Errorf("keyless attestation does not contain a signing certificate")
}

type staticCertificateProvider struct {
	certDER []byte
}

func (p staticCertificateProvider) GetCertificate(context.Context, sigstoregosign.Keypair, *sigstoregosign.CertificateProviderOptions) ([]byte, error) {
	if len(p.certDER) == 0 {
		return nil, fmt.Errorf("static certificate provider is missing a certificate")
	}

	return append([]byte(nil), p.certDER...), nil
}

func resolveAmbientIDToken(ctx context.Context, env map[string]string) (string, error) {
	if token := strings.TrimSpace(env["SIGSTORE_ID_TOKEN"]); token != "" {
		return token, nil
	}
	if token := strings.TrimSpace(env["CI_JOB_JWT_V2"]); token != "" {
		return token, nil
	}
	if token := strings.TrimSpace(env["CI_JOB_JWT"]); token != "" {
		return token, nil
	}
	if token, err := resolveGitHubActionsIDToken(ctx, env); err == nil && token != "" {
		return token, nil
	}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure the signer is created via newKeylessSigner, which requests and parses the Fulcio certificate before any SignBundle call.
  2. Check that the Fulcio GetCertificate step did not silently return empty bytes in a custom newKeylessFulcio override.
  3. If constructing staticCertificateProvider directly, pass the non-empty cert.Raw DER bytes.
  4. Add a pre-flight check that the signer's certificate is non-nil before bundling.

Example fix

// before
provider := staticCertificateProvider{} // empty
// after
if len(certDER) == 0 {
    return fmt.Errorf("no Fulcio certificate available for bundling")
}
provider := staticCertificateProvider{certDER: certDER}
Defensive patterns

Strategy: validation

Validate before calling

if signer == nil || signer.cert == nil || len(signer.cert.Raw) == 0 {
    return fmt.Errorf("keyless signer has no Fulcio certificate; construct via newKeylessSigner")
}

Type guard

func signerReady(s *keylessSigner) bool {
    return s != nil && s.cert != nil && len(s.cert.Raw) > 0
}

Try / catch

envelope, _, err := signer.SignBundle(ctx, payloadType, payload, cfg)
if err != nil && strings.Contains(err.Error(), "static certificate provider is missing") {
    return fmt.Errorf("signer was not initialized with a Fulcio certificate: %w", err)
}

Prevention

When it happens

Trigger: Calling SignBundle (which passes staticCertificateProvider{certDER: s.cert.Raw}) on a keylessSigner whose cert was never parsed/set, or directly constructing staticCertificateProvider with a nil/empty certDER slice.

Common situations: Zero-value keylessSigner used outside newKeylessSigner; a refactoring that reordered Fulcio certificate retrieval; tests constructing the provider manually with no bytes.

Understand the failure class

Related errors


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