{"record":{"id":"075bfdb54235fe6b","repo":"tursodatabase/turso","slug":"failed-to-generate-random-bytes","errorCode":null,"errorMessage":"failed to generate random bytes","messagePattern":"failed to generate random bytes","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"extensions/core/src/vfs_modules.rs","lineNumber":31,"sourceCode":"    pub builtin_vfs: *mut *const VfsImpl,\n    pub builtin_vfs_count: i32,\n}\nunsafe impl Send for VfsInterface {}\n\npub trait VfsExtension: Default + Send + Sync {\n    const NAME: &'static str;\n    type File: VfsFile;\n    fn open_file(&self, path: &str, flags: i32, direct: bool) -> ExtResult<Self::File>;\n    fn remove_file(&self, path: &str) -> ExtResult<()>;\n    fn run_once(&self) -> ExtResult<()> {\n        Ok(())\n    }\n    fn close(&self, _file: Self::File) -> ExtResult<()> {\n        Ok(())\n    }\n    fn generate_random_number(&self) -> i64 {\n        let mut buf = [0u8; 8];\n        getrandom::fill(&mut buf).expect(\"failed to generate random bytes\");\n        i64::from_ne_bytes(buf)\n    }\n    fn get_current_time(&self) -> String {\n        chrono::Local::now().format(\"%Y-%m-%d %H:%M:%S\").to_string()\n    }\n}\n\npub trait VfsFile: Send + Sync {\n    fn lock(&mut self, _exclusive: bool) -> ExtResult<()> {\n        Ok(())\n    }\n    fn unlock(&self) -> ExtResult<()> {\n        Ok(())\n    }\n    fn read(&mut self, buf: BufferRef, offset: i64, cb: Callback) -> ExtResult<()>;\n    fn write(&mut self, buf: BufferRef, offset: i64, cb: Callback) -> ExtResult<()>;\n    fn sync(&self, cb: Callback) -> ExtResult<()>;\n    fn truncate(&self, len: i64, cb: Callback) -> ExtResult<()>;","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/extensions/core/src/vfs_modules.rs#L13-L49","documentation":"The VFS extension trait's default generate_random_number (extensions/core/src/vfs_modules.rs:28-32) fills an 8-byte buffer via getrandom::fill and unwraps it with expect(\"failed to generate random bytes\"). getrandom only fails when the OS entropy source is unavailable or blocked - e.g. the getrandom(2) syscall is denied by a seccomp policy, or the platform has no usable entropy source. Any SQL needing engine randomness (random(), randomblob()) or a custom VFS that does not override this method will panic in that situation.","triggerScenarios":"Using an extension VFS that inherits the default generate_random_number inside a sandbox that blocks the getrandom syscall (custom seccomp/AppArmor profile, gVisor, Kata), on embedded/WASI targets without an entropy source, or in minimal containers where the syscall or /dev/urandom is not available.","commonSituations":"Hand-rolled Docker seccomp profiles missing getrandom, gVisor/sandboxed runtimes, distroless or scratch containers with restricted devices, embedded deployments, CI in hardened sandboxes.","solutions":["Override generate_random_number in your Vfs implementation to source randomness from an API your environment permits (e.g. a pre-seeded RNG or platform API).","Fix the sandbox: add 'getrandom' to the seccomp allowlist (SECCOMP_RET_ALLOW) or relax the container security profile.","Ensure /dev/urandom exists and is readable in minimal containers.","Upgrade the getrandom crate dependency - newer versions cover more platforms and fallback paths."],"exampleFix":"// before: default trait method panics in restricted sandbox\nimpl Vfs for MyVfs { /* generate_random_number not overridden */ }\n\n// after: provide your own entropy source\nimpl Vfs for MyVfs {\n    fn generate_random_number(&self) -> i64 {\n        let mut buf = [0u8; 8];\n        my_platform_fill(&mut buf); // e.g. pre-seeded RNG or host API\n        i64::from_ne_bytes(buf)\n    }\n}","handlingStrategy":"fallback","validationCode":"// Probe entropy availability once at startup, before SQL runs:\nfn entropy_available() -> bool {\n    let mut buf = [0u8; 8];\n    getrandom::fill(&mut buf).is_ok()\n}\n// If false, install a VFS whose generate_random_number uses your own source\n// and avoid random()/randomblob() in the schema.","typeGuard":null,"tryCatchPattern":"Rust host: std::panic::catch_unwind around the first query that may touch randomness, then swap in a VFS override that does not call getrandom.","preventionTips":["Always override generate_random_number when implementing a Vfs for restricted environments.","Add 'getrandom' to container seccomp allowlists (or use the default Docker profile).","Smoke-test SELECT random(); in the exact deployment sandbox, not just on the dev machine.","Keep getrandom and the extension crate updated for new platform fallbacks."],"tags":["rust","panic","getrandom","entropy","vfs","sandbox","seccomp","extension"],"backgroundTag":"getrandom-entropy-unavailable","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}