{"record":{"id":"56d06c74015def9f","repo":"crowdsecurity/crowdsec","slug":"failed-to-marshal-challenge-cookie-proto-w","errorCode":null,"errorMessage":"failed to marshal challenge cookie proto: %w","messagePattern":"failed to marshal challenge cookie proto: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/appsec/challenge/crypto.go","lineNumber":140,"sourceCode":"\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create cipher: %w\", err)\n\t}\n\n\tgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create GCM: %w\", err)\n\t}\n\n\t// Reject an over-limit envelope before marshaling it.\n\tmaxPlaintext := maxCookieLen/4*3 - 1 - gcm.NonceSize() - gcm.Overhead()\n\tif plaintextLen := cookiePlaintextFixedHeaderLen + len(reason) + proto.Size(envelope); plaintextLen > maxPlaintext {\n\t\treturn \"\", fmt.Errorf(\"%w: plaintext=%d > %d\", ErrCookieTooLarge, plaintextLen, maxPlaintext)\n\t}\n\n\tenvelopeBytes, err := proto.Marshal(envelope)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to marshal challenge cookie proto: %w\", err)\n\t}\n\n\tnonce := make([]byte, gcm.NonceSize())\n\tif _, err := rand.Read(nonce); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to generate nonce: %w\", err)\n\t}\n\n\t// Build the plaintext: not_after_be8 || flags || reason_len_be || reason || envelope\n\tplaintext := make([]byte, 0, cookiePlaintextFixedHeaderLen+len(reason)+len(envelopeBytes))\n\n\tvar notAfterBytes [8]byte\n\tbinary.BigEndian.PutUint64(notAfterBytes[:], uint64(notAfter))\n\tplaintext = append(plaintext, notAfterBytes[:]...)\n\n\tplaintext = append(plaintext, flags)\n\n\tvar reasonLenBytes [2]byte\n\tbinary.BigEndian.PutUint16(reasonLenBytes[:], uint16(len(reason)))","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/challenge/crypto.go#L122-L158","documentation":"sealCookieV0 serializes the pb.ChallengeCookie envelope with proto.Marshal before encrypting it. This error means protobuf marshaling failed — for a plain generated message like ChallengeCookie, this is essentially unreachable (proto.Marshal only errors on required fields unset or internal wire issues), so it is a defensive internal check.","triggerScenarios":"Calling sealCookieV0 with an envelope that proto.Marshal cannot serialize — practically only with a nil or corrupt generated message, or a message with unpopulated required fields in proto2. All in-repo callers pass a valid &pb.ChallengeCookie{}.","commonSituations":"Effectively never in supported flows; would require a malformed protobuf type or corrupted reflection state.","solutions":["Inspect the wrapped proto error message for the failing field.","Verify the pb.ChallengeCookie passed to sealCookieV0 is a valid, non-nil generated message.","Regenerate the pb package if the generated code was hand-edited or is from a mismatched .proto version."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if envelope == nil {\n    return errors.New(\"nil challenge cookie envelope\")\n}","typeGuard":"func validEnvelope(e *pb.ChallengeCookie) bool { return e != nil && proto.Size(e) >= 0 }","tryCatchPattern":"if err != nil {\n    return fmt.Errorf(\"proto marshal: %w\", err)\n}","preventionTips":["Only pass non-nil generated pb.ChallengeCookie messages.","Regenerate the pb package when the .proto changes.","Never hand-edit generated protobuf Go code."],"tags":["appsec","protobuf","serialization","internal-error"],"backgroundTag":"protobuf-marshal-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}