Skip to content

fix(aztec-nr): tolerate malformed partial-note completion logs - #24668

Merged
nventuro merged 4 commits into
merge-train/fairies-v5from
nchamo/f-798-aztec-packages-malicious-sender-can-permanently-freeze-a
Jul 15, 2026
Merged

nventuro merged 4 commits into
merge-train/fairies-v5from
nchamo/f-798-aztec-packages-malicious-sender-can-permanently-freeze-a

Conversation

@nchamo

@nchamo nchamo commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Problem

Partial-note discovery has four crash points on the completion path, each reachable by a malicious sender and each firing before the pending note advances — so every subsequent sync re-hits it and permanently freezes note sync for that contract:

  • a matched completion log yields no note (panic),
  • a pending note resolves to more than one completion log (assert),
  • the delivered private half plus the log's public content exceed the packed-note capacity (BoundedVec overflow in the append), or
  • the completion log payload is empty, so reading the storage slot is out of bounds.

The first three are reachable on the canonical token (mismatched content over the unconstrained delivery channel, completing the same partial note twice which the token does not prevent, and an over-length delivered private half); the last needs an attacker-controlled contract emitting a tag-only log.

Fix

Make each non-fatal: warn and advance the FSM rather than panicking, so one bad message cannot break sync. A completion log that cannot yield a note (empty, over-length, or matching none) is skipped; more than one completion log completes with the first.

Fixes F-798

@nchamo nchamo self-assigned this Jul 13, 2026
@nchamo nchamo added ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure labels Jul 13, 2026
@nchamo
nchamo marked this pull request as ready for review July 13, 2026 22:24
@nchamo
nchamo requested a review from nventuro as a code owner July 13, 2026 22:24
Comment on lines +216 to +219
// The tag is not unique, so a pending partial note can resolve to more than one completion log (e.g.
// the same partial note completed twice). We complete with the first and ignore the rest rather than
// fail, so one crafted delivery cannot permanently break sync.
if num_logs > 1 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think (current) partial notes can be completed more than once. And the meaning of 'crafted' is unclear here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can, I could reproduce the issue with discovery_tolerates_a_partial_note_completed_twice. And I re-worded the comments to avoid "crafted"

@nchamo

nchamo commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

@nventuro , I added handling for two more panic sources. I updated the PR description to list all of them. Some of them are hard to trigger, some of them are easier. But I think it makes sense to be on the defensive side of things and just avoid panics all together, instead of trusting the contract dev to protect themselves against these situations

@nchamo
nchamo requested a review from nventuro July 14, 2026 12:59
@nventuro
nventuro merged commit 6489102 into merge-train/fairies-v5 Jul 15, 2026
15 checks passed
@nventuro
nventuro deleted the nchamo/f-798-aztec-packages-malicious-sender-can-permanently-freeze-a branch July 15, 2026 01:23
PhilWindle pushed a commit that referenced this pull request Jul 21, 2026
## Problem

Partial-note discovery has four crash points on the completion path,
each reachable by a malicious sender and each firing before the pending
note advances — so every subsequent sync re-hits it and permanently
freezes note sync for that contract:

- a matched completion log yields no note (`panic`),
- a pending note resolves to more than one completion log (`assert`),
- the delivered private half plus the log's public content exceed the
packed-note capacity (`BoundedVec` overflow in the append), or
- the completion log payload is empty, so reading the storage slot is
out of bounds.

The first three are reachable on the canonical token (mismatched content
over the unconstrained delivery channel, completing the same partial
note twice which the token does not prevent, and an over-length
delivered private half); the last needs an attacker-controlled contract
emitting a tag-only log.

## Fix

Make each non-fatal: warn and advance the FSM rather than panicking, so
one bad message cannot break sync. A completion log that cannot yield a
note (empty, over-length, or matching none) is skipped; more than one
completion log completes with the first.

Fixes F-798

(cherry picked from commit 6489102)
PhilWindle pushed a commit that referenced this pull request Jul 21, 2026
## Problem

Partial-note discovery has four crash points on the completion path,
each reachable by a malicious sender and each firing before the pending
note advances — so every subsequent sync re-hits it and permanently
freezes note sync for that contract:

