Use GitHub's private vulnerability reporting on this repository: the Security tab → Report a vulnerability. That is the only channel — there is no security mailing address, deliberately, because a published address nobody monitors is worse than none.
Please do not open a public issue for anything in the list below.
This is a small project. We aim to acknowledge within 72 hours and assess within a week, but that is an intention rather than a guarantee, and it is worth knowing that before you rely on it. If you want credit in the release notes, say so; if you want anonymity, that is fine too.
The interesting attack surface here is not the usual one — there is no server, no account, no user data. It is the path by which content reaches a phone and gets shown as trustworthy.
| Area | Why it matters |
|---|---|
| Signature verification | a bypass means "Verified" can be forged, and the whole trust model is theatre |
| Digest canonicalization | two different packs hashing to the same digest means a signed pack can be swapped |
| Pack validation bypass | a pack that installs while breaking an invariant can show a step with no way out, or no citation |
| Content lint bypass | a way to phrase a withdrawn technique that reads as an instruction but passes the negation check |
| Update path | anything that lets an unsigned or altered pack be treated as signed |
| Data leaving the device | any code path by which an utterance, trace or identifier could be transmitted |
| Permission creep | anything that reintroduces network, location or contacts access into the release build |
Also in scope, and genuinely welcome: routing attacks — an utterance that reliably reaches a
dangerous protocol. "my baby is choking" reaching the adult abdominal-thrust protocol would be a
serious finding, not a mere bug. Report those the same way.
- The app displaying medical guidance you disagree with — that is a content question. Open a
SAFETY:issue instead (see docs/SAFETY.md). - Vulnerabilities in Expo, React Native or Android that we do not control. Report them upstream; tell us if we need to pin or patch.
- Anything requiring physical access to an unlocked device.
- Social engineering of maintainers or reviewers.
If a signing key is compromised:
- The key is added to the revocation list with a
revokedAtdate. - An app update ships the updated trust store; packs signed by that key then report status
revokedand are downgraded to community rather than silently failing. - Affected packs are re-signed under a new key and republished with a version bump.
Users on old app versions keep working — their bundled packs are unaffected — but they stop accepting new content signed by the revoked key once they update.
Private keys are held offline and are never present on any build machine, CI runner or update server. The update infrastructure cannot sign; a full compromise of it can serve a bad pack, and every client will downgrade that pack to community rather than trust it.
- Release Android builds ship without the
INTERNETpermission — there is no network stack for an utterance to escape through. - Location, contacts and camera permissions are explicitly blocked in
app.json. - Protocol packs cannot compute: no expression language, no arithmetic, no code. An untrusted pack is inert data.
- Every verification failure path lands on
community. There is no code path that yieldsverifiedby default, by omission, or by error — asserted row by row inpackages/core/test/signature.test.js.