fix(inbox): bind settings + last_update into inbox signature (#253)#284
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #253. The inbox
inbox_signatureonly coveredSTATE_UPDATE || owner_ek_bytes, leavingsettingsandlast_updateunauthenticated mutable state. A peer relaying inboxStatecould keep the legit ek+signature, rewritesettingsto a permissive anti-flood policy (dropminimum_tier, enableallow_verified_skip_token, injectverified_senders) and bumplast_update, then rebroadcast —verifypassed andmergeadopted the spoofed policy via LWW. Spam-gate bypass with no key compromise.Fix
Widen the signed payload to:
ModifySettingsmutates settings + last_update in the WASM host (no signing key), so the owner now signs the post-mutation payload client-side: the variant carriesinbox_signature(full payload) +last_update; the host pinslast_updateverbatim (drops the+1µsbump) and stores the signature so the resulting state re-verifies. Old settings-onlyModifySettings.signaturedropped — 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 toLEGACY_INBOX_CODE_HASHES).Changes
contracts/inbox/src/lib.rs): pubsign_payloadhelper (reused by UI + tests), widenedsign/verify, reworkedModifySettingsvariant + both host arms +can_update_settings.settings_modify_preparesigns the full payload with a freshUtc::now()last_update;InternalSettingscarriesowner_ek_bytes; ModifySettings-delta cache arm uses the wirelast_update.INBOX_CODE_HASHappended toLEGACY_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_updateis 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.