Repository navigation
v2.103.1 — security: audit findings 001, 003, 004, 005
An independent audit of v2.103.0 raised 1 Critical, 9 High, 5 Medium, 4 Low and 5 Informational findings. This release fixes the Critical and the three High findings that belong to Communities.
Every finding was checked against the source before being acted on. All four were exactly as reported.
A peer could claim another peer's identities — Critical
The cross-port session handler chose which peer to talk to from the request, but took the principal's namespace from the answering peer's own claim. A cross-port identity is keyed on (home_node, home_user_id), so any active peer could answer the code exchange with a user id in another peer's namespace and be handed a session on that person's existing account — inheriting every Community role attached to it.
The home-node standing check introduced in v2.100.0 offered no protection, because it reads the same home_node the attacker supplied. The control intended to protect remote membership was satisfied by the attacker's own assertion.
A peer now speaks for its own users and nobody else's: a response naming a different home node is refused outright rather than reconciled, and a pending remote invitation binds only within the authenticated namespace.
The regression test was confirmed to fail with the fix disabled, so it catches the vulnerability rather than passing for reasons of its own.
Every renewal path asks the home node — High
/api/auth/token/refresh was gated on home-node standing in v2.100.0. /api/auth/renew mints a session too, and was not. Somebody banned or deleted at home could simply renew there instead and keep their Community authority for as long as their peer stayed paired.
A revocation control with a second door beside it is not a revocation control.
Role priority could be raised above the owner — High
The guard judged a role's current priority and its proposed permissions, and never saw the proposed priority. An administrator could take a harmless role they already held, lift it above the owner, and use their existing powers to remove them. The escalation required no capability nobody had granted — only a number the guard never looked at.
The evaluator now judges the role it is about to become, and refuses a priority that is not a whole number rather than coercing one.
Removal now revokes — High
Role grants survived every exit, so a removed administrator could rejoin a public Community through the ordinary join route and be an administrator again. Removal that the removed person can undo is not removal.
removed and banned now revoke the grants and record what was taken in the audit log. left keeps them, because leaving is the member's own decision and returning to the rank you set down is reasonable. Those two shared one code path and one behaviour, which is how the unsafe half went unnoticed. A last-owner guard was also added to removal and ban.
Everything else the audit found
Recorded in docs/communities/01-threat-model.md §11 with its status rather than left to be guessed at — including five High findings inherited from wave federation, WebSocket authentication and upload handling. Those affect every wave on a node rather than only Communities, and are a separate decision.
Verification
Suite 256 → 261. No migration.