{"record":{"id":"2d47543199a54b6f","repo":"hyperledger/fabric","slug":"malformed-signature-header","errorCode":null,"errorMessage":"malformed signature header","messagePattern":"malformed signature header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/verifier.go","lineNumber":394,"sourceCode":"\nfunc (v *Verifier) verifySignatureIsBoundToProposal(sig *Signature, identityID uint64, prop types.Proposal) error {\n\t// We verify the following fields:\n\t// ConsenterMetadata    []byte\n\t// SignatureHeader      []byte\n\t// BlockHeader          []byte\n\t// OrdererBlockMetadata []byte\n\n\t// Ensure block header is equal\n\tif !bytes.Equal(prop.Header, sig.BlockHeader) {\n\t\tv.Logger.Errorf(\"Expected block header %s but got %s\", base64.StdEncoding.EncodeToString(prop.Header),\n\t\t\tbase64.StdEncoding.EncodeToString(sig.BlockHeader))\n\t\treturn errors.Errorf(\"mismatched block header\")\n\t}\n\n\t// Ensure signature header matches the identity\n\tsigHdr := &cb.IdentifierHeader{}\n\tif err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil {\n\t\treturn errors.Wrap(err, \"malformed signature header\")\n\t}\n\tif identityID != uint64(sigHdr.Identifier) {\n\t\tv.Logger.Warnf(\"Expected identity %d but got %d\", identityID,\n\t\t\tsigHdr.Identifier)\n\t\treturn errors.Errorf(\"identity in signature header does not match expected identity\")\n\t}\n\n\t// Ensure orderer block metadata's consenter MD matches the proposal\n\tordererMD := &cb.OrdererBlockMetadata{}\n\tif err := proto.Unmarshal(sig.OrdererBlockMetadata, ordererMD); err != nil {\n\t\treturn errors.Wrap(err, \"malformed orderer metadata in signature\")\n\t}\n\n\tif !bytes.Equal(ordererMD.ConsenterMetadata, prop.Metadata) {\n\t\tv.Logger.Warnf(\"Expected consenter metadata %s but got %s in proposal\",\n\t\t\tbase64.StdEncoding.EncodeToString(ordererMD.ConsenterMetadata), base64.StdEncoding.EncodeToString(prop.Metadata))\n\t\treturn errors.Errorf(\"consenter metadata in OrdererBlockMetadata doesn't match proposal\")\n\t}","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/verifier.go#L376-L412","documentation":"Each consenter signature carries an IdentifierHeader (protobuf) binding the signature to a consenter identity number. VerifyConsenterSig -> verifySignatureIsBoundToProposal unmarshals it and this error means the bytes are not a valid IdentifierHeader — the signature's IdentifierHeader field is empty, truncated, or corrupted.","triggerScenarios":"VerifyConsenterSig -> verifySignatureIsBoundToProposal: proto.Unmarshal(sig.IdentifierHeader, sigHdr) returns an error — sig.IdentifierHeader is nil/empty or contains garbage bytes. Happens when a VerificationData blob is malformed, truncated in transit, or produced by incompatible code.","commonSituations":"Corrupted BFT message over the network; version skew between nodes producing different signature payloads; a replayed or hand-assembled VerificationData file; storage corruption of persisted signature metadata.","solutions":["Discard the malformed signature and re-request it from the signing consenter.","Confirm all ordering nodes run the same Fabric version so IdentifierHeader encoding is identical.","Enable debug logging on the BFT message layer to find where the payload got truncated or corrupted.","If it follows a restart from persisted state, delete/refresh the corrupted signature metadata (view/sequence data) and re-join the consensus flow."],"exampleFix":"// before: truncated signature payload\nsig.IdentifierHeader = []byte{0x0a, 0x05} // invalid proto -> error\n// after: valid marshalled IdentifierHeader\nsig.IdentifierHeader = protoutil.MarshalOrPanic(&cb.IdentifierHeader{Identifier: uint32(2)})","handlingStrategy":"type-guard","validationCode":"if len(sig.IdentifierHeader) == 0 {\n    return errors.New(\"signature has empty IdentifierHeader; reject message\")\n}","typeGuard":"func validIdentifierHeader(b []byte) bool {\n    h := &cb.IdentifierHeader{}\n    return len(b) > 0 && proto.Unmarshal(b, h) == nil\n}","tryCatchPattern":"err := verifier.VerifyConsenterSig(sig, id)\nif err != nil && strings.Contains(err.Error(), \"malformed signature header\") {\n    // discard corrupted signature and re-request from consenter\n}","preventionTips":["Use the same Fabric build across all consenters","Checksum/sign BFT messages on the wire to detect truncation","Rebuild consensus state if persisted signature metadata fails to unmarshal after restart"],"tags":["hyperledger-fabric","smartbft","protobuf","malformed-payload"],"backgroundTag":"malformed-protobuf-payload","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"}