- a matched completion log yields no note (`panic`),
- a pending note resolves to more than one completion log (`assert`),
- the delivered private half plus the log's public content exceed the
packed-note capacity (`BoundedVec` overflow in the append), or
- the completion log payload is empty, so reading the storage slot is
out of bounds.

The first three are reachable on the canonical token (mismatched content
over the unconstrained delivery channel, completing the same partial
note twice which the token does not prevent, and an over-length
delivered private half); the last needs an attacker-controlled contract
emitting a tag-only log.

## Fix

Make each non-fatal: warn and advance the FSM rather than panicking, so
one bad message cannot break sync. A completion log that cannot yield a
note (empty, over-length, or matching none) is skipped; more than one
completion log completes with the first.

Fixes F-798

(cherry picked from commit 6489102)
rangozd pushed a commit to rangozd/aztec-packages that referenced this pull request Aug 5, 2026
…Protocol#24668)

## Problem

Partial-note discovery has four crash points on the completion path,
each reachable by a malicious sender and each firing before the pending
note advances — so every subsequent sync re-hits it and permanently
freezes note sync for that contract:

- a matched completion log yields no note (`panic`),
- a pending note resolves to more than one completion log (`assert`),
- the delivered private half plus the log's public content exceed the
packed-note capacity (`BoundedVec` overflow in the append), or
- the completion log payload is empty, so reading the storage slot is
out of bounds.

The first three are reachable on the canonical token (mismatched content
over the unconstrained delivery channel, completing the same partial
note twice which the token does not prevent, and an over-length
delivered private half); the last needs an attacker-controlled contract
emitting a tag-only log.

## Fix

Make each non-fatal: warn and advance the FSM rather than panicking, so
one bad message cannot break sync. A completion log that cannot yield a
note (empty, over-length, or matching none) is skipped; more than one
completion log completes with the first.

Fixes F-798

(cherry picked from commit 6489102)
rangozd pushed a commit to rangozd/aztec-packages that referenced this pull request Aug 5, 2026
…ztecProtocol#24931)

Forward-ports the **noir / aztec-nr / contracts** slice of the v5-next →
next backlog (work merged to `v5-next` after the ~2026-07-08 cut that
reshaped `next`).

## Applied (clean cherry-picks, chronological)
- fix: prevent reception of messages too far into the future (AztecProtocol#24645)
- fix(aztec-nr): reject infinity ephemeral key in message encryption
(AztecProtocol#24665)
- fix(aztec-nr): tolerate malformed partial-note completion logs
(AztecProtocol#24668)
- docs(aztec-nr): document partial note completion trust model (AztecProtocol#24816)
- refactor(aztec-nr): shared no-op sync handler for stateless contracts
(AztecProtocol#24844)
- fix: dont panic on note msgs on contracts with no notes (AztecProtocol#24852)
- docs(noir-contracts): document standard-contract re-pin consequences
(AztecProtocol#24890)

## ⚠️ Needs owner conflict-resolution (conflict against reshaped `next`;
not included here)
Cherry-pick onto this branch and resolve:
- [ ] `git cherry-pick -x 9f1167e` — feat!: make inbox secrets be
multiple fields (AztecProtocol#24599)
- [ ] `git cherry-pick -x 4490597` — fix(aztec-nr): prevent recipient
forging a colliding handshake (AztecProtocol#24403)
- [ ] `git cherry-pick -x 8b1903c` — feat!: forbid external note
validation checks (AztecProtocol#24644)
- [ ] `git cherry-pick -x 10e339a` — fix(aztec-nr)!: compute note
property selectors from the packed layout (AztecProtocol#24689)
- [ ] `git cherry-pick -x 15c7a1e` — chore: clarify scope of packable
impl detection (AztecProtocol#24820)
- [ ] `git cherry-pick -x f66808c` — fix: change init and single
claim nullif to incl owner address, add testing utilities (AztecProtocol#24892)

Part of the manual v5-next → next backlog sweep. Draft until conflicts
are resolved and CI is green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants