{"record":{"id":"576d8b6fe28277e2","repo":"getsops/sops","slug":"could-not-generate-random-bytes-for-iv-s","errorCode":null,"errorMessage":"Could not generate random bytes for IV: %s","messagePattern":"Could not generate random bytes for IV: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"aes/cipher.go","lineNumber":154,"sourceCode":"\t\treturn false\n\t}\n}\n\n// Encrypt takes one of (string, int, float, bool) and encrypts it with the provided key and additional auth data, returning a sops-format encrypted string.\nfunc (c Cipher) Encrypt(plaintext interface{}, key []byte, additionalData string) (ciphertext string, err error) {\n\tif isEmpty(plaintext) {\n\t\treturn \"\", nil\n\t}\n\taescipher, err := cryptoaes.NewCipher(key)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"Could not initialize AES GCM encryption cipher: %s\", err)\n\t}\n\tvar iv []byte\n\tif stash, ok := c.stash[stashKey{plaintext: plaintext, additionalData: additionalData}]; !ok {\n\t\tiv = make([]byte, nonceSize)\n\t\t_, err = rand.Read(iv)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"Could not generate random bytes for IV: %s\", err)\n\t\t}\n\t} else {\n\t\tiv = stash\n\t}\n\tgcm, err := cipher.NewGCMWithNonceSize(aescipher, nonceSize)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"Could not create GCM: %s\", err)\n\t}\n\tvar plainBytes []byte\n\tvar encryptedType string\n\tswitch value := plaintext.(type) {\n\tcase string:\n\t\tencryptedType = \"str\"\n\t\tplainBytes = []byte(value)\n\tcase int:\n\t\tencryptedType = \"int\"\n\t\tplainBytes = []byte(strconv.Itoa(value))\n\tcase float64:","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/aes/cipher.go#L136-L172","documentation":"When a fresh IV is needed (the plaintext/additionalData pair is not stashed), Encrypt fills a nonceSize-byte buffer from crypto/rand. rand.Read practically never fails on modern platforms, but if the system entropy source is unavailable the error is wrapped here. Failure points to the operating environment, not the input data.","triggerScenarios":"Calling Cipher.Encrypt when the crypto/rand reader cannot provide nonceSize (32) random bytes — e.g. /dev/urandom unavailable, severe resource exhaustion, or a restricted sandbox/blocking seccomp profile.","commonSituations":"Containers with stripped-down /dev or restricted syscall allowlists; embedded/minimal images lacking a usable entropy source; sandboxed CI runners blocking getrandom(2).","solutions":["Verify /dev/urandom exists and is readable inside the container/host.","Check the runtime sandbox (seccomp/AppArmor) permits getrandom(2) or read(2) on urandom.","Retry after the system recovers; entropy exhaustion is usually transient."],"exampleFix":"// before (sandbox blocks getrandom)\n// seccomp profile: no getrandom\n// after\n// add getrandom to the seccomp allowlist, then:\ncipher.Encrypt(value, key, ad)","handlingStrategy":"retry","validationCode":"if _, err := os.Stat(\"/dev/urandom\"); err != nil {\n    return fmt.Errorf(\"entropy source unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"ciphertext, err := cipher.Encrypt(v, key, ad)\nif err != nil && strings.Contains(err.Error(), \"random bytes\") {\n    time.Sleep(100 * time.Millisecond)\n    return retryEncrypt(v, key, ad) // bounded retries\n}","preventionTips":["Ensure /dev/urandom is mounted in containers","Keep getrandom(2) in seccomp allowlists","Avoid running crypto workloads on hosts with exhausted entropy"],"tags":["sops","aes","encryption","random","entropy"],"backgroundTag":"crypto-rand-failure","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}