{"record":{"id":"9dc511a3e3bed169","repo":"JuliusBrussee/caveman","slug":"nonce-entropy-w","errorCode":null,"errorMessage":"nonce entropy: %w","messagePattern":"nonce entropy: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"shared/platform/secretbox/secretbox.go","lineNumber":80,"sourceCode":"\t}\n\tif runtimeenv.IsProduction() {\n\t\treturn nil, fmt.Errorf(\"secretbox: production requires CAVE_KMS_PROVIDER=scaleway\")\n\t}\n\tkeyBytes, err := loadKey()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tblock, err := aes.NewCipher(keyBytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"aes cipher: %w\", err)\n\t}\n\tgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"aes-gcm: %w\", err)\n\t}\n\tnonce := make([]byte, gcm.NonceSize())\n\tif _, err := rand.Read(nonce); err != nil {\n\t\treturn nil, fmt.Errorf(\"nonce entropy: %w\", err)\n\t}\n\t// Seal appends the ciphertext+tag to nonce, so the returned slice is the\n\t// full nonce||ciphertext envelope.\n\treturn gcm.Seal(nonce, nonce, plaintext, nil), nil\n}\n\n// EncryptPayloadKey wraps an artifact data-encryption key. Production uses the\n// dedicated payload KEK; local development retains the same AES-GCM envelope as\n// other local secrets.\nfunc EncryptPayloadKey(plaintext []byte) ([]byte, error) {\n\tif useKMS() {\n\t\tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n\t\tdefer cancel()\n\t\twrapped, err := kms.EncryptPayload(ctx, plaintext)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"secretbox: payload KMS encrypt: %w\", err)\n\t\t}\n\t\treturn wrapped, nil","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/secretbox/secretbox.go#L62-L98","documentation":"crypto/rand.Read failed while generating the 12-byte AES-GCM nonce in local-mode Encrypt. The kernel's CSPRNG essentially never fails on Linux/macOS in normal operation; documented failure modes are file-descriptor exhaustion (getrandom(2)/dev/urandom open fails), early boot before the entropy pool is ready on minimal VMs, or broken sandbox/seccomp profiles blocking the syscall. Since a repeated or predictable nonce destroys GCM security, the operation aborts.","triggerScenarios":"Local Encrypt under a container/sandbox whose seccomp or device-cgroup policy blocks getrandom or /dev/urandom; a very early-started process on an embedded/minimal kernel with an unseeded CRNG; ulimit -n exhausted so the random device cannot be opened.","commonSituations":"Custom Docker/seccomp profiles, gVisor/Firecracker microVMs at boot, sidecar-less initrd environments, or a malicious/accidental fd leak filling the process's descriptor table.","solutions":["Check the wrapped error (errno) — EMFILE means fd exhaustion: fix the leak or raise the limit; EPERM means the sandbox blocks the syscall: allow getrandom(2)/open of /dev/urandom.","On minimal VMs, ensure the boot path seeds entropy (haveged, virtio-rng, or waiting for the crng ready flag) before the service starts.","This is environmental, not a code bug — retrying without fixing the environment repeats the failure."],"exampleFix":"# before: container blocks getrandom -> \"nonce entropy: operation not permitted\"\ndocker run --security-opt seccomp=broken.json mysvc\n\n# after: default profile (or one permitting getrandom) \ndocker run mysvc","handlingStrategy":"fallback","validationCode":"// Cheap environmental preflight: confirm the CSPRNG answers before serving.\nfunc entropyAvailable() bool {\n    b := make([]byte, 1)\n    _, err := rand.Read(b)\n    return err == nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := secretbox.Encrypt(pt); err != nil {\n    if strings.Contains(err.Error(), \"nonce entropy\") {\n        // do NOT retry blindly: diagnose fd limits / seccomp / boot entropy; fail closed\n    }\n}","preventionTips":["Run containers with the default (or a getrandom-permitting) seccomp profile; verify /dev/urandom is accessible.","On minimal VMs, seed entropy before service start (virtio-rng, haveged, or wait for the kernel crng-ready flag).","Watch fd usage; EMFILE from a leak can surface here first."],"tags":["crypto","entropy","sandbox","environment"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}