Please do not open a public issue for a suspected vulnerability. Report it
privately through GitHub's Report a vulnerability button on this repository
(Security → Advisories), or by email to the maintainer listed in Cargo.toml.
You will get an acknowledgement within a few days and a fix or a written
assessment before any public disclosure. Data-corruption bugs, memory-safety
bugs in the unsafe surface, and crash-consistency violations all count.
ZeroDB is an embedded storage engine, not a security boundary. It assumes the database file is written only by trusted processes on a trusted filesystem, the same assumption LMDB makes.
What it promises
- Crash consistency. A power loss or
SIGKILLat any point leaves the file at some previously committed transaction, never a torn state: two double-buffered meta pages carry a mandatory CRC32C, and data pages are flushed before the meta that references them (SPEC 06). This is exercised continuously by a fault-injecting write backend and aSIGKILLharness (ADR-0008). - Memory safety and freedom from panics for every legal sequence of API
calls, verified by differential fuzzing against LMDB,
mirion the core, andloomon the reader table. - Single-writer, many-reader MVCC isolation within one process. Readers never block the writer or each other; a reader always sees one committed snapshot.
- Environment/transaction pairing is checked. Using a database handle with a transaction from a different environment panics with heed's message instead of touching the wrong file.
What it does not promise
- Safety against a hostile or corrupt database file. The meta CRC detects
accidental tearing, not tampering; it is unkeyed. A first-release hardening
pass made the open path and the read path refuse out-of-range page
references, zero-child branch pages, and hostile free-page lists with typed
errors, and added a fuzz target that feeds arbitrary bytes to
open. That work is a best effort, not a guarantee: a crafted file can still be able to cause a panic or an out-of-memory inzerodb-tools. Runzerodb-tools checkon files you trust or in a sandbox. - Cross-process access by untrusted processes. Several processes may
open one environment through its lock file (on by default, ADR-0023), but
every one of them must be a cooperating ZeroDB process: any process that
can write the lock file or the data file can corrupt the environment or
stall its readers and writers. With
NO_LOCKthere is no lock file, and opening the environment from two processes is undefined, as with LMDB'sMDB_NOLOCK. - Encryption at rest, or protection from a local user with write access to
the environment directory. Files are created with mode
0600. - Strictly bounded memory for a write transaction. Past a dirty-page limit
(
EnvOpenOptions::max_dirty_bytes, by default LMDB's 131,072 pages) a write transaction spills dirty pages to the file, as LMDB does. But a single value may be up to 4 GiB and is held in memory whole while it is written, and there is noMDB_TXN_FULLequivalent. - Anything about the C LMDB fork.
zerodb-tools migrate-from-lmdb(an opt-in build feature) parses an LMDB file with the C library; any LMDB memory-safety issue is in scope for that one command and no other part of the engine.
Only the latest release on the 0.x line receives fixes. Releases are git
tags with GitHub release notes (ADR-0013); a fix ships as the next patch tag.
unsafe is confined to the memory map and the unchecked page-field readers
behind a validated-view contract (zerodb-core::page::raw, zerodb-io), the
in-place WRITE_MAP path that writes dirty pages straight into the writable map
(zerodb-core::dirty, ADR-0021), the grow-only mapping cell, the lock
file's shared-memory atomics with its fcntl record locks and Linux futex
calls (zerodb-io::lockfile, ADR-0023), one pwritev FFI call, the
differential oracle's LMDB FFI, and the few pointer-shaped constructs heed's own
API forces on the adapter. Every block
carries a // SAFETY: comment; the policy is in AGENTS.md.