Surfaced while fixing the fail-closed seal (#168/#170).
Gap
The natural flow is: create KB with content → kb-share → kb-set-encryption e2e. The share transmits node
content as plaintext (legitimately — the KB is unencrypted at that point), so the daemon holds plaintext
kb:{node} docs. Enabling E2e does NOT retroactively re-seal that existing content — only subsequent EDITS
seal (via the now-fail-closed kb/node_update). So historical, un-edited node content stays readable by the
key-blind daemon after enable.
#170 stops the re-share from RE-leaking, and #168 stops new edits from leaking — but neither retro-protects the
content that was shared before enable.
Fix (re-encryption-on-enable)
When kb-set-encryption e2e runs (KbSetEncryption handler, after the content key is generated): re-seal every
existing node — author a sealed kb/node_update (full node state) for each node so the daemon's kb:{node}
becomes the op-set, replacing the plaintext. The editor side iterates the KB's nodes; the network task seals
them under the new key. Joiners then receive only ciphertext.
Workaround until then (document)
Enable E2e on an EMPTY KB before adding content, or treat pre-enable content as not-confidential.
Severity
HIGH — the natural share→enable flow leaves existing content unprotected. Not an active new-content leak
(those are #168/#170, fixed), but a confidentiality gap for historical content.
Surfaced while fixing the fail-closed seal (#168/#170).
Gap
The natural flow is: create KB with content →
kb-share→kb-set-encryption e2e. The share transmits nodecontent as plaintext (legitimately — the KB is unencrypted at that point), so the daemon holds plaintext
kb:{node}docs. Enabling E2e does NOT retroactively re-seal that existing content — only subsequent EDITSseal (via the now-fail-closed
kb/node_update). So historical, un-edited node content stays readable by thekey-blind daemon after enable.
#170 stops the re-share from RE-leaking, and #168 stops new edits from leaking — but neither retro-protects the
content that was shared before enable.
Fix (re-encryption-on-enable)
When
kb-set-encryption e2eruns (KbSetEncryption handler, after the content key is generated): re-seal everyexisting node — author a sealed
kb/node_update(full node state) for each node so the daemon'skb:{node}becomes the op-set, replacing the plaintext. The editor side iterates the KB's nodes; the network task seals
them under the new key. Joiners then receive only ciphertext.
Workaround until then (document)
Enable E2e on an EMPTY KB before adding content, or treat pre-enable content as not-confidential.
Severity
HIGH — the natural share→enable flow leaves existing content unprotected. Not an active new-content leak
(those are #168/#170, fixed), but a confidentiality gap for historical content.