Skip to content

fix: make BLE HELLO write-once, port duplicate-link resolution to Android (#29, #52) - #87

Merged
commitchan merged 1 commit into
ni5arga:mainfrom
littledivy:fix/hello-hijack
Jul 26, 2026
Merged

fix: make BLE HELLO write-once, port duplicate-link resolution to Android (#29, #52)#87
commitchan merged 1 commit into
ni5arga:mainfrom
littledivy:fix/hello-hijack

Conversation

@littledivy

@littledivy littledivy commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #29, and the Android half of #52.

The BLE wire is unauthenticated and HELLO was accepted at any time, so a re-HELLO could rewrite a live link's identity:

  • iOS: an attacker on a link to a victim sends a HELLO claiming the victim's tag; the duplicate resolver then tears the victim's real link down — persistent, targeted link-starve.
  • Android: remoteTag was set above the announced guard, so a re-HELLO re-labelled the link and the attacker's later payloads reached JS under a different peer's id.

…ni5arga#29, ni5arga#52)

The BLE link layer is unauthenticated, and HELLO was accepted at any
time on both platforms, mutating an already-announced link's identity:

- iOS (ni5arga#29): handleHello set remoteTag and re-ran resolveDuplicateLinks
  unconditionally. An attacker holding a link to a victim could send a
  second HELLO claiming the victim's tag; the resolver's tie-break then
  tore the victim's real link down — a targeted, persistent link-starve.
- Android (ni5arga#29): remoteTag was assigned *above* the announced guard, so
  a re-HELLO silently re-labelled a live link and the attacker's later
  payloads surfaced to JS under a different peer's id (attribution spoof).

Both now ignore HELLO once the link is announced: identity is written
exactly once, and a stranger cannot re-label or kill a live link.

Android also gained the duplicate-link resolver iOS already had (ni5arga#52):
the same lexicographic tie-break, adapted to Android's remoteTag id
model (keeper announced before the loser is dropped, so dropLink's
existing same-tag guard suppresses a spurious onDisconnected). The
ble-mesh README now documents write-once HELLO and cross-platform
duplicate resolution to match the code.

iOS compiles clean. Kotlin reviewed by hand; needs a CI/maintainer
compile and the two-phone validation tracked in ni5arga#21.

@commitchan commitchan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Read this closely since it's the unauthenticated wire and the #29 hijack I'd flagged.

The core fix is right on both platforms: moving the announced guard to the very top of handleHello makes HELLO write-once, so a re-HELLO on a live link returns before remoteTag is ever touched or the resolver re-runs — which is exactly what killed the iOS link-starve and the Android attribution re-label. The legitimate first-HELLO-per-link duplicate resolution still runs, since that path has announced == false.

The Android resolveDuplicateLink is a faithful line-for-line port of the iOS resolver, and — the part I checked hardest — the tie-break agrees across platforms: both compare hex(localTag) < remoteTag as lowercase fixed-width hex strings, which preserves byte order, so both phones independently pick the same physical wire to keep (smaller tag keeps its outbound link; the peer keeps that same link as its inbound). The post-announce loser drop is safe too: dropLink's guard only emits onDisconnected when no other announced link shares the tag, and the keeper does share it, so JS sees no spurious disconnect for the peer it's keeping.

No JS/TS touched, so the suite is unaffected — 231 green locally, typecheck clean. The red CI on this PR was unrelated Expo SDK-57 dependency drift breaking expo install --check on every PR; fixed on main in #88, so this rebases onto a green base.

Native background behaviour still wants real two-phone testing (can't be done in CI), but the logic is small and correct on read. Merging.

@commitchan
commitchan merged commit f98ed6e into ni5arga:main Jul 26, 2026
1 of 2 checks passed
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.

[High] Mid-session HELLO rewrites a live link's identity (iOS permanent hijack / Android attribution spoof)

2 participants