Skip to main content
Sigvex

Arbitrary Storage Write Remediation

Stop user-controlled storage slots by writing only through mappings and arrays under access control.

Arbitrary Storage Write Remediation

Overview

EVM state lives in a flat 2^256-slot space. If a function lets the caller choose the slot index for an SSTORE, the caller can overwrite the owner variable, a proxy implementation address, or any balance, giving them the same power as the contract owner. The fix is to never write to a raw caller-supplied slot: route writes through mappings or arrays, whose slots are derived by hashing, and gate state changes with access control.

Related Detector: Arbitrary Storage Write

Before (Vulnerable)

// User controls storage slot
function writeSlot(uint256 slot, uint256 value) external {
    assembly {
        sstore(slot, value)  // Attacker can overwrite any slot
    }
}

After (Fixed)

mapping(uint256 => uint256) public data;

// Mapping hash prevents arbitrary slot access
function writeData(uint256 key, uint256 value) external onlyOwner {
    data[key] = value;
}

A mapping computes its slot as keccak256(key, baseSlot), so the caller cannot target the owner slot or a proxy slot by choosing the key. Combined with onlyOwner, only authorized accounts can change state at all.

Alternative Mitigations

  • If raw slot access is truly required (for example, a migration tool), validate the slot against an explicit allowlist of permitted slots before writing.
  • For proxy patterns, use the standardized EIP-1967 slots rather than computing slots from input.
  • Keep all assembly storage writes behind access-controlled functions and never derive the slot from calldata.

Common Mistakes

  • Assuming an assembly { sstore(...) } block is safe because it is “low level”; the slot is still attacker-controlled.
  • Bounds-checking the value but not the slot index.
  • Writing to array.length directly, which can expand an array over adjacent storage.

References