Some checks are pending
ci / test (pull_request) Waiting to run
Wire format lives in docs/PROTOCOL.md so the handshake, invite, and frames can be read without the Rust. Threat model points at it. The in-house audit notes are a finding-status table, not a third-party audit. SDK README no longer claims the legacy concat invite signature is what we encode.
39 lines
2.4 KiB
Markdown
39 lines
2.4 KiB
Markdown
# OnionWire security notes
|
||
|
||
**This is not a public third-party audit.** It is an in-house review of
|
||
commit `2b42864` plus a status check against the current tree. Do not cite it
|
||
as “audited.”
|
||
|
||
Protocol: [PROTOCOL.md](PROTOCOL.md). Claims: [THREAT_MODEL.md](THREAT_MODEL.md).
|
||
|
||
Original pass: rust-dev, no live hidden service / live wallet. Ignored tests
|
||
(`rotate_hs`, `tor_hs`, `two_node`) were not run.
|
||
|
||
## Finding status (vs current tree)
|
||
|
||
| Id | Original | Now |
|
||
|---|---|---|
|
||
| F1 receipt `verified` on OR-match | High — txid **or** addr+amount | **Fixed.** `transfers_match` requires txid ∧ amount ∧ address, all non-empty. |
|
||
| F2 chat AEAD empty AAD | Medium — row swap | **Fixed.** AAD `owmsg1 \|\| friend_id_le64 \|\| dir \|\| 0x00 \|\| row_id_le64`. |
|
||
| F3 invite concat signature | Medium — field shift | **Fixed on encode.** Domain tag `onionwire-invite-v1` + `0x00` separators. Decode still **accepts** legacy concat so old invites work. |
|
||
| F4 Monero address shape-only | Medium | **Fixed.** Base58 + Keccak checksum + network prefixes. |
|
||
| F5 wallet RPC no auth | Medium | **Fixed.** HTTP Digest required; open RPC refused; 1 MiB read cap; `.onion` RPC URLs refused. |
|
||
| F6 `/wipe` skipped payments | Low | **Fixed.** `/wipe` also `DELETE FROM payments` + WAL checkpoint. Still not forensic. |
|
||
| F7 HS logs unredacted onion | Low | **Fixed.** stderr uses a redacted label. `dangerously_trust_everyone` remains on Arti storage only. |
|
||
| F8 threat model vs F1–F3 | Low | **Fixed** in [THREAT_MODEL.md](THREAT_MODEL.md) when the code landed. |
|
||
|
||
## Still true / not a “finding we forgot”
|
||
|
||
- Identity secret key and roster (pubkeys + locators) are **plaintext** in sqlite. Chat bodies are not. Seized laptop without FDE yields who you are and who you talk to.
|
||
- Arti onion services are experimental. Fail closed; no C-tor fallback.
|
||
- No public third-party audit, no `cargo-audit` gate in CI as of the original pass.
|
||
- Invite decode still accepts the legacy concat signature (compatibility).
|
||
- Rate limit is availability, not traffic-analysis defense.
|
||
- One-shot sessions: no channel binding across file chunks beyond “same Noise peer.”
|
||
|
||
## Verified correct (original pass, still the protocol)
|
||
|
||
Noise is `Noise_IK_25519_ChaChaPoly_BLAKE2s`, prologue `onionwire-v1`, 96-byte
|
||
identity proofs, loc/prf/inv/rcp signed under the session identity, unknown
|
||
`[a-z]{3} ` prefixes dropped, frames length-checked before allocate. See
|
||
[PROTOCOL.md](PROTOCOL.md).
|