Skip to content

One cache budget is enforced twice over two subtrees, so the cache holds about twice the configured cap #284

Description

@MichaelTaylor3d

Task

cache_cap_bytes() is enforced independently by two eviction paths over two different subtrees, so the configured cap bounds each half rather than the whole.

The defect

  • crates/dig-node-core/src/lib.rs:1106 -- plan_eviction reads cache_cap_bytes() at lib.rs:2154, over <cache>/responses.
  • crates/dig-node-core/src/lib.rs:2340 -- evict_modules_locked reads the same cache_cap_bytes() at lib.rs:2342, over <cache>/modules.

Neither knows about the other, so a node configured for N bytes can hold close to 2N.

The reporting compounds it: dispatch.rs:526 reports used_bytes = total() against one cap_bytes, so displayed usage can exceed the cap it is shown against -- and dig-app's storage warning derives from that number (dig-app-core/src/cache.rs:211). A user watching the figure sees an impossible state and has no way to tell which half is over.

The sharper half: the response cache is attacker-orderable

plan_eviction ranks on mtime, and serve_cached_response calls touch() on every hit (lib.rs:2116). The serving path is inbound peer traffic -- so a peer's ordinary requests order this node's eviction, keeping its content resident and pushing another peer's out.

evict_modules_locked already refuses to do this: it passes last_access: 0 and names this exact attack at lib.rs:2347-2358. So the node contains both the defect and its own written-down diagnosis, in one file, on two paths.

Survivor

dig_store_cache::EvictionPolicy with dig_sex::TieredPolicy, which the modules path already uses.

Scope

Route <cache>/responses through the same seam, and split one budget across both subtrees rather than applying it twice. Whatever the split, used_bytes and cap_bytes must describe the same thing.

Related: DIG-Network/dig-store-cache#3, where LruPolicy has the same attacker-orderable recency defect at its source.

Evidence

Tests that fail without the fix: the sum across both subtrees stays under the configured cap; and repeated serving of one capsule does not change which entry is evicted next.

Parent

Rival-centralization epic: https://github.com/DIG-Network/dig_ecosystem/issues/3140

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:businessa person can DO something new, or money moves, or a shipped surface stops lying to them

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions