hashicorp/packer · error

summarize Fulcio certificate: %w

Error message

summarize Fulcio certificate: %w

What it means

After chain and SCT checks pass, verifyKeylessCertificate calls fulciocertificate.SummarizeCertificate to extract the OIDC issuer and identity/san extensions from the Fulcio certificate. This error means the certificate is not a well-formed Fulcio certificate: the required extension fields that record the OIDC issuer or subject identity could not be parsed or are absent.

Source

Thrown at internal/attestation/sign_keyless.go:68

}

var verifyKeylessCertificate = func(certificate *x509.Certificate, trustedMaterial sigstoreroot.TrustedMaterial, expectedIdentity, expectedOIDCIssuer, trustedRootPath string) error {
	chains, err := sigstoreverify.VerifyLeafCertificate(time.Now().UTC(), certificate, trustedMaterial)
	if err != nil {
		return fmt.Errorf("verify Fulcio certificate chain: %w", err)
	}

	// When using the public Sigstore root (no custom trusted root configured),
	// require a valid SCT so certificates issued outside a public CT log are rejected.
	if strings.TrimSpace(trustedRootPath) == "" {
		if err := sigstoreverify.VerifySignedCertificateTimestamp(chains, 1, trustedMaterial); err != nil {
			return fmt.Errorf("verify Fulcio certificate SCT: %w", err)
		}
	}

	summary, err := fulciocertificate.SummarizeCertificate(certificate)
	if err != nil {
		return fmt.Errorf("summarize Fulcio certificate: %w", err)
	}

	identity, err := sigstoreverify.NewShortCertificateIdentity(expectedOIDCIssuer, "", expectedIdentity, "")
	if err != nil {
		return fmt.Errorf("build keyless identity policy: %w", err)
	}
	if err := identity.Verify(summary); err != nil {
		return fmt.Errorf("verify keyless certificate identity: %w", err)
	}

	return nil
}

func init() {
	RegisterSigner(SigningModeKeyless, newKeylessSigner)
}

type keylessSigner struct {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Verify the attestation was signed with a genuine Fulcio-issued certificate (inspect extensions: 'openssl x509 -in cert.pem -noout -ext 1.3.6.1.4.1.57264.1.1').
  2. Re-sign the artifact with keyless mode so a fresh, correctly-issued Fulcio certificate is produced.
  3. Confirm the certificate in the envelope was not swapped or re-encoded; re-obtain the original attestation bundle.
  4. If your Fulcio instance is custom, ensure it is configured to include the OIDC issuer and SAN identity extensions per the Fulcio profile sigstore-go expects.
  5. Read the wrapped inner error from SummarizeCertificate to see which extension was missing or unparsable.

Example fix

// before: attacker-supplied / non-Fulcio cert in envelope -> no OIDC issuer extension
// after: re-produce the attestation with signing_mode = "keyless" via public Fulcio,
// so cert carries the Fulcio OIDC-issuer and identity extensions
Defensive patterns

Strategy: type-guard

Validate before calling

// pre-parse the envelope certificate and require Fulcio OIDC-issuer extension before Verify
func hasFulcioOIDCIssuerExt(certPEM string) error {
	block, _ := pem.Decode([]byte(certPEM))
	if block == nil {
		return fmt.Errorf("no certificate PEM")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return err
	}
	oidOIDCIssuer := asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}
	for _, ext := range cert.Extensions {
		if ext.Id.Equal(oidOIDCIssuer) {
			return nil
		}
	}
	return fmt.Errorf("certificate %s lacks Fulcio OIDC-issuer extension; not Fulcio-issued", cert.Subject)
}

Type guard

func isFulcioIssued(cert *x509.Certificate) bool {
	_, err := fulciocertificate.SummarizeCertificate(cert)
	return err == nil
}

Try / catch

err := keylessVerifier.Verify(ctx, payloadType, payload, sig)
if err != nil {
	if strings.Contains(err.Error(), "summarize Fulcio certificate") {
		return fmt.Errorf("signing certificate is not a well-formed Fulcio certificate (missing OIDC issuer/identity extensions); obtain the attestation from a trusted signer: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: keylessVerifier.Verify invokes SummarizeCertificate(certificate) and it returns an error because the certificate lacks Fulcio's OIDC issuer extension (1.3.6.1.4.1.57264.1.1) or malformed identity extensions, so the issuer/identity summary cannot be built.

Common situations: The envelope's certificate was replaced or hand-crafted rather than issued by Fulcio; verifying an artifact signed by a non-Fulcio CA whose cert happens to chain to the trusted root; an old or unusual Fulcio issuance configuration that omits the OIDC-issuer extension; certificate corruption in transit.

Understand the failure class

Related errors


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