Starling 0.4.0
0.4.0 adds a way to get help from people who are not in your circle, and fixes something real in how devices decide who a message came from. Everyone should update: 0.3.x clients cannot talk to the 0.4.0 relay.
Get help from outside your circle
Your circle is a list you chose in advance. In an actual emergency the people who can reach you are often not on it, and are not going to install an app in the next two minutes: a neighbour, a colleague, whoever is nearby.
An SOS can now mint a help link. It opens your live position in any browser, on any phone or laptop, with no app and no account. It runs on its own secret, its own channel and its own signing identity, so it shows that one emergency and can never turn into access to your circle or its history. Checking in safe, stopping the share, or locking the app ends it, and the person watching sees that it ended instead of a dot that quietly stops moving.
Anyone you send the link to can forward it. That is what a link with no account means, and it is the trade: reachability when you need it, in exchange for not controlling who ends up watching.
Devices verify who sent a message now
The circle's content key is shared by everyone in it. That means decrypting a message only ever proved that some member wrote it, never which one. The thing that answers "which one" is the per-sender signature, and until now the relay was the only party checking it.
So a member working with a compromised relay could have put another member's name on any position. The threat model claimed otherwise, which made it wrong.
The feed now carries each signature and every device checks it against the key that member's id hashes from, before decrypting anything. test/roster.test.mjs runs that exact forgery, and with the check removed it succeeds, which is the point of having the test.
Member ids went from 64 to 128 bits at the same time, since that id is how a key gets named and a receiver's whole trust in a sender rests on it. Existing installs upgrade in place and keep their circles, keys and invite links.
Also
- Tor mode asks Orbot which SOCKS port it is actually on instead of assuming 9050, which is still the fallback. It only trusts an answer to a question it just asked, since the receiver has to be exported and cannot see who sent it an intent.
- The relay stops a member's replay window from re-opening under concurrent posts, and separates its rate limit accounting so flooding new channels can no longer clear an address's own limit.
On the audits
This release was reviewed by models and tooling other than the ones that wrote it, which is the right way round for new code doing cryptography, and was suggested by someone whose opinion on that is worth more than mine. Two independent passes plus a fan-out of reviewers with an adversarial refutation round.
What that caught and what shipped fixed: a location failure racing an SOS could leave a beacon running with no way on screen to stop it, and the next SOS would have reused its secret; the viewer left the beacon secret in the browser's address bar and history, where it would sync to the helper's other devices; ending a beacon could hang on a stalled request and never cancel the sender.
What it got wrong, for the record: a confident report that alg could be set to hmac to make the verifier import a public key as a symmetric secret. It is an allowlist lookup, so hmac, HMAC, __proto__ and constructor all return false. Worth writing down, because a plausible crypto finding that is wrong costs as much time as a real one.
Still true, and still worth saying: nobody independent has audited this. Boring constructions and real tests are not the same thing as review by a person.
Verify this build
Signed with the certificate whose SHA-256 fingerprint is served at starlingmap.app/.well-known/assetlinks.json. Reproducible: a clean checkout of tag v0.4.0 (npm ci, bash tools/sync-vendor.sh, ./gradlew assembleRelease in android/) yields an unsigned APK with sha256 6ad4533c4a9a71a3b846d9d53a05d56a877fa96b5386bc5f32522a7d6b962341, and signing with the same key yields this exact file:
ebc95c6a6573e0733a47acd600a08f49242c4cb9ddc93298866da8af36e8e9b1 starling-0.4.0.apk