{"id":"a1c9bb2c10b7a694","repo":"gofiber/fiber","slug":"failed-to-create-gcm-mode-w","errorCode":null,"errorMessage":"failed to create GCM mode: %w","messagePattern":"failed to create GCM mode: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"middleware/encryptcookie/utils.go","lineNumber":54,"sourceCode":"\t_, err := decodeKey(key)\n\treturn err\n}\n\n// EncryptCookie Encrypts a cookie value with specific encryption key\nfunc EncryptCookie(name, value, key string) (string, error) {\n\tkeyDecoded, err := decodeKey(key)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tblock, err := aes.NewCipher(keyDecoded)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create AES cipher: %w\", err)\n\t}\n\n\tgcm, err := cipher.NewGCMWithRandomNonce(block)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create GCM mode: %w\", err)\n\t}\n\n\tciphertext := gcm.Seal(nil, nil, []byte(value), []byte(name))\n\treturn base64.StdEncoding.EncodeToString(ciphertext), nil\n}\n\n// DecryptCookie Decrypts a cookie value with specific encryption key\nfunc DecryptCookie(name, value, key string) (string, error) {\n\tkeyDecoded, err := decodeKey(key)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tenc, err := base64.StdEncoding.DecodeString(value)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to base64-decode value: %w\", err)\n\t}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/encryptcookie/utils.go#L36-L72","documentation":"Thrown at middleware/encryptcookie/utils.go:54 inside EncryptCookie() when cipher.NewGCMWithRandomNonce(block) returns an error. Via the public API this is effectively unreachable: the block is always an AES block (16-byte block size), which is a valid GCM block size, and NewGCMWithRandomNonce only errors on unsupported block sizes. The guard exists defensively.","triggerScenarios":"Only fires if NewGCMWithRandomNonce is handed a non-AES block (unsupported block size for GCM). Via EncryptCookie/DecryptCookie the block always comes from aes.NewCipher, so this cannot trigger in the supported flow. Could surface in a custom Encryptor that builds a non-AES cipher and reuses this code path.","commonSituations":"Custom Encryptor/Decryptor that swaps in a non-AES cipher (e.g. a DES or test-only block) but routes through this code path; future Go crypto/cipher change tightening GCM acceptance; an exotic build where AES is replaced by a no-op cipher.","solutions":["If you supply a custom Encryptor/Decryptor, ensure it uses an AES block (the only block type this code path supports).","Run encryptcookie.ValidateKey(key) at startup; combined with the AES cipher construction it confirms the whole chain.","For non-AES ciphers, write the GCM (or other AEAD) construction yourself rather than reusing EncryptCookie internals.","Add a smoke test that calls EncryptCookie then DecryptCookie round-trip on app boot to catch environment-level crypto issues."],"exampleFix":"// before: custom encryptor mixes a non-AES block into this code path\ncfg.Encryptor = func(name, value, key string) (string, error) {\n    block, _ := des.NewTripleDESCipher(rawKey) // non-AES\n    gcm, err := cipher.NewGCMWithRandomNonce(block) // unsupported -> error 159\n    ...\n}\n\n// after: keep AES in this path; move non-AES ciphers to their own helper\nblock, err := aes.NewCipher(rawKey) // AES - always GCM-compatible\nif err != nil { return \"\", err }\ngcm, err := cipher.NewGCMWithRandomNonce(block)\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to create GCM mode: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// At startup, exercise the full encrypt/decrypt chain to confirm GCM works.\nenc, err := encryptcookie.EncryptCookie(\"probe\", \"hello\", key)\nif err != nil { log.Fatalf(\"cookie encryption unavailable: %v\", err) }\nif _, err := encryptcookie.DecryptCookie(\"probe\", enc, key); err != nil {\n    log.Fatalf(\"cookie decryption unavailable: %v\", err)\n}","typeGuard":"// Ensure custom encryptors only feed AES blocks into NewGCMWithRandomNonce.\nfunc isAESBlock(block cipher.Block) bool {\n    return block.BlockSize() == 16 // AES is the only standard 16-byte block here\n}","tryCatchPattern":"// Custom encryptor: only AES reaches the GCM construction.\nblock, err := aes.NewCipher(raw)\nif err != nil { return \"\", err }\ngcm, err := cipher.NewGCMWithRandomNonce(block)\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to create GCM mode: %w\", err)\n}","preventionTips":["Keep AES as the cipher for this code path; route non-AES ciphers elsewhere.","Add an encrypt/decrypt round-trip smoke test at app boot.","In custom encryptors, construct GCM only from a known-AES block.","Pin to supported Go versions whose crypto/aes + crypto/cipher behave as expected."],"tags":["encryptcookie","crypto","aes","gcm","fiber"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}