{"record":{"id":"16a12694a4cd35cc","repo":"hyperledger/fabric","slug":"identity-s-for-msp-s-has-trailing-bytes","errorCode":null,"errorMessage":"identity %s for MSP %s has trailing bytes","messagePattern":"identity (.+?) for MSP (.+?) has trailing bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"msp/mspimpl.go","lineNumber":956,"sourceCode":"\t\t}\n\t\tparentCert = chain[1]\n\n\t\t// Sanitize\n\t\treturn sanitizeECDSASignedCert(cert, parentCert)\n\t}\n\treturn cert, nil\n}\n\n// IsWellFormed checks if the given identity can be deserialized into its provider-specific form.\n// In this MSP implementation, well formed means that the PEM has a Type which is either\n// the string 'CERTIFICATE' or the Type is missing altogether.\nfunc (msp *bccspmsp) IsWellFormed(identity *m.SerializedIdentity) error {\n\tbl, rest := pem.Decode(identity.IdBytes)\n\tif bl == nil {\n\t\treturn errors.New(\"PEM decoding resulted in an empty block\")\n\t}\n\tif len(rest) > 0 {\n\t\treturn errors.Errorf(\"identity %s for MSP %s has trailing bytes\", string(identity.IdBytes), identity.Mspid)\n\t}\n\n\t// Important: This method looks very similar to getCertFromPem(idBytes []byte) (*x509.Certificate, error)\n\t// But we:\n\t// 1) Must ensure PEM block is of type CERTIFICATE or is empty\n\t// 2) Must not replace getCertFromPem with this method otherwise we will introduce\n\t//    a change in validation logic which will result in a chain fork.\n\tif bl.Type != \"CERTIFICATE\" && bl.Type != \"\" {\n\t\treturn errors.Errorf(\"pem type is %s, should be 'CERTIFICATE' or missing\", bl.Type)\n\t}\n\tcert, err := x509.ParseCertificate(bl.Bytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !isECDSASignedCert(cert) {\n\t\treturn nil\n\t}","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/msp/mspimpl.go#L938-L974","documentation":"IsWellFormed requires the identity PEM to decode to exactly one block: pem.Decode returns leftover bytes if extra data follows the certificate. Trailing content means the identity is not canonical and could decode differently across versions, so it is rejected, naming the identity bytes and MSP ID.","triggerScenarios":"IsWellFormed is called with identity.IdBytes containing a valid CERTIFICATE block followed by any additional bytes — e.g. concatenated certs, whitespace/newlines after the END line are tolerated but a second block or junk is not.","commonSituations":"Concatenating a user cert with the CA cert into one PEM file used as the identity; copying two certs into signcerts; pasting cert plus private key into the identity field.","solutions":["Strip everything after the first END CERTIFICATE line from the identity PEM","Keep only the single end-entity certificate in the identity/signcerts file","Move CA certs into the MSP cacerts/intermediatescerts folders instead of concatenating","Re-export the identity PEM from the original enrollment output"],"exampleFix":"// before\n// signcerts/cert.pem: userCert + caCert concatenated\n// after\n// signcerts/cert.pem: userCert only\n// cacerts/ca.pem: caCert","handlingStrategy":"validation","validationCode":"func singlePEMBlock(b []byte) bool {\n\tblk, rest := pem.Decode(b)\n\treturn blk != nil && len(bytes.TrimSpace(rest)) == 0\n}","typeGuard":"func isCanonicalSingleCertPEM(b []byte) bool {\n\tblk, rest := pem.Decode(b)\n\treturn blk != nil && blk.Type == \"CERTIFICATE\" && len(rest) == 0\n}","tryCatchPattern":"if err := msp.IsWellFormed(si); err != nil {\n\tif strings.Contains(err.Error(), \"trailing bytes\") {\n\t\t// trim everything after first END CERTIFICATE line\n\t}\n\treturn err\n}","preventionTips":["Keep exactly one certificate per identity PEM file","Never concatenate CA certs into signcerts","Sanitize copied PEM files for extra blocks/junk before use"],"tags":["pem","x509","fabric","serialization"],"backgroundTag":"pem-trailing-bytes","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}