{"record":{"id":"04efe27d8db669b7","repo":"JuliusBrussee/caveman","slug":"envelope-gcm-w","errorCode":null,"errorMessage":"envelope: gcm: %w","messagePattern":"envelope: gcm: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/envelope/envelope.go","lineNumber":80,"sourceCode":"\taad, scopeHash, err := scopeAAD(scope)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn seal(plaintext, schemeV2, aad, scopeHash)\n}\n\nfunc seal(plaintext []byte, scheme string, aad []byte, scopeHash string) (ciphertext []byte, metaJSON []byte, err error) {\n\tdataKey := make([]byte, 32)\n\tif _, err := rand.Read(dataKey); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: data key entropy: %w\", err)\n\t}\n\tblock, err := aes.NewCipher(dataKey)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: aes: %w\", err)\n\t}\n\tgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: gcm: %w\", err)\n\t}\n\tnonce := make([]byte, gcm.NonceSize())\n\tif _, err := rand.Read(nonce); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: nonce entropy: %w\", err)\n\t}\n\tciphertext = gcm.Seal(nonce, nonce, plaintext, aad)\n\n\twrapped, err := secretbox.EncryptPayloadKey(dataKey)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: wrap data key: %w\", err)\n\t}\n\tmeta := Metadata{Scheme: scheme, WrappedDataKey: base64.StdEncoding.EncodeToString(wrapped), ScopeHash: scopeHash}\n\tmetaJSON, err = json.Marshal(meta)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"envelope: marshal metadata: %w\", err)\n\t}\n\treturn ciphertext, metaJSON, nil\n}","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/envelope/envelope.go#L62-L98","documentation":"seal constructs an AES-GCM instance with cipher.NewGCM(block) and wraps failure as 'envelope: gcm: %w'. NewGCM only fails if the underlying cipher's block size is nonstandard, so with the library's own AES block this is effectively an internal invariant failure.","triggerScenarios":"Seal/SealForScope calling cipher.NewGCM on a block cipher whose BlockSize() != 16 — not reachable with the standard aes.NewCipher output unless the crypto stack is replaced.","commonSituations":"Patched or vendor-replaced crypto packages; exotic Go toolchains; test doubles injected in place of crypto/aes.","solutions":["Inspect the wrapped cause; confirm crypto/aes is the standard implementation (BlockSize 16).","Remove any custom crypto replacements/overrides in the build.","Rebuild with the official Go toolchain and redeploy.","File a bug with the wrapped error if it persists on a standard build."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"ciphertext, meta, err := envelope.Seal(plaintext, aad)\nif err != nil {\n    if strings.Contains(err.Error(), \"envelope: gcm\") {\n        log.Fatalf(\"GCM construction failed — crypto stack invariant broken: %v\", err)\n    }\n    return err\n}","preventionTips":["Do not vendor-replace crypto/* packages in builds.","Add a startup self-test that seals and opens a round-trip message.","Report persistent occurrences on standard builds upstream as bugs."],"tags":["crypto","gcm","aead","encryption"],"backgroundTag":"internal-invariant-violation","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}