Skip to content

Stale removal selections can delete a different validator key #638

Description

@exromany

Locations

Summary

A validator-key removal is bound to a cached numeric position rather than the pubkey the manager selected. An ordered earlier removal can therefore make a still-valid stale transaction delete a different key.

Root cause

The removal workflow filters a cached key array and converts the selected offset into totalDepositedKeys + start. It passes the selected pubkeys to the SDK, but they are not encoded in calldata, and neither validation nor submission refreshes the inventory or verifies that the current range still contains those pubkeys.

  • Inventory queries may remain stale for ten minutes and do not refresh on focus or reconnect.
  • The contract checks only manager authority, the deposited prefix, and the current numeric range.
  • Removing a non-tail key compacts the last key into the removed position.

Impact

A manager can authorize removal of key B in two concurrent sessions yet have the later stale transaction remove key C. In CSM, the unintended successful removal also incurs another configured bond-funded removal charge; recovery requires retaining C's deposit material and re-adding it, potentially after losing queue placement.

This is low severity because both transactions require the operator manager's authorization, the blast radius is limited to that operator, and the key can generally be re-added. Nevertheless, the resulting on-chain mutation does not match the reviewed key identity, and the extra removal charge is not automatically recoverable.

Scenario

  1. The cached inventory is [D0,D1,A,B,C], with the first two keys deposited.
  2. A manager selects B; the widget constructs removeKeys(nodeOperatorId,3,1).
  3. Another session submits an intentional B-removal as the predecessor transaction.
  4. EOA nonce order, multisig nonce order, or smart-account operation order executes that removal first, producing [D0,D1,A,C].
  5. The stale transaction remains range-valid and removes the key now at index 3, which is C.
  6. The widget reports that one key was removed without comparing the emitted pubkey to B, while C must be re-added and the CSM removal-charge path has executed a second time.

Drafted from LidoLens finding RES-03

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions