Root holder notice: replay on a fresh node, a trust root that pins a fake root, and the root in the join #114

Open
opened 2026-10-08 22:27:42 -03:00 by marcos-mendez · 0 comments
marcos-mendez commented 2026-10-08 22:27:42 -03:00 (Migrated from github.com)

Found in the security review of #112 (keel#105). Three follow-ups to the holder notice of keel/mesh/rootholder.py.

  1. Replay of an old notice on a fresh node (L1). A node that keeps no notice takes any notice signed by the root, also an old one that names a former holder address. The time bound of #112 refuses a notice dated more than 5 minutes ahead, but not an old one. Possible fixes: refuse a notice older than a maximum age and let the holder sign it again regularly; or put the notice in the join answer, so a new node starts from a current one.
  2. A compromised trust root can pin a fake root (L3). A node with no root certificate takes one from a roster it fetched from a trust root. A trust root that is compromised can give a self-signed CA with the mesh root's name. The node keeps it for good, and then trusts notices and database leaves under it. Possible fixes: the 0051 trust bundle, or a root fingerprint carried in the invite token or join answer.
  3. The root certificate should come in the invite and join exchange. Today a node that is no etcd member learns the root only from rosters, and a node that has learned no root takes the root that comes with its database grant. The join answer is authenticated by the invite's HMAC. It should carry the root certificate and the current holder notice for every joining node, so that a node never needs trust on first use. When this is done, keel.system.dbtls can refuse a grant when no root is known.
Found in the security review of #112 (keel#105). Three follow-ups to the holder notice of `keel/mesh/rootholder.py`. 1. **Replay of an old notice on a fresh node (L1).** A node that keeps no notice takes any notice signed by the root, also an old one that names a former holder address. The time bound of #112 refuses a notice dated more than 5 minutes ahead, but not an old one. Possible fixes: refuse a notice older than a maximum age and let the holder sign it again regularly; or put the notice in the join answer, so a new node starts from a current one. 2. **A compromised trust root can pin a fake root (L3).** A node with no root certificate takes one from a roster it fetched from a trust root. A trust root that is compromised can give a self-signed CA with the mesh root's name. The node keeps it for good, and then trusts notices and database leaves under it. Possible fixes: the 0051 trust bundle, or a root fingerprint carried in the invite token or join answer. 3. **The root certificate should come in the invite and join exchange.** Today a node that is no etcd member learns the root only from rosters, and a node that has learned no root takes the root that comes with its database grant. The join answer is authenticated by the invite's HMAC. It should carry the root certificate and the current holder notice for every joining node, so that a node never needs trust on first use. When this is done, `keel.system.dbtls` can refuse a grant when no root is known.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Keel-Linux/keel#114
No description provided.