{"record":{"id":"85035a0b4158dde4","repo":"crowdsecurity/crowdsec","slug":"failed-to-create-cipher-w","errorCode":null,"errorMessage":"failed to create cipher: %w","messagePattern":"failed to create cipher: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/appsec/challenge/crypto.go","lineNumber":124,"sourceCode":"//\n// Returns ErrAllowlistReasonSize if reason exceeds MaxAllowlistReasonLen.\nfunc sealCookieV0(envelope *pb.ChallengeCookie, masterCookieKey []byte, notAfter int64, flags byte, reason string, aad []byte, maxCookieLen int) (string, error) {\n\tif maxCookieLen <= 0 {\n\t\tmaxCookieLen = MaxCookieLen\n\t}\n\n\tif len(reason) > MaxAllowlistReasonLen {\n\t\treturn \"\", fmt.Errorf(\"%w: %d > %d\", ErrAllowlistReasonSize, len(reason), MaxAllowlistReasonLen)\n\t}\n\n\tkey, err := deriveKey(masterCookieKey)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\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","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/challenge/crypto.go#L106-L142","documentation":"After HKDF key derivation, sealCookieV0 creates the AES block cipher via aes.NewCipher. This error means Go's AES implementation rejected the key. With a correct 32-byte HKDF output this is effectively impossible; it indicates the derived key has an invalid length, i.e. a broken keyring or a corrupted deriveKey path.","triggerScenarios":"Calling sealCookieV0 when deriveKey returned a key whose length is not 16/24/32 bytes — only possible with a corrupted or improperly initialized master cookie key, or an hkdf stream truncated by an error path.","commonSituations":"Programmatic misuse of the challenge package bypassing normal runtime construction; in practice developers rarely see this — it is a defensive check on an internal invariant.","solutions":["Inspect the wrapped error; if it mentions illegal key size, audit how masterCookieKey reaches sealCookieV0.","Rebuild the ChallengeRuntime through its standard constructor so the keyring produces a proper 32-byte key.","Verify the hkdf.Read call in deriveKey returns no error and fills all 32 bytes."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    return fmt.Errorf(\"cookie sealing failed (cipher): %w\", err)\n}","preventionTips":["Do not bypass the standard runtime constructor.","Keep crypto packages stock (no vendored forks).","Treat any occurrence as a bug report-worthy internal invariant failure."],"tags":["appsec","crypto","aes","internal-error"],"backgroundTag":"internal-invariant-violation","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}