Smart Contract Diff Audit L-16: Unvalidated `OnBlockSlot` Parameters Can Overflow the Consumability Window Computation

Open Beginner friendly
#3,679 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
65/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
security

Research direction

The issue is in crates/miden-standards/src/note/execution_hint.rs. Look at the on_block_slot constructor and from_parts decoder to see where the three bytes are accepted without validation. Then examine the can_be_consumed method to understand the overflow risk. The fix is to add bounds checks (e.g., ensuring shift amounts are less than 32) and possibly use checked arithmetic. Run the existing round-trip test to verify it still passes after your changes.

Written by the indexing model from the issue text.

Description

The OnBlockSlot variant of NoteExecutionHint describes a repeating window in which a note is expected to be consumable, encoded as three bytes named round_len, slot_len, and slot_offset. Neither the decoder in from_parts, which checks only that the unused high payload byte is zero, nor the on_block_slot constructor places any bound on the three values or on their relationship to each other, so a payload in which all three bytes are 255 decodes without error. The values are fully controlled by the note author, since the network account target attachment stores the hint and decodes it back without a bounds check.

The decoded bytes are consumed by can_be_consumed as shift amounts in 1 << round_len and 1 << slot_len, and then in unchecked u32 multiplication and addition. A shift amount of 32 or greater panics when overflow checks are enabled, and is otherwise masked into the range 0 to 31, yielding a window unrelated to the encoded parameters. The multiplication of slot_offset by the slot length in blocks can exceed u32::MAX even when both shift amounts are in range, for instance with round_len of 1, slot_len of 25, and slot_offset of 255. That out-of-range values reach this arithmetic unhindered is illustrated by the crate's own round-trip test, which encodes and decodes a slot_len of 33. The hint is advisory metadata that no kernel or note script enforces, and can_be_consumed has no caller outside its unit test in this repository, so the consequence falls on external consumers of the library: a consumer compiled with overflow checks aborts when evaluating a single malformed public note, while a consumer compiled without them silently computes an incorrect scheduling window.

Consider rejecting out-of-range round_len, slot_len, and slot_offset values at construction and decode time, in both on_block_slot and from_parts, so that an OnBlockSlot hint cannot exist with parameters its own window computation cannot represent. Alternatively, or in addition, consider making can_be_consumed total by widening the intermediate arithmetic to u64 or by using the checked shift, multiplication, and addition operations and returning a defined result when the computation does not fit.


Copied verbatim from finding L-16 (low severity) of the OpenZeppelin smart contract diff audit (NFTs). The audit was performed against commit 8411bf093bde25285708faac152b6d7269009617.

Dominant language
Rust
Stars
133
Forks
168
Avg merge
2d 3h
Merged PRs (30d)
93

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from 0xMiden/protocol

All issues in 0xMiden/protocol

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.