A certificate as defined in section 8.2 consists of publicKey, grant, and signature. There is no expiry field, no serial number, and the spec defines no revocation mechanism anywhere. Consequences:
-
Grants are cryptographically eternal. Once a profile signs a certificate granting e.g. post/comment/react to a device or peer, any client that ever sees a signature chain containing that certificate will validate it forever. If the delegated key is stolen (lost phone, compromised peer client), content signed with it remains indistinguishable from authorized content indefinitely.
-
The only mitigation today is server-side, not cryptographic. A profile server can stop issuing publishing tokens for a withdrawn key (the 403 case in §15.3), which blocks new publishing through that profile's own publish endpoint. But consuming clients verifying already-distributed signed objects have no way to learn that a certificate was withdrawn, and nothing stops the key holder from signing objects that get distributed through other channels.
-
This interacts badly with the grant/ca permissions: a stolen key holding ca can mint further eternal certificates.
Suggested direction
- Add an optional (recommended)
expires timestamp to the certificate object, included in the signed payload. Verifiers reject expired certificates for content whose authenticated createts is after expiry. This bounds damage cheaply and requires no new infrastructure.
- Consider a profile-published revocation list: a signed document (e.g. referenced from the profile root) listing revoked certificate key ids. Clients that can reach the profile check it; offline verification degrades gracefully to expiry-only.
- At minimum, document the current lifetime semantics explicitly so implementers and users understand that issuing a certificate is a permanent act under the current spec.
*Disclosure: this finding came out of an AI-assisted review of the spec; I have verified the certificate object definition against the current master text.*
A certificate as defined in section 8.2 consists of
publicKey,grant, andsignature. There is no expiry field, no serial number, and the spec defines no revocation mechanism anywhere. Consequences:Grants are cryptographically eternal. Once a profile signs a certificate granting e.g.
post/comment/reactto a device or peer, any client that ever sees a signature chain containing that certificate will validate it forever. If the delegated key is stolen (lost phone, compromised peer client), content signed with it remains indistinguishable from authorized content indefinitely.The only mitigation today is server-side, not cryptographic. A profile server can stop issuing publishing tokens for a withdrawn key (the 403 case in §15.3), which blocks new publishing through that profile's own publish endpoint. But consuming clients verifying already-distributed signed objects have no way to learn that a certificate was withdrawn, and nothing stops the key holder from signing objects that get distributed through other channels.
This interacts badly with the
grant/capermissions: a stolen key holdingcacan mint further eternal certificates.Suggested direction
- Add an optional (recommended)
- Consider a profile-published revocation list: a signed document (e.g. referenced from the profile root) listing revoked certificate key ids. Clients that can reach the profile check it; offline verification degrades gracefully to expiry-only.
- At minimum, document the current lifetime semantics explicitly so implementers and users understand that issuing a certificate is a permanent act under the current spec.
*Disclosure: this finding came out of an AI-assisted review of the spec; I have verified the certificate object definition against the current master text.*expirestimestamp to the certificate object, included in the signed payload. Verifiers reject expired certificates for content whose authenticatedcreatetsis after expiry. This bounds damage cheaply and requires no new infrastructure.