Assessment reports>Radix>Threat Model>Key-value store operations

Key-value store operations

The key-value store API implements comprehensive validation and access control through

  • type safety through schema validation,

  • access control via locking mechanisms, and

  • resource cleanup through handle management.

Constructor API

The Constructor API provides methods for creating and initializing new key-value stores with proper schema validation and type safety controls.

KEY_VALUE_STORE_NEW

This creates a new key-value store with schema validation.

fn key_value_store_new( &mut self, data_schema: KeyValueStoreDataSchema, ) -> Result;

The following security controls are in place:

  1. Schema validation

    It validates the provided schema with built-in validation rules before store creation and prevents invalid schemas from being used.

validate_schema(additional_schema.v1()) .map_err(|_| RuntimeError::SystemError(SystemError::InvalidGenericArgs))?;
  1. Type safety

    It validates generic type substitutions against schema and ensures type safety across all store operations.

self.validate_kv_store_generic_args(&additional_schemas, &key_type, &value_type) .map_err(|e| RuntimeError::SystemError(SystemError::TypeCheckError(e)))?;

Handle API

The Handle API manages the lifecycle of key-value store entries through controlled access mechanisms, including opening entries with appropriate locks and proper cleanup of resources.

KEY_VALUE_STORE_OPEN_ENTRY

This opens a key-value entry with appropriate locking.

fn key_value_store_open_entry( &mut self, node_id: &NodeId, key: &Vec, flags: LockFlags, ) -> Result;

The key safeguards include the following:

  1. Type verification

    It verifies the type of the node before accessing it to prevent type-confusion attacks.

match type_info { TypeInfoSubstate::KeyValueStore(info) => info, _ => return Err(RuntimeError::SystemError(SystemError::NotAKeyValueStore)), }
  1. Lock-flag validation

    It validates lock flags against allowed operations. This prevents internal lock flags from being used in the user-facing API, which could lead to unintended behavior.

if flags.contains(LockFlags::UNMODIFIED_BASE) || flags.contains(LockFlags::FORCE_WRITE) { return Err(RuntimeError::SystemError(SystemError::InvalidLockFlags)); }
  1. Key schema validation

    It validates the key against the store's schema before access.

self.validate_kv_store_payload(&target, KeyOrValue::Key, &key)?;
  1. Lock-status checks

    It checks the lock status before granting write access, preventing write access to locked entries. This enables implementation of write-once semantics.

if flags.contains(LockFlags::MUTABLE) { let lock_status = self.api.kernel_read_substate(handle).map(|v| { let kv_entry: KeyValueEntrySubstate = v.as_typed().unwrap(); kv_entry.lock_status() })?; if let LockStatus::Locked = lock_status { return Err(RuntimeError::SystemError(SystemError::KeyValueEntryLocked)); } }

KEY_VALUE_ENTRY_CLOSE

This manages entry-handle cleanup.

fn key_value_entry_close(&mut self, handle: KeyValueEntryHandle) -> Result<(), RuntimeError>;

Entry API

The Entry API allows the reading and writing of key-value store entries.

KEY_VALUE_ENTRY_READ / KEY_VALUE_ENTRY_WRITE

These control read/write access to entries.

fn key_value_entry_read(&mut self, handle: KeyValueEntryHandle) -> Result, RuntimeError>; fn key_value_entry_write(&mut self, handle: KeyValueEntryHandle, buffer: Vec) -> Result<(), RuntimeError>;

The following are the key protections:

  1. Lock validation

    It verifies the appropriate lock type for an operation and prevents handle type-confusion attacks.

match data { SystemLockData::KeyValueEntry(..) => {} _ => return Err(RuntimeError::SystemError(SystemError::NotAKeyValueEntryHandle)); }
  1. Write-permission check

    It validates write permissions before modification and enforces proper access control.

match data { SystemLockData::KeyValueEntry(KeyValueEntryLockData::KVStoreWrite { .. }) => {} _ => return Err(RuntimeError::SystemError(SystemError::NotAKeyValueEntryWriteHandle)); }
  1. Schema validation on write

    It validates written data against a store schema and prevents invalid data corruption from entering the store.

self.validate_kv_store_payload( &kv_store_validation_target, KeyOrValue::Value, &buffer, )?;

KEY_VALUE_ENTRY_REMOVE / KEY_VALUE_STORE_REMOVE_ENTRY

The first method removes an already opened entry, whereas the latter removes an entry from the store by a (node, key) pair reference.

fn key_value_entry_remove(&mut self, handle: KeyValueEntryHandle) -> Result, RuntimeError>; fn key_value_store_remove_entry(&mut self, node_id: &NodeId, key: &Vec) -> Result, RuntimeError>;

There is one main security control:

  1. Write-lock requirement

    It requires a write lock for removal and prevents immutable entries from being deleted.

if !data.is_kv_entry_with_write() { return Err(RuntimeError::SystemError(SystemError::NotAKeyValueEntryWriteHandle)); }
Zellic © 2025Back to top ↑