{"record":{"id":"1948a73ee19d8f18","repo":"JuliusBrussee/caveman","slug":"envelope-aes-w","errorCode":null,"errorMessage":"envelope: aes: %w","messagePattern":"envelope: aes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/envelope/envelope.go","lineNumber":76,"sourceCode":"// SealForScope binds ciphertext authentication to tenant/object scope. Moving\n// ciphertext plus metadata to another tenant, project, or object class makes\n// decryption fail even when storage and KMS credentials are compromised.\nfunc SealForScope(plaintext []byte, scope Scope) (ciphertext []byte, metaJSON []byte, err error) {\n\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 {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/envelope/envelope.go#L58-L94","documentation":"After generating the data key, seal calls aes.NewCipher(dataKey) and wraps any failure as 'envelope: aes: %w'. With a 32-byte key this should always produce AES-256, so the error indicates the cipher could not be constructed — practically only possible if the key length is wrong or the crypto backend is unavailable (e.g. FIPS builds without AES).","triggerScenarios":"Seal/SealForScope reaching aes.NewCipher with a dataKey whose length is not a valid AES key size, or a Go build whose AES implementation is unavailable.","commonSituations":"Custom/patched crypto stacks (FIPS-restricted builds); toolchain or hardware AES issues; code paths that modified the key material length before sealing.","solutions":["Inspect the wrapped cause; confirm the data key is exactly 32 bytes.","Verify the Go build includes standard AES support (avoid stripped/patched crypto packages).","Rebuild with the official Go toolchain and retry.","If on a restricted platform, enable an AES-capable crypto provider."],"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: aes\") {\n        log.Fatalf(\"AES unavailable in this build — rebuild with standard crypto: %v\", err)\n    }\n    return err\n}","preventionTips":["Build with the official Go toolchain and unmodified crypto/aes.","Test envelope sealing at boot (seal/decrypt a canary) to fail fast on crypto issues.","If FIPS-constrained, verify AES-256 support in the certified provider before deploying."],"tags":["crypto","aes","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"}