{"record":{"id":"3a789fca0693b573","repo":"kubernetes/kops","slug":"parsing-pkcs7-signature-w","errorCode":null,"errorMessage":"parsing PKCS7 signature: %w","messagePattern":"parsing PKCS7 signature: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/attest.go","lineNumber":246,"sourceCode":"\n// parseAndValidatePKCS7Signer decodes and parses a base64-encoded PKCS7 signature, verifies its\n// self-signature, and validates that the signer certificate's SAN identifies an Azure metadata\n// endpoint. All checks here are CPU-only; no network I/O is performed, so this is safe to call\n// before triggering intermediate certificate fetches.\nfunc parseAndValidatePKCS7Signer(signature string) (*pkcs7.PKCS7, *x509.Certificate, error) {\n\tif signature == \"\" {\n\t\treturn nil, nil, fmt.Errorf(\"empty PKCS7 signature\")\n\t}\n\n\tsigBytes, err := base64.StdEncoding.DecodeString(signature)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"decoding PKCS7 signature: %w\", err)\n\t}\n\tklog.V(4).Infof(\"Decoded PKCS7 signature (%d bytes)\", len(sigBytes))\n\n\tp7, err := pkcs7.Parse(sigBytes)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"parsing PKCS7 signature: %w\", err)\n\t}\n\tklog.V(8).Infof(\"Parsed PKCS7 structure with %d embedded certificate(s)\", len(p7.Certificates))\n\n\t// Verify the PKCS7 signature against the embedded leaf certificate.\n\tif err := p7.Verify(); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"verifying PKCS7 signature: %w\", err)\n\t}\n\tklog.V(4).Infof(\"PKCS7 self-signature verified\")\n\n\tsigner := p7.GetOnlySigner()\n\tif signer == nil {\n\t\treturn nil, nil, fmt.Errorf(\"PKCS7 signer certificate not found\")\n\t}\n\tklog.V(8).Infof(\"PKCS7 signer certificate: subject=%q issuer=%q SANs=%v\", signer.Subject, signer.Issuer, signer.DNSNames)\n\tif err := validateAzureMetadataSignerSAN(signer); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"validating PKCS7 signer SAN: %w\", err)\n\t}\n\tklog.V(4).Infof(\"PKCS7 signer SAN validated as Azure metadata endpoint\")","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/attest.go#L228-L264","documentation":"This wraps a failure from go-pkcs7's pkcs7.Parse when the base64-decoded bytes could not be parsed as a PKCS#7/CMS SignedData structure. It means the signature decoded successfully but the DER bytes are not a well-formed PKCS#7 message, so signature verification could not proceed.","triggerScenarios":"parseAndValidatePKCS7Signer passes sigBytes to pkcs7.Parse; the underlying bytes are not DER (e.g. PEM headers left in, JSON, DER of the wrong ASN.1 type), or are truncated mid-sequence.","commonSituations":"Fake IMDS responses in tests containing arbitrary base64 strings; PEM-wrapped certificates ('-----BEGIN PKCS7-----') pasted as the signature; a truncated attested document from a network hiccup; pointing the code at a non-Azure metadata service whose signature format differs.","solutions":["Dump the decoded bytes (hex) and run `openssl pkcs7 -inform DER -text` to confirm they form a PKCS#7 SignedData structure","If the bytes are PEM-encoded, strip the BEGIN/END armor and base64-decode the inner payload before passing it","Verify the attested document fetcher returns the complete, untruncated IMDS response (compare Content-Length with received bytes)","Regenerate test fixtures using a real Azure attested document or a correctly DER-encoded PKCS7 blob rather than hand-written strings"],"exampleFix":"// before\nsigBytes, _ := base64.StdEncoding.DecodeString(\"-----BEGIN PKCS7-----\\nMIAG...\") // armor stripped incorrectly, parse fails\np7, err := pkcs7.Parse(sigBytes)\n// after\ninner := strings.TrimSuffix(strings.TrimPrefix(pemBody, \"-----BEGIN PKCS7-----\"), \"-----END PKCS7-----\")\nsigBytes, _ := base64.StdEncoding.DecodeString(strings.TrimSpace(inner))\np7, err := pkcs7.Parse(sigBytes)","handlingStrategy":"validation","validationCode":"sigBytes, err := base64.StdEncoding.DecodeString(signature)\nif err != nil {\n    return err\n}\nif len(sigBytes) < 8 || !bytes.HasPrefix(sigBytes, []byte{0x30}) {\n    return fmt.Errorf(\"decoded signature is not DER (missing ASN.1 SEQUENCE header)\")\n}","typeGuard":"func looksLikeDER(b []byte) bool {\n    return len(b) >= 2 && b[0] == 0x30 && int(b[1]) <= len(b)-2\n}","tryCatchPattern":"p7, err := pkcs7.Parse(sigBytes)\nif err != nil {\n    klog.V(4).Infof(\"pkcs7.Parse failed (%d bytes): %v; first bytes: % x\", len(sigBytes), err, sigBytes[:min(8, len(sigBytes))])\n    return nil, nil, fmt.Errorf(\"parsing PKCS7 signature: %w\", err)\n}","preventionTips":["Verify fixtures with `openssl pkcs7 -inform DER -in sig.der -text` before committing them","Strip PEM armor before base64-decoding if a signature ever arrives PEM-wrapped","Check Content-Length against the received IMDS response body to catch truncation","Do not route IMDS traffic through proxies that could rewrite the payload"],"tags":["azure","pkcs7","asn1","attestation"],"backgroundTag":"pkcs7-parse-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}