From 97057a6221f1c48d05276bdb9b8a8f51397cd494 Mon Sep 17 00:00:00 2001 From: bordumb Date: Sun, 21 Jun 2026 23:10:42 +0100 Subject: [PATCH] verify: note that a capless delegator scope is unconstrained MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The capability-attenuation check only runs when the delegator-anchored scope has a non-empty capability list. An empty list therefore means unconstrained, not deny-all — every claimed capability passes. That is by design (the scope is advisory authorization and a delegator may choose not to constrain a delegate), but the intent should be explicit so the empty case is never mistaken for a fail-closed one. Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd Auths-Device: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd Auths-Anchor-Seq: 1 --- crates/auths-verifier/src/commit_kel.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/auths-verifier/src/commit_kel.rs b/crates/auths-verifier/src/commit_kel.rs index 80f5f66e..50c836de 100644 --- a/crates/auths-verifier/src/commit_kel.rs +++ b/crates/auths-verifier/src/commit_kel.rs @@ -898,6 +898,12 @@ fn reject_unauthorized_delegate( } // Capability attenuation is time-independent: a delegate may never exceed the // delegator-anchored scope, so it is enforced whether or not a time is given. + // + // Accepted risk: an empty delegator-anchored capability list means UNCONSTRAINED, not + // "deny all" — with nothing to attenuate against, every claimed capability passes. This is + // by design: the scope is advisory authorization, and a delegator that anchors a capless + // scope is choosing not to constrain the delegate. A capless grant is therefore as + // powerful as the delegator; constrain a delegate by anchoring a non-empty capability set. if !scope.capabilities.is_empty() { for claimed in parse_scope_claim(commit_bytes) { if !scope.capabilities.iter().any(|c| c.as_str() == claimed) {