Skip to content

fix(inbox): bind settings + last_update into inbox signature (#253)#284

Merged
iduartgomez merged 2 commits into
mainfrom
fix/inbox-sig-settings-253
May 29, 2026
Merged

fix(inbox): bind settings + last_update into inbox signature (#253)#284
iduartgomez merged 2 commits into
mainfrom
fix/inbox-sig-settings-253

Conversation

@iduartgomez
Copy link
Copy Markdown
Contributor

Summary

Closes #253. The inbox inbox_signature only covered STATE_UPDATE || owner_ek_bytes, leaving settings and last_update unauthenticated mutable state. A peer relaying inbox State could keep the legit ek+signature, rewrite settings to a permissive anti-flood policy (drop minimum_tier, enable allow_verified_skip_token, inject verified_senders) and bump last_update, then rebroadcast — verify passed and merge adopted the spoofed policy via LWW. Spam-gate bypass with no key compromise.

Fix

Widen the signed payload to:

STATE_UPDATE || owner_ek_bytes || serde_json(settings) || last_update_micros_be

ModifySettings mutates settings + last_update in the WASM host (no signing key), so the owner now signs the post-mutation payload client-side: the variant carries inbox_signature (full payload) + last_update; the host pins last_update verbatim (drops the +1µs bump) and stores the signature so the resulting state re-verifies. Old settings-only ModifySettings.signature dropped — hard cutover (the code change rotates the inbox wasm hash anyway, so #213 migration re-PUTs every user's state under the new id; prior hash appended to LEGACY_INBOX_CODE_HASHES).

Changes

  • contract (contracts/inbox/src/lib.rs): pub sign_payload helper (reused by UI + tests), widened sign/verify, reworked ModifySettings variant + both host arms + can_update_settings.
  • ui: settings_modify_prepare signs the full payload with a fresh Utc::now() last_update; InternalSettings carries owner_ek_bytes; ModifySettings-delta cache arm uses the wire last_update.
  • migration: inbox hash rotated; prior INBOX_CODE_HASH appended to LEGACY_INBOX_CODE_HASHES.

Tests

40 inbox integration + 176 ui lib tests pass. New: tamper-rejection for settings/last_update/ek in State broadcasts, ModifySettings round-trip pins last_update + re-verifies, forged-sig + ek-mismatch rejection. QA inventory updated.

Note

last_update is owner-supplied wall-clock — two devices racing could pick equal/lower stamps (same constraint #223 already had). Out of scope; device-monotonic stamping is a possible follow-up.

The inbox signature only covered STATE_UPDATE || owner_ek_bytes, leaving
`settings` and `last_update` unauthenticated mutable state. A peer relaying
inbox State could keep the legit ek+signature, rewrite `settings` to a
permissive anti-flood policy (drop minimum_tier, enable verified-skip, inject
verified_senders) and bump `last_update`, then rebroadcast: verify passed and
merge adopted the spoofed policy via LWW — a spam-gate bypass with no key
compromise.

Widen the signed payload to:
  STATE_UPDATE || owner_ek_bytes || serde_json(settings) || last_update_micros_be

ModifySettings mutates settings + last_update in the WASM host, which has no
signing key, so the owner now signs the post-mutation payload client-side: the
variant carries `inbox_signature` (full payload) + `last_update`, the host pins
last_update verbatim (drops the +1µs bump) and stores the signature so the
resulting state re-verifies. Old settings-only `ModifySettings.signature` dropped
(hard cutover — the code change rotates the inbox wasm hash anyway, so #213
migration re-PUTs every user's state under the new id).

- contract: `sign_payload` helper (now pub, reused by UI + tests), widened
  sign/verify, reworked ModifySettings variant + both host arms +
  can_update_settings.
- ui: settings_modify_prepare signs the full payload with a fresh Utc::now()
  last_update; InternalSettings carries owner_ek_bytes; ModifySettings-delta
  cache arm uses the wire last_update; prior INBOX_CODE_HASH appended to
  LEGACY_INBOX_CODE_HASHES.
- tests: tamper-rejection for settings/last_update/ek in State broadcasts,
  ModifySettings round-trip pins last_update + re-verifies, forged-sig and
  ek-mismatch rejection. 40 inbox + 176 ui tests pass.
@iduartgomez iduartgomez merged commit 0e9f3f3 into main May 29, 2026
5 checks passed
@iduartgomez iduartgomez deleted the fix/inbox-sig-settings-253 branch May 29, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Widen Inbox signature to bind settings + last_update (#249 followup)

1 participant