Disambiguate between UCAN capabilities that are introduced through delegation vs. introduced "via parenthood" #21
Description
From just looking at a single UCAN (disregarding its prf
section), it's impossible to figure out whether a certain capability was meant to be introduced "by parenthood" ("through ambient authority") or delegated from one of its proofs.
Problematic Example
Let's assume a malicious actor "Mallory" and an honest actor "Alice".
Mallory has access to their own WNFS (mallory.fission.name/public/") by ambient authority. Alice has access to her email address (
alice@email.com`) by ambient authority.
Alice requests access to "Mallory"'s public WNFS. Mallory gives her this UCAN:
eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsInVjdiI6IjAuNy4wIn0.eyJhdWQiOiJkaWQ6a2V5Ono2TWtrODliQzNKclZxS2llNzFZRWNjNU0xU01WeHVDZ054NnpMWjhTWUpzeEFMaSIsImF0dCI6W3sid25mcyI6Im1hbGxvcnkuZmlzc2lvbi5uYW1lL3B1YmxpYy8iLCJjYXAiOiJPVkVSV1JJVEUifSx7ImVtYWlsIjoiYWxpY2VAZW1haWwuY29tIiwiY2FwIjoiU0VORCJ9XSwiZXhwIjoxNzAwMDAwMDAwLCJmY3QiOltdLCJpc3MiOiJkaWQ6a2V5Ono2TWt0YWZaVFJFakprdlY1bWZKeGNMcE5Cb1ZQd0RMaFR1TWc5bmc3ZFk0ek1BTCIsInByZiI6W119.b8V5ey95NIKO5UzsIwyZM0f99HNwOXQ_jrBk3BwB4tgnT1HDEidryfG_oNHbo0ldCDc-vzKV--6EkRv2bNaQBw
Which decodes to roughly this payload:
{
"iss": "did:key:z6MktafZTREjJkvV5mfJxcLpNBoVPwDLhTuMg9ng7dY4zMAL",
"aud": "did:key:z6Mkk89bC3JrVqKie71YEcc5M1SMVxuCgNx6zLZ8SYJsxALi",
"att": [
{
"wnfs": "mallory.fission.name/public/",
"cap": "OVERWRITE"
},
{
"email": "alice@email.com",
"cap": "SEND"
}
],
"exp": 1700000000,
"fct": [],
"prf": []
}
It also includes alice@email.com
as capability, even though Mallory doesn't actually have access to that email address.
However, that shouldn't stop Alice from using this UCAN for writing to Mallory's WNFS. After all, it's possible that at some point, Mallory did have access to alice@email.com
, but for various reasons ambient authority might have changed.
Alice can actually authorize WNFS writes to Mallory's WNFS against the Fission servers just fine, because Fission will ignore the invalid ambient authority in the proof. However, when she attempts to do an atomic action involving both sending an email from her email address as well as changing Mallory's WNFS, she uses this UCAN:
eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsInVjdiI6IjAuNy4wIn0.eyJhdWQiOiJkaWQ6a2V5Ono2TWtueURtQ1FOcndRRHA5clVxS0Y5enRtQmFub2VWdDdZSjZhVmRhcnBidnoxTiIsImF0dCI6W3siZW1haWwiOiJhbGljZUBlbWFpbC5jb20iLCJjYXAiOiJTRU5EIn0seyJ3bmZzIjoibWFsbG9yeS5maXNzaW9uLm5hbWUvcHVibGljLyIsImNhcCI6Ik9WRVJXUklURSJ9XSwiZXhwIjoxNzAwMDAwMDAwLCJmY3QiOltdLCJpc3MiOiJkaWQ6a2V5Ono2TWtrODliQzNKclZxS2llNzFZRWNjNU0xU01WeHVDZ054NnpMWjhTWUpzeEFMaSIsInByZiI6WyJleUpoYkdjaU9pSkZaRVJUUVNJc0luUjVjQ0k2SWtwWFZDSXNJblZqZGlJNklqQXVOeTR3SW4wLmV5SmhkV1FpT2lKa2FXUTZhMlY1T25vMlRXdHJPRGxpUXpOS2NsWnhTMmxsTnpGWlJXTmpOVTB4VTAxV2VIVkRaMDU0Tm5wTVdqaFRXVXB6ZUVGTWFTSXNJbUYwZENJNlczc2lkMjVtY3lJNkltMWhiR3h2Y25rdVptbHpjMmx2Ymk1dVlXMWxMM0IxWW14cFl5OGlMQ0pqWVhBaU9pSlBWa1ZTVjFKSlZFVWlmU3g3SW1WdFlXbHNJam9pWVd4cFkyVkFaVzFoYVd3dVkyOXRJaXdpWTJGd0lqb2lVMFZPUkNKOVhTd2laWGh3SWpveE56QXdNREF3TURBd0xDSm1ZM1FpT2x0ZExDSnBjM01pT2lKa2FXUTZhMlY1T25vMlRXdDBZV1phVkZKRmFrcHJkbFkxYldaS2VHTk1jRTVDYjFaUWQwUk1hRlIxVFdjNWJtYzNaRmswZWsxQlRDSXNJbkJ5WmlJNlcxMTkuYjhWNWV5OTVOSUtPNVV6c0l3eVpNMGY5OUhOd09YUV9qckJrM0J3QjR0Z25UMUhERWlkcnlmR19vTkhibzBsZENEYy12ektWLS02RWtSdjJiTmFRQnciXX0.cnTHsgARxkGTopzRj-BhnPsA5rep1tSlXxhYQUflwrQtagiy90zcCTFqDaGODKvN5V2uKKuTdWaDaXwr0H59Bw
Which roughly decodes to this:
{
"iss": "did:key:z6Mkk89bC3JrVqKie71YEcc5M1SMVxuCgNx6zLZ8SYJsxALi",
"aud": "did:key:z6MknyDmCQNrwQDp9rUqKF9ztmBanoeVt7YJ6aVdarpbvz1N",
"att": [
{
"email": "alice@email.com",
"cap": "SEND"
},
{
"wnfs": "mallory.fission.name/public/",
"cap": "OVERWRITE"
}
],
"exp": 1700000000,
"fct": [],
"prf": [
"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsInVjdiI6IjAuNy4wIn0.eyJhdWQiOiJkaWQ6a2V5Ono2TWtrODliQzNKclZxS2llNzFZRWNjNU0xU01WeHVDZ054NnpMWjhTWUpzeEFMaSIsImF0dCI6W3sid25mcyI6Im1hbGxvcnkuZmlzc2lvbi5uYW1lL3B1YmxpYy8iLCJjYXAiOiJPVkVSV1JJVEUifSx7ImVtYWlsIjoiYWxpY2VAZW1haWwuY29tIiwiY2FwIjoiU0VORCJ9XSwiZXhwIjoxNzAwMDAwMDAwLCJmY3QiOltdLCJpc3MiOiJkaWQ6a2V5Ono2TWt0YWZaVFJFakprdlY1bWZKeGNMcE5Cb1ZQd0RMaFR1TWc5bmc3ZFk0ek1BTCIsInByZiI6W119.b8V5ey95NIKO5UzsIwyZM0f99HNwOXQ_jrBk3BwB4tgnT1HDEidryfG_oNHbo0ldCDc-vzKV--6EkRv2bNaQBw"
]
}
However, upon validating this UCAN's capabilities, a validator will assume that the email capability was meant to be delegated from Mallory, but Mallory doesn't have access to that email address.
In short: Validation fails, even though Alice should have gained access not by delegation, but by ambient authority. It's the ambiguity that prevents her from using her capability this way.
Solution
Capabilities should be marked with whether they're introduced by parenthood ("through ambient authority") or not, in which case they're assumed to be delegated from one or more capabilities in the proofs.
There's a few options for what this could look like concretely:
- Add an optional field
prt: true
("by parenthood: true") oramb: true
("by ambient authority") to capabilities - Split capabilities into two sections in the payload/claims. The existing section for attenutations under
att
indicates capabilities delegated from proofs. Another section is added undercap
("capabilities") oramb
("ambient authority") - ?
Bikeshedding for names is very much appreciated!
Related
This also makes it easier for UCAN libraries to tell whether a capability is actually invalid and provide an error message to developers in these cases. As long as the ambiguity exists, libraries can't error out on capabilities which weren't delegated, because they have to assume they've been introduced by parenthood instead. (I feel this point is related to @Gozala's design in ucan-wg/ts-ucan#21: We can't provide much better error messages, because the semantics allow lots of ambiguity).