{"record":{"id":"c80444a024246553","repo":"hashicorp/packer","slug":"static-certificate-provider-is-missing-a-certifica","errorCode":null,"errorMessage":"static certificate provider is missing a certificate","messagePattern":"static certificate provider is missing a certificate","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/attestation/sign_keyless.go","lineNumber":296,"sourceCode":"\n\t\tcertificate, err := x509.ParseCertificate(block.Bytes)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parse keyless certificate: %w\", err)\n\t\t}\n\n\t\treturn certificate, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"keyless attestation does not contain a signing certificate\")\n}\n\ntype staticCertificateProvider struct {\n\tcertDER []byte\n}\n\nfunc (p staticCertificateProvider) GetCertificate(context.Context, sigstoregosign.Keypair, *sigstoregosign.CertificateProviderOptions) ([]byte, error) {\n\tif len(p.certDER) == 0 {\n\t\treturn nil, fmt.Errorf(\"static certificate provider is missing a certificate\")\n\t}\n\n\treturn append([]byte(nil), p.certDER...), nil\n}\n\nfunc resolveAmbientIDToken(ctx context.Context, env map[string]string) (string, error) {\n\tif token := strings.TrimSpace(env[\"SIGSTORE_ID_TOKEN\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token := strings.TrimSpace(env[\"CI_JOB_JWT_V2\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token := strings.TrimSpace(env[\"CI_JOB_JWT\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token, err := resolveGitHubActionsIDToken(ctx, env); err == nil && token != \"\" {\n\t\treturn token, nil\n\t}","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/attestation/sign_keyless.go#L278-L314","documentation":"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.","triggerScenarios":"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.","commonSituations":"Zero-value keylessSigner used outside newKeylessSigner; a refactoring that reordered Fulcio certificate retrieval; tests constructing the provider manually with no bytes.","solutions":["Ensure the signer is created via newKeylessSigner, which requests and parses the Fulcio certificate before any SignBundle call.","Check that the Fulcio GetCertificate step did not silently return empty bytes in a custom newKeylessFulcio override.","If constructing staticCertificateProvider directly, pass the non-empty cert.Raw DER bytes.","Add a pre-flight check that the signer's certificate is non-nil before bundling."],"exampleFix":"// before\nprovider := staticCertificateProvider{} // empty\n// after\nif len(certDER) == 0 {\n    return fmt.Errorf(\"no Fulcio certificate available for bundling\")\n}\nprovider := staticCertificateProvider{certDER: certDER}","handlingStrategy":"validation","validationCode":"if signer == nil || signer.cert == nil || len(signer.cert.Raw) == 0 {\n    return fmt.Errorf(\"keyless signer has no Fulcio certificate; construct via newKeylessSigner\")\n}","typeGuard":"func signerReady(s *keylessSigner) bool {\n    return s != nil && s.cert != nil && len(s.cert.Raw) > 0\n}","tryCatchPattern":"envelope, _, err := signer.SignBundle(ctx, payloadType, payload, cfg)\nif err != nil && strings.Contains(err.Error(), \"static certificate provider is missing\") {\n    return fmt.Errorf(\"signer was not initialized with a Fulcio certificate: %w\", err)\n}","preventionTips":["Only obtain keylessSigner through newKeylessSigner.","Check the Fulcio GetCertificate result is non-empty before returning the signer.","Add constructor assertions that cert and certPEM are set.","Never zero-value initialize internal signer structs in tests."],"tags":["go","sigstore","keyless-signing","internal-invariant"],"backgroundTag":"missing-certificate-bytes","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}