hashicorp/packer · error
decode keyless certificate: no PEM block found
Error message
decode keyless certificate: no PEM block found
What it means
certificateFromEnvelope iterates the envelope's signatures looking for one with a Cert field, and pem.Decode returned no block for the first non-empty Cert. This means the signature's certificate field is non-empty but is not valid PEM (missing -----BEGIN CERTIFICATE----- armor, base64-encoded instead of PEM-encoded, or corrupted). The function aborts instead of skipping to the next signature.
Source
Thrown at internal/attestation/sign_keyless.go:276
return err
}
return v.signatureVerifier.Verify(ctx, payloadType, payload, signature)
}
func (v *keylessVerifier) KeyID() string {
return v.signatureVerifier.KeyID()
}
func certificateFromEnvelope(envelope Envelope) (*x509.Certificate, error) {
for _, signature := range envelope.Signatures {
if strings.TrimSpace(signature.Cert) == "" {
continue
}
block, _ := pem.Decode([]byte(signature.Cert))
if block == nil {
return nil, fmt.Errorf("decode keyless certificate: no PEM block found")
}
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) {View on GitHub (pinned to eb36e3c3e4)
Solutions
- Ensure EnvelopeSignature.Cert is PEM-encoded (pem.EncodeToMemory of the DER bytes) before building the envelope.
- If the value is base64, decode it with base64.StdEncoding.DecodeString and then PEM-encode the DER.
- Regenerate the attestation from the original signer so the certificate is emitted in the canonical PEM form.
- Check the producing tool version for known certificate-format changes.
Example fix
// before
sig.Cert = base64.StdEncoding.EncodeToString(certDER)
// after
sig.Cert = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})) Defensive patterns
Strategy: validation
Validate before calling
func isPEMCertificate(s string) bool {
block, _ := pem.Decode([]byte(s))
return block != nil && block.Type == "CERTIFICATE"
}
// check every signature before calling newKeylessVerifierForEnvelope
for _, sig := range env.Signatures {
if strings.TrimSpace(sig.Cert) != "" && !isPEMCertificate(sig.Cert) {
return fmt.Errorf("signature cert is not PEM-encoded")
}
} Type guard
func firstPEMCertificate(sig []EnvelopeSignature) (string, bool) {
for _, s := range sig {
if strings.TrimSpace(s.Cert) == "" {
continue
}
block, _ := pem.Decode([]byte(s.Cert))
if block != nil && block.Type == "CERTIFICATE" {
return s.Cert, true
}
}
return "", false
} Try / catch
verifier, err := newKeylessVerifierForEnvelope(cfg, envelope)
if err != nil && strings.Contains(err.Error(), "no PEM block found") {
return fmt.Errorf("attestation certificate is not PEM-encoded; re-produce the attestation: %w", err)
} Prevention
- Always emit EnvelopeSignature.Cert via pem.EncodeToMemory, mirroring keylessSigner.SignBundle.
- Never store base64 DER directly in the Cert field; PEM-encode it.
- Round-trip test envelopes through certificateFromEnvelope in CI.
- Validate attestation JSON schema before verification.
When it happens
Trigger: newKeylessVerifierForEnvelope is called with an Envelope whose first signature with a non-empty Cert contains raw DER bytes, base64 text, or truncated PEM rather than PEM-encoded certificate text.
Common situations: Storing the certificate base64-encoded (from protobuf bundles) but forgetting to decode before placing it in EnvelopeSignature.Cert; hand-editing or truncating attestation JSON; an older producer version that emitted raw DER.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- load verifier %q: %w
- parse keyless certificate: %w
- read verifier %q: %w
- no PEM block found
- unsupported PEM verifier data
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/5a63d65d49aaf3a7.
Report an issue: GitHub.