What Is the Cell Scope Validation Security Model in celld? A Complete Technical Guide
Celld's cell scope validation security model isolates each Durable Object in a dedicated SQLite database and enforces exclusive access through epoch-based ownership leases, ensuring only the legitimate node can modify a cell's state.
This article explains how the celld runtime—an open-source Durable Object platform developed by Deno—implements cell scope validation, a layered security architecture that prevents unauthorized access, stale writes, and cross-tenant data leakage. The model combines physical database separation, cryptographically secured leases, and runtime fencing checks.
Overview of the Cell Scope Validation Architecture
The celld runtime treats every cell (analogous to a Cloudflare Durable Object) as an isolated unit with three core guarantees:
- Physical isolation: Each cell owns a dedicated SQLite database file
- Temporal ownership: A node must hold a valid lease to access the cell
- Operational fencing: Every write operation validates the lease epoch against the database
These guarantees are enforced through mechanisms implemented across crates/celld/ownership_store.rs, crates/celld/protocol.rs, and the internal operator API endpoints.
Core Mechanism 1: Per-Cell SQLite Database Isolation
According to the celld source code and documentation, each cell receives its own SQLite database file stored on disk. This design choice eliminates shared table spaces that could enable cross-cell data leakage or resource contention attacks.
// Conceptual structure from ownership_store.rs
// Each cell maps to a unique database path
let db_path = format!("{}/{}.db", cell_storage_root, cell_id);
The physical separation means that even if a process-level compromise occurred, an attacker cannot ATTACH another cell's database without first obtaining its ownership lease and passing epoch validation.
Core Mechanism 2: Ownership Leases and Epoch Tracking
The ownership lease system in crates/celld/ownership_store.rs controls which node in the celld cluster may access a cell. Key properties include:
- Lease storage: Leases are persisted to the fleet bucket (typically S3-compatible object storage)
- Epoch counter: Each lease carries a monotonically increasing integer called the epoch
- Lease acquisition: Nodes compete for leases through a coordination protocol; only the winner may proceed
The epoch serves as a fence token—a distributed systems pattern that detects stale participants. When a node loses its lease (through expiration, eviction, or graceful release), the epoch increments. Any subsequent operation by the previous holder fails validation.
Core Mechanism 3: Fencing with Epoch Validation
The fencing mechanism, detailed in docs/fencing.md, is the runtime enforcement layer. Before any write operation to a cell's SQLite database, celld performs:
// Simplified logic from ownership_store.rs
async fn validate_fence(&self, cell_id: &str, expected_epoch: u64) -> Result<(), FenceError> {
let stored_epoch = self.db.get_epoch(cell_id).await?;
if stored_epoch != expected_epoch {
return Err(FenceError::EpochMismatch {
expected: expected_epoch,
found: stored_epoch,
});
}
Ok(())
}
Fence failure scenarios:
- A node with a stale lease attempts a write → epoch mismatch → operation aborted
- A partitioned node rejoins after lease expiration → its lease is invalid → rejected
- A malicious node fabricates a lease → HMAC verification fails → rejected (see peer protocol below)
The fencing check occurs at the SQLite layer, ensuring the database file itself records the authoritative epoch.
Core Mechanism 4: Authenticated Peer Protocol
Celld nodes communicate through a peer protocol implemented in crates/celld/protocol.rs. Every peer request includes:
| Component | Security Function |
|---|---|
| HMAC | Request authentication using a shared cluster secret |
| Body signature | Integrity verification of the message payload |
| Clock limit | Prevention of replay attacks via time windows |
| Replay protection | Nonce or sequence tracking to reject duplicate requests |
// From protocol.rs — peer request structure
pub struct PeerRequest {
cell_id: String,
payload: Vec<u8>,
hmac: [u8; 32],
signature: [u8; 64],
timestamp: u64,
nonce: [u8; 16],
}
The receiving node validates the HMAC against the shared secret stored in the fleet bucket. Without this secret, a compromised node cannot forge valid peer requests, even if it possesses an old lease.
Core Mechanism 5: Internal Operator API Boundaries
The operator API enforces cell scope validation through network-layer separation:
- Public listener: Exposes only health and metadata endpoints; rejects cell-specific operations
- Internal listener: Bound to
127.0.0.1or protected interfaces; requires valid lease for cell access
This design, documented in docs/security.md, prevents external actors from directly invoking cell operations. Even with network access to the celld node, attackers cannot reach cell-scoped endpoints without bypassing firewall rules.
Example: Cell Resolution via Internal API
# Succeeds only if node holds valid lease for my-cell
curl http://127.0.0.1:12345/cell/my-cell
Example: Forced Eviction (Administrative)
# Removes ownership lease, incrementing epoch and invalidating all pending operations
curl -X POST http://127.0.0.1:12345/evict/my-cell
The evict endpoint demonstrates administrative override of cell scope—intentionally restricted to the internal listener.
Security Model Integration: How the Layers Interact
The complete cell scope validation flow for a write operation:
- Lease check: Verify local ownership lease exists and is unexpired
- Peer authentication (if request proxied from another node): Validate HMAC and signature
- Fence check: Compare lease epoch against database-stored epoch
- Write execution: Open SQLite database, apply transaction, increment epoch
- Lease renewal: Extend lease in fleet bucket with new epoch
Any failure in steps 1–3 aborts the operation before database contact. Step 4's epoch increment ensures subsequent writes require the new epoch value.
Source Code References
| File | Role in Cell Scope Validation |
|---|---|
crates/celld/ownership_store.rs |
Lease storage, epoch management, fence validation |
crates/celld/protocol.rs |
Peer request HMAC, signatures, replay protection |
docs/security.md |
Listener separation, forwarded headers, internal API exposure |
docs/fencing.md |
Epoch-based fencing specification and failure modes |
Summary
Celld's cell scope validation security model provides defense in depth through:
- Physical isolation of cell state in dedicated SQLite databases
- Lease-based ownership with monotonic epoch counters
- Runtime fencing that rejects stale or unauthorized operations
- Cryptographic peer authentication using HMAC and body signatures
- Network-layer access control separating public and internal APIs
These mechanisms ensure that a cell's scope—its data and execution context—is strictly bound to the legitimate owner node at all times.
Frequently Asked Questions
How does celld prevent a stale node from writing to a cell after losing its lease?
Celld implements epoch-based fencing in crates/celld/ownership_store.rs. Each write validates the lease epoch against the epoch stored in the cell's SQLite database. A stale node holds an outdated epoch; the mismatch causes immediate operation abort before any data modification occurs.
What happens if an attacker gains access to the internal operator API?
The internal listener is typically bound to 127.0.0.1 or protected by firewall rules as documented in docs/security.md. Even with network access, every cell-specific endpoint requires a valid ownership lease. Without holding the current epoch-lease from the fleet bucket, requests return 404 or 403 errors.
Can a compromised celld node forge peer requests to access other cells?
No. The peer protocol in crates/celld/protocol.rs requires an HMAC computed with a shared cluster secret stored in the fleet bucket. A compromised node without this secret cannot generate valid request authentication codes. Additionally, lease holders must still pass epoch fencing at the target node.
Where is the authoritative cell state stored if nodes can lose leases?
Each cell's authoritative state resides in its dedicated SQLite database file on durable storage. The fleet bucket stores only lightweight lease metadata (node ID, epoch, expiration). When a new node acquires the lease, it opens the same database file and validates epoch continuity through fencing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →