Skip to content

security: gate verify screen confirmation behind an in-app-only arm (#34) - #73

Open
konkomaji wants to merge 1 commit into
ni5arga:mainfrom
konkomaji:fix/verify-screen-deep-link-34
Open

security: gate verify screen confirmation behind an in-app-only arm (#34)#73
konkomaji wants to merge 1 commit into
ni5arga:mainfrom
konkomaji:fix/verify-screen-deep-link-34

Conversation

@konkomaji

Copy link
Copy Markdown

Why

app.json registers the protestchat:// scheme, and expo-router auto-linking meant any website, QR code, or other app could push protestchat://verify/<publicId> straight onto the navigation stack, landing on a live "They match, mark verified" button with zero confirmation.

A link cannot forge a matching safety number, but it delivers a pre-armed verification UI outside the in-person ritual, a social-engineering assist against the app's one MITM defence (A5), aimed at exactly the stressed, non-expert users the threat model describes: "Your organizer sent you this link to verify them, tap here, the numbers match."

What changed

  • New src/lib/verify-session.ts: an in-memory, single-use "this id was armed by the in-app Verify press" flag. A URL cannot set it, since whatever a link puts in /verify/<id> is exactly the same param the in-app button would have produced, so origin has to be proven by something a link literally cannot carry.
  • src/app/chat/[id].tsx: the existing "Verify" action in the mode notice now calls armVerification(conversationId) immediately before navigating.
  • src/app/verify/[id].tsx: consumes the arm once on mount. If armed, behaviour is unchanged (match / no-match buttons). If not armed, meaning the screen was reached by deep link, QR, or another app, it still shows the correct safety-number digits (a link cannot forge those either way) but replaces the confirmation buttons with a caution notice explaining verification has to be started from the person's chat.
  • Existing contact?.verified undo path is untouched; downgrading trust needs no gate.

Test plan

  • npm test (236 tests, including 5 new for the arm/consume/expiry behaviour in verify-session.test.ts)
  • npm run typecheck
  • npm run lint
  • npm run i18n:check
  • Manual: tap protestchat://verify/<id> from outside the app on a device and confirm the caution notice appears with no confirm action

Safety / docs

  • docs/THREAT-MODEL.md Fixed section updated with this entry.
  • New user-facing string verify.externalOrigin added to all six locales. The hi/bn/mr/te/ta translations are a best effort on my part and should get the same native-speaker review already noted for the rest of the i18n work.

Closes #34

…i5arga#34)

protestchat:// deep links, QR codes on a website, or another app could push
straight onto /verify/<id> with a live "They match, mark verified" button,
skipping the in-person comparison that verification exists to prove
happened. That is a social-engineering assist against the one MITM defence
the app has (A5), aimed at stressed, non-expert users.

The confirm/deny buttons are now gated on an in-memory, single-use flag that
only the in-app Verify press in chat can set (src/lib/verify-session.ts). A
screen reached any other way still shows the correct safety-number digits,
since a link cannot forge them either way, but offers no confirmation
action.

Translations for verify.externalOrigin across hi/bn/mr/te/ta are a best
effort and should get the same native-speaker review noted for the rest of
the i18n work.
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.

[Medium] protestchat:// deep links can push a pre-armed verify screen from external content

1 participant