String processing errors

52 views
Skip to first unread message

Alan Karp

unread,
Apr 14, 2026, 3:38:16 PMApr 14
to cap-...@googlegroups.com, <friam@googlegroups.com>
https://niyikiza.com/posts/map-territory/ lists a number of well-known problems when you deal with strings.  That page nicely explains the problem when you want to grant access to everything in /data.

Map vs. Territory

Let’s look at the core problem:

The Map: The string the LLM gives you. /data/../etc/passwd

The Territory: The inode the OS actually opens. /etc/passwd

The Vulnerability: Security checks usually validate the Map. Execution touches the Territory. When they disagree, attacks slip through.

Is sanitization the best we can do?  Or do capabilities give us something better?  What about more complicated situations, such as SQL queries and JSON schemas?

--------------
Alan Karp

Matt Rice

unread,
Apr 14, 2026, 5:33:34 PMApr 14
to fr...@googlegroups.com, cap-...@googlegroups.com
On Tue, Apr 14, 2026 at 7:38 PM Alan Karp <alan...@gmail.com> wrote:
>
> https://niyikiza.com/posts/map-territory/ lists a number of well-known problems when you deal with strings. That page nicely explains the problem when you want to grant access to everything in /data.
>
> Map vs. Territory
>
> Let’s look at the core problem:
>
> The Map: The string the LLM gives you. /data/../etc/passwd
>

I'm having difficulty finding a specific document that from what I
recall compares unix filesystems to one of keykos/eros/capros
directory objects
but in those systems ".." is not necessarily a thing, there is no
root, no implicit parent pointers, or tree shape.
Directories may be cyclic, forming a directed graph.

I would argue that they do not "solve" this problem, but avoid it entirely
(there exists no mapping of the directory structure to strings including ".."
unless it was intentionally added and given the arbitrary name "..") .

One thing to look at is hybrid capability systems like capsicum which
do attempt to deal with by switching
capability mode and ambient mode, where after entering capability mode
you can no longer turn strings
into capabilities via the filesystem.

Jonathan S. Shapiro

unread,
Apr 14, 2026, 6:09:09 PMApr 14
to cap-...@googlegroups.com, <friam@googlegroups.com>
It's slightly worse than that, because /data might be a symlink to an arbitrary place. In a poorly constructed chroot environment this could be used to trick the passwd program into accessing an entirely fabricated version of /etc/passwd.

I don't think this is an "it should be a capability approach" situation. Ambient authority is involved at each traversal step (at least in UNIX descendents), but almost any problem you can introduce by exploiting ambient authority can also be introduced by exploiting name re-bindings. Name spaces and bindings are much harder to get right than people tend to imagine.

Path canonicalization in UNIX variants is such a well known problem that different shells do not agree on how they canonicalize paths before opening/accessing. Some handle it textually while others walk the presented path segment by segment. If the openat() system call is used to do segment-at-a-time traversal, it's constrained by a sequence of stepwise descriptor walks, albeit with ambient access rights. Since opening '/' is a guarded special case due to chroot enforcement, the risk is that canonicalization is neither transactional nor idempotent. Changes in directory entry bindings before, after, or during a walk can lead to different results. This hazard also exists in capability-based implementations.

These days, the standard specification of open(2) actually states how it is supposed to follow these paths, but the behavior in pre-SVR4 editions of UNIX was inconsistently specified or not specified at all.

One could argue - and there are various reasons to consider - that "directory" objects should implement deep hierarchies rather than single level hierarchies, but this doesn't address the idempotency issue.

For extra credit, say what additional issues are introduced by loop-back mount points, both in modern UNIX but especially in Plan-9 where these can be introduced by non-privileged users in name spaces they control. A stiff drink may be helpful before starting; works best if you give it 15 minutes or so to kick in before you start thinking about this one.

It is sometimes a wonder to me how such a bright group of people got almost everything wrong about namespace security and units of operation. The UNIX process model didn't have a well-specified account for the effect of signal arrival on process and system state until... 1988, which Roger Faulkner, Steve Rago, and Ron Gomes nailed that down during the SVR4 /proc work. I poked my nose in a couple of times while working on the associated debugger support, but didn't have a big hand in it. Roger, Brendan Eich, and I extended it further in 1989/90 to add watchpoint handling with specified behavior for Sun's Solaris and SGI's IRIX, respectfully. So far as I'm aware, Linux still doesn't have a fully specified model, though there was work done in ptrace(2) to clean up a bunch of the bigger issues.


Jonathan


--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/cap-talk/CANpA1Z3UwZtWtnyFAS_CpL1VUhCFrDQCxDkW_anWZmz16fdYZA%40mail.gmail.com.

Vinícius dos Santos Oliveira

unread,
Apr 15, 2026, 2:02:45 PMApr 15
to fr...@googlegroups.com, cap-...@googlegroups.com
Em ter., 14 de abr. de 2026 às 16:38, Alan Karp <alan...@gmail.com> escreveu:
> https://niyikiza.com/posts/map-territory/ lists a number of well-known problems when you deal with strings. That page nicely explains the problem when you want to grant access to everything in /data.
>
> Map vs. Territory
>
> Let’s look at the core problem:
>
> The Map: The string the LLM gives you. /data/../etc/passwd
>
> The Territory: The inode the OS actually opens. /etc/passwd
>
> The Vulnerability: Security checks usually validate the Map. Execution touches the Territory. When they disagree, attacks slip through.
>
> Is sanitization the best we can do? Or do capabilities give us something better?

For the specific case of path traversal, you may open /data, and use
the /data file descriptor (a capability) with
openat2/O_RESOLVE_BENEATH. That works on FreeBSD and Linux. Other UNIX
systems don't even bother to give any answer.

On FreeBSD you may even cap_rights_limit() the dirfd for /data, and
any fd acquired from openat on it will inherit the restrictions placed
by cap_rights_limit().

This blog post goes into the history behind O_RESOLVE_BENEATH:
https://val.packett.cool/blog/use-openat/#and-back-to-the-regular-syscall-interfaces

> What about more complicated situations, such as SQL queries and JSON schemas?

Filesystem access isn't ocaps (obviously), but at least there's an
initial idea of delegation. /home/someuser is ACL-checked against
someuser. ACLs might not scale, but the underlying point that I want
to make is that we always viewed subtrees as something meant to be
delegated. /data is no different in this regard. Filesystems have
clear points for delegation (even if the APIs outside FreeBSD/Linux
lag behind). Subtrees are meant to be delegated.

However for SQL queries and JSON schemas... it's not clear to me that
there is anything that is meant for delegation here. The well is too
poisoned in this case.

Alan Karp

unread,
Apr 22, 2026, 1:25:55 PMApr 22
to cap-...@googlegroups.com, <friam@googlegroups.com>
I've been pondering this problem and may have come up with a solution that doesn't rely on string sanitization.  To refresh your memory, Alice delegates to Bob access to everything in /data, even things added after the delegation.  Bob uses that capability to access some object by specifying a string, say "foo.txt".  Alice's machine interprets that request as being for /data/foo.txt.  Great, but what if the string is "../etc/password"?

The basic solution is that the capability to /data only allows asking for a capability to the thing designated by the specified string.  Alice, who knows everything in /data, keeps a map of strings to capabilities.  Bob then uses his /data capability to ask for a capability to foo.txt.  There won't be an entry in the map if he asks for ../etc/password.  You can avoid the round trip to retrieve the capability by having a /data service that accesses the map and forwards the request using the designated capability.

Does this approach solve the problem?  Does it introduce any vulnerabilities?  Can it be adapted to solve other related problems, such as SQL queries?

--------------
Alan Karp


On Tue, Apr 14, 2026 at 12:38 PM Alan Karp <alan...@gmail.com> wrote:

Rob Meijer

unread,
Apr 23, 2026, 7:16:28 AMApr 23
to cap-...@googlegroups.com, <friam@googlegroups.com>
It never grew a user base, so I haven't been doing maintenance on it for years, so not 100% sure it runs in the current python ecosystem (there was a weird issue a few years back, but if you follow the readme, that did the trick). But this is basicly what rumpletree does, not with any map, but with a root sparse-cap (multi rooted), and a single server side key. If it still installs, Play around with rumpelbox a bit. It's a demo tool of pyrumpeltree. As said, it's unmaintained because of a zero size user base AFAIK, but I think it fills your need exactly:


I wanted to make it into a users pace fil-system like MinorFS and MattockFS, but never found time to look  into the locking and random access crypto needs properly.

I'dd be hapy to help anyone wanting to take over the project  to get started, but I'm too filled up with other pet projects right now to work on pyrumpeltree or related stuff for now, so if you are interested in adopting it, or porting it, that would be great, if its indeed the fit that I think it is.

If not, it will stay the unmaintained thing it's now without a FUSE filesysyem implementation on top. 

--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.

Rob Meijer

unread,
Apr 23, 2026, 7:28:15 AMApr 23
to cap-...@googlegroups.com, <friam@googlegroups.com>


On Thu, 23 Apr 2026, 13:16 Rob Meijer, <pib...@gmail.com> wrote:
It never grew a user base, so I haven't been doing maintenance on it for years, so not 100% sure it runs in the current python ecosystem (there was a weird issue a few years back, but if you follow the readme, that did the trick). But this is basicly what rumpletree does, not with any map, but with a root sparse-cap (multi rooted), and a single server side key. If it still installs, Play around with rumpelbox a bit. It's a demo tool of pyrumpeltree. As said, it's unmaintained because of a zero size user base AFAIK, but I think it fills your need exactly:


I wanted to make it into a users pace fil-system like MinorFS and MattockFS, but never found time to look  into the locking and random access crypto needs properly.

I'dd be hapy to help anyone wanting to take over the project  to get started, but I'm too filled up with other pet projects right now to work on pyrumpeltree or related stuff for now, so if you are interested in adopting it, or porting it, that would be great, if its indeed the fit that I think it is.


Just for context, it's a really small project. Just about 150 lines of python for the library and about 300 lines of code for the single codebase demo tools (rumpelbox has a busybox like symlink setup).  Should be easy enough to port or take custody of if it matches your needs, but there are a few mental click moments for many before it makes sense. 

I remember trying to explain it to Zooko many years ago when I didn't have code yet, and failing. But I think explaining it "with" code is probably easier. Especialy because the core of it is only 150 lines. 

Douglas Crockford

unread,
Apr 23, 2026, 7:41:18 AMApr 23
to friam
Te problem is '..'. If you have access to a directory, you also have access to the parent directory and on up. That convenience is  a leak. It should be abolished. 

Matt Rice

unread,
Apr 23, 2026, 6:58:04 PMApr 23
to fr...@googlegroups.com
On Thu, Apr 23, 2026 at 11:41 AM Douglas Crockford
<dou...@crockford.com> wrote:
>
> Te problem is '..'. If you have access to a directory, you also have access to the parent directory and on up. That convenience is a leak. It should be abolished.
>

I say we get rid of '.' or CWD too, static mutable state should be verboten.

Mike Samuel

unread,
Apr 24, 2026, 2:00:24 PMApr 24
to friam
On path traversal attacks, is the root of the problem that path composition idioms are confusable deputies?

I've been working on content composition idioms, and here's an example of how simple, readable non-malicious code can get it wrong:

      let dir = "";  // empty string
      let file = "file.ext";

      // With simple string concatenation, joining a path on '/'
      // leads to a path that is not relative as intended, but
      // is accidentally absolute.
      assert(    "${dir}/${file}" == "/file.ext");

      // But the path tag does better.
      assert(path"${dir}/${file}".posixString == "file.ext");


The footgun in POSIX path syntax is that '/' is overloaded to mean "join path segments" when infix and to mean "root directory" when prefix.

We can defang a lot of path traversal attacks if we disallow parent traversal by default.

      let attack = "../../../../etc/passwd";
      assert(path"session-files/1234/uploads/${attack}".posixString == "/dev/null/zz_Temper_zz");

      let ok = "a/b/../c"; // Internal .. is ok
      assert(path"session-files/1234/uploads/${ok}".posixString == "session-files/1234/uploads/a/c");

But of course `..` that is literal can be privileged over that which comes from an untrusted string since the path function can distinguish the literal, fixed parts from a trusted author from untrusted interpolations..

      let abc = "a/b/c";
      assert(path"${abc}/..".posixString == "a/b");
      //                 ^^ trusted

But once we establish that path"..." can use literal '/' to establish content, we can do other things.  That same path string composition helper allows for explicit opt-in to parent traversal.
Here, the path tag adds `<` as a meta-character to allow opting into parent traversal with limitations.

      let upPath = "../../foo";
      let shortUpPath = "../foo";

      // /<, '<' after a slash, allows for upwards traversal
      assert(path"dir/<${upPath}".posixString == "../foo");
      // </, '<' before the slash, blocks upwards traversal
      assert(path"base</subdir/<${shortUpPath}".posixString == "base/foo");
      //              ^^      ^^
      assert(path"base</subdir/<${upPath}".posixString == "/dev/null/zz_Temper_zz");

Matt Rice

unread,
Apr 24, 2026, 7:16:27 PMApr 24
to fr...@googlegroups.com
I suppose I am a little bit confused, as Norm's original confused
deputy paper doesn't use path rewriting at all,
the paths were apparently absolute (although using a different syntax,
or maybe using shell substitutions I'm not sure which).
So it feels like once we've fixed these path normalization problems we
still have underlying issues to resolve.

One question going back to Alan's original email he asked "Or do
capabilities give us something better?" to which I would ask
what kind of capabilities? The post seems to be LLM centric and using
data channels to transmit capabilities we are limited to password
capabilities. One disadvantage is that we encode password
capabilities typically in a way in which they are not intended to be
human meaningful,
so they wrap a safely usable user interface around the capabilities.
It isn't clear to me that this trick actually works with password/data
capabilities given to AI.


> assert(path"${dir}/${file}".posixString == "file.ext");

I'm not sure what language you're using or the semantics of the path
tag, I assume it is replacing the empty string with "./" and
normalizing
so that it extrapolates to ".//file.ext" -> "./file.ext" ->
"file.ext"? I'm not sure I find it intuitive.
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/e003a52b-1939-45c6-80b6-29715fc864afn%40googlegroups.com.

Alan Karp

unread,
Apr 24, 2026, 7:33:47 PMApr 24
to fr...@googlegroups.com
On Fri, Apr 24, 2026 at 4:16 PM Matt Rice <rat...@gmail.com> wrote:
I suppose I am a little bit confused, as Norm's original confused
deputy paper doesn't use path rewriting at all,
the paths were apparently absolute (although using a different syntax,
or maybe using shell substitutions I'm not sure which).
So it feels like once we've fixed these path normalization problems we
still have underlying issues to resolve.

That's because he didn't need that complication to illustrate the problem.  Alice said compile(a.c, log.txt) even though she lacked permission to write log.txt.  A more realistic example would require tests, such as path normalization, to prevent the attack.

One question going back to Alan's original email he asked "Or do
capabilities give us something better?" to which I would ask
what kind of capabilities?

I'm hoping any kind.  My proposed solution says nothing about the type of capability.
 
The post seems to be LLM centric and using
data channels to transmit capabilities we are limited to password
capabilities. 

I certainly didn't intend to be LLM centric.
 
--------------
Alan Karp

Matt Rice

unread,
Apr 24, 2026, 10:37:49 PMApr 24
to fr...@googlegroups.com
On Fri, Apr 24, 2026 at 11:33 PM Alan Karp <alan...@gmail.com> wrote:
>
> On Fri, Apr 24, 2026 at 4:16 PM Matt Rice <rat...@gmail.com> wrote:
>>
>> I suppose I am a little bit confused, as Norm's original confused
>> deputy paper doesn't use path rewriting at all,
>> the paths were apparently absolute (although using a different syntax,
>> or maybe using shell substitutions I'm not sure which).
>> So it feels like once we've fixed these path normalization problems we
>> still have underlying issues to resolve.
>
>
> That's because he didn't need that complication to illustrate the problem. Alice said compile(a.c, log.txt) even though she lacked permission to write log.txt. A more realistic example would require tests, such as path normalization, to prevent the attack.
>>

I personally don't find it particularly appetizing, adding a security
model on top of the failed file system access control,
still giving the compiler/deputy an identity with authority, but
attempting to avoid using through path comparisons.

The problem isn't that alice lacked permission, the deputy had
permission despite the fact that it didn't need it to use it on behalf
of alice.
It is easy to prove that the deputy cannot mix up permissions it does
not have, and another thing entirely to prove that tests such as path
normalization are complete in not using that authority on behalf of
alice.

I suppose this whole approach to the solution isn't my cup of tea.

>>
>> One question going back to Alan's original email he asked "Or do
>> capabilities give us something better?" to which I would ask
>> what kind of capabilities?
>
>
> I'm hoping any kind. My proposed solution says nothing about the type of capability.
>
>>
>> The post seems to be LLM centric and using
>> data channels to transmit capabilities we are limited to password
>> capabilities.
>
>
> I certainly didn't intend to be LLM centric.
>

Yeah I meant the article you had linked to...

Alan Karp

unread,
Apr 24, 2026, 11:32:37 PMApr 24
to fr...@googlegroups.com
On Fri, Apr 24, 2026 at 7:37 PM Matt Rice <rat...@gmail.com> wrote:

The problem isn't that alice lacked permission, the deputy had
permission despite the fact that it didn't need it to use it on behalf
of alice.
But the deputy does need to use the log file on behalf of Alice.  Otherwise she couldn't be billed.  
The important factor is who designates the resource.  If the deputy designates it, no problem. 
If someone else does, you've got a vulnerability.
 
It is easy to prove that the deputy cannot mix up permissions it does
not have, and another thing entirely to prove that tests such as path
normalization are complete in not using that authority on behalf of
alice.

Path normalization becomes a factor when you're designating files by strings.
It doesn't enter the picture if you designate by specifying a capability.  That's
why I think my proposed solution works.

--------------
Alan Karp

Matt Rice

unread,
Apr 25, 2026, 2:36:29 AMApr 25
to fr...@googlegroups.com
On Sat, Apr 25, 2026 at 3:32 AM Alan Karp <alan...@gmail.com> wrote:
>
> On Fri, Apr 24, 2026 at 7:37 PM Matt Rice <rat...@gmail.com> wrote:
>>
>>
>> The problem isn't that alice lacked permission, the deputy had
>> permission despite the fact that it didn't need it to use it on behalf
>> of alice.
>
> But the deputy does need to use the log file on behalf of Alice. Otherwise she couldn't be billed.
> The important factor is who designates the resource. If the deputy designates it, no problem.
> If someone else does, you've got a vulnerability.
>

I oversimplified...

At least to me, the interesting thing about the way Norm solved the
problem is that the deputy cannot
really misbehave, it doesn't have the log capabilities when invoked by
alice, it has a closure which can invoke
the log, and in the same way as the *-property papers, has distinct
capability channels and data channels,
with no way to transmit the log capabilities between alice and the
closure containing the log cap.

If the deputy designates it, you're one logic error away from the
deputy becoming confused.
By using the keykos factory style, the deputy is more of an impartial
arbiter between two mutually suspicious parties,
where if both parties trust the factory the instance of the deputy
created cannot transfer capabilities in either direction.

It's the difference between being able to write something which is
properly secure, and the inability to write something which
behaves insecurely/improperly. I don't see how you get anything
resembling the latter with the involvement of a singularly rooted
filesystem.

>>
>> It is easy to prove that the deputy cannot mix up permissions it does
>> not have, and another thing entirely to prove that tests such as path
>> normalization are complete in not using that authority on behalf of
>> alice.
>
>
> Path normalization becomes a factor when you're designating files by strings.
> It doesn't enter the picture if you designate by specifying a capability. That's
> why I think my proposed solution works.
>
> --------------
> Alan Karp
>
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z1753BeztMGcbwK3EKknkn1SAhcyOFB3Y_YiUzjasUrWw%40mail.gmail.com.

Alan Karp

unread,
Apr 25, 2026, 5:51:09 PMApr 25
to fr...@googlegroups.com
On Fri, Apr 24, 2026 at 11:36 PM Matt Rice <rat...@gmail.com> wrote:

At least to me, the interesting thing about the way Norm solved the
problem is that the deputy cannot
really misbehave, it doesn't have the log capabilities when invoked by
alice, it has a closure which can invoke
the log, and in the same way as the *-property papers, has distinct
capability channels and data channels,
with no way to transmit the log capabilities between alice and the
closure containing the log cap.

That's not my understanding.  The deputy necessarily has permission to write the log
when invoked by Alice.  The deputy can be confused if it allows Alice to designate
where the output goes.  She can't designate writing to the log in a capability system.

If the deputy designates it, you're one logic error away from the
deputy becoming confused.

What you've described is a bug, not a vulnerability.

By using the keykos factory style, the deputy is more of an impartial
arbiter between two mutually suspicious parties,
where if both parties trust the factory the instance of the deputy
created cannot transfer capabilities in either direction.

You don't need a factory to explain why capabilities aren't subject to the 
confused deputy vulnerability.

--------------
Alan Karp

Matt Rice

unread,
Apr 25, 2026, 6:13:52 PMApr 25
to fr...@googlegroups.com
I'm not saying you need it, but e.g. given that you can recreate the
confused deputy in a capability system just by sharing a hash table or
any other tree structure, building a system based on passing string
identifiers seems like it would really toe the line.

When relying on a pattern like the factory we can get the factory
right one time, whereas when relying on the logic of the deputy to get
things,
we must get each deputy right every time (across different teams &
projects.)... anyhow I guess neither of us are likely to sway the
other,
I feel like anything relying on string passing for it to be correct is
going to be too nuanced for the average vibe coder to get right.
Whether it is technically required or not misuse resistance has its
place....

Raoul Duke

unread,
Apr 25, 2026, 6:57:50 PMApr 25
to fr...@googlegroups.com
Sorry, pretty please re-state the 2 options, I for one am unclear on the sides. (Personally, would prefer an obviously-no-bugs approach in any security decision.)

Alan Karp

unread,
Apr 25, 2026, 7:03:41 PMApr 25
to fr...@googlegroups.com
On Sat, Apr 25, 2026 at 3:13 PM Matt Rice <rat...@gmail.com> wrote:

I'm not saying you need it, but e.g. given that you can recreate the
confused deputy in a capability system just by sharing a hash table or
any other tree structure, building a system based on passing string
identifiers seems like it would really toe the line.

You cannot recreate the confused deputy vulnerability in a properly constructed 
capability system.  You can only get the vulnerability if a capability can designate 
more than a single resource, which is something I managed to do in my first capability 
system and something that I've found in other systems, such as an early version of UCAN.

When relying on a pattern like the factory we can get the factory
right one time, whereas when relying on the logic of the deputy to get
things,
we must get each deputy right every time (across different teams &
projects.)... anyhow I guess neither of us are likely to sway the
other,
I feel like anything relying on string passing for it to be correct is
going to be too nuanced for the average vibe coder to get right.
Whether it is technically required or not misuse resistance has its
place....

That's not my understanding of the value of factories.  Using an application
produced by a factory means you don't have to trust the behavior of the 
application.  The factory provides those guarantees.  I got that from Norm's example 
of a factory that guarantees that one of its calculators doesn't steal your data.

--------------
Alan Karp

Alan Karp

unread,
Apr 25, 2026, 7:04:28 PMApr 25
to fr...@googlegroups.com
What 2 options are you referring to?

--------------
Alan Karp


On Sat, Apr 25, 2026 at 3:57 PM Raoul Duke <rao...@gmail.com> wrote:
Sorry, pretty please re-state the 2 options, I for one am unclear on the sides. (Personally, would prefer an obviously-no-bugs approach in any security decision.)

--
You received this message because you are subscribed to the Google Groups "friam" group.
To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.

Raoul Duke

unread,
Apr 25, 2026, 7:11:36 PMApr 25
to fr...@googlegroups.com
The Mental Models of Alan vs. Matt :-)

Mike Samuel

unread,
Apr 25, 2026, 7:24:18 PMApr 25
to friam
On Friday, April 24, 2026 at 5:16:27 PM UTC-6 ratmice wrote:

> assert(path"${dir}/${file}".posixString == "file.ext");

I'm not sure what language you're using or the semantics of the path
tag, I assume it is replacing the empty string with "./" and
normalizing
so that it extrapolates to ".//file.ext" -> "./file.ext" ->
"file.ext"? I'm not sure I find it intuitive.

Sorry for the confusion.  The language is Temper, my current project.
The semantics of that expression are that `path` is resolved as an expression and it receives the fixed parts separately from the interpolations in the same way that JavaScript template strings and Python PEP-750 do.
The `path` function produces a Path class instance and it does some normalization but also defaults to disallowing parent traversal by interpolations.

Matt Rice

unread,
Apr 25, 2026, 7:31:57 PMApr 25
to fr...@googlegroups.com
On Sat, Apr 25, 2026 at 11:03 PM Alan Karp <alan...@gmail.com> wrote:
>
> On Sat, Apr 25, 2026 at 3:13 PM Matt Rice <rat...@gmail.com> wrote:
>>
>>
>> I'm not saying you need it, but e.g. given that you can recreate the
>> confused deputy in a capability system just by sharing a hash table or
>> any other tree structure, building a system based on passing string
>> identifiers seems like it would really toe the line.
>
>
> You cannot recreate the confused deputy vulnerability in a properly constructed
> capability system. You can only get the vulnerability if a capability can designate
> more than a single resource, which is something I managed to do in my first capability
> system and something that I've found in other systems, such as an early version of UCAN.
>>

I struggle to see how this can be avoided in a system where developers
write applications
which become capabilities... For instance Eros/Coyotos has directory
capabilities which
given strings return capabilities, these are "closely held", they
designate multiple resources and
give capabilties human meaningful names, but sharing them essentially
recreates the problems of having a filesystem.

>> When relying on a pattern like the factory we can get the factory
>> right one time, whereas when relying on the logic of the deputy to get
>> things,
>> we must get each deputy right every time (across different teams &
>> projects.)... anyhow I guess neither of us are likely to sway the
>> other,
>> I feel like anything relying on string passing for it to be correct is
>> going to be too nuanced for the average vibe coder to get right.
>> Whether it is technically required or not misuse resistance has its
>> place....
>
>
> That's not my understanding of the value of factories. Using an application
> produced by a factory means you don't have to trust the behavior of the
> application. The factory provides those guarantees. I got that from Norm's example
> of a factory that guarantees that one of its calculators doesn't steal your data.

That is the common value, I think the confused deputy paper in
particular is using a feature of the keykos factories
(which I don't think was carried on in eros or coyotos) of holes, if
we extend your understanding of the factory to consider capabilities
provided
the creator as well as capability provided by the user. The
application produced by the factory is the deputy.

The job (of the factory) then is to ensure the isolation of the
capabilities provided by the creator from those of the user.
By using holes we can open a *data* channel between the creator and
the user for instance for billing we could allow the creator to
observe an unsigned integer dollar amount or some such that gets
produced by the user's usage. This can be as simple as a fixed size
data channel which bounds the amount of data leakage.

typically there are no holes and no data leakage exactly as you
suggest. But I tend to view the confused deputy as an example of the
usage of holes to provide a more complex scenario where the deputy
serves two mutually suspicious parties, both the creator and the user
while providing some amount of benefit and protection to both.

Sorry, you know... for blathering on and on...

Matt Rice

unread,
Apr 25, 2026, 7:33:52 PMApr 25
to fr...@googlegroups.com
Emphasis on data channel to indicate the lack of a capability channel.

Matt Rice

unread,
Apr 25, 2026, 8:15:26 PMApr 25
to fr...@googlegroups.com
I would say from my point of view, there is a spectrum of mental
models in play here (not all alan's)...

at the very bottom there are crappy designs that are impossible to
write secure software.
Next, there are hybrid capability systems which attempt to retain the
familiarity of the aforementioned while making it possible to write
something resembling secure software.
Followed by systems where it is possible, and perhaps even natural way
to write software is seen as the secure way.
Lastly, systems which enforce confinement and isolation, which build
secure patterns that cannot be misused.

I was originally viewing this whole topic through the "hybrid" lens, I
have yet to actually see a hybrid system which follows the "the
natural way to build software is the secure way", I believe Alan was
arguing for the "natural way to build software is the secure way".
Me, I'm always in the last camp of patterns of strict confinement... I
am skeptical that a "natural way" system can be built on top of a
hybrid and conceptually filesystem oriented basis, since filesystems
are so prone to misuse and familiar.

I feel like I'm probably pushing back hard on this because I don't
understand where the line actually is between "it's possible to build
secure systems", and "natural way is the secure way", but I don't
think it just being possible to write a secure implementation is
evidence of that being the way people will target the system in
practice. When one has no strict enforcement barriers it feels like a
potential liability to me.

Alan probably just accidentally and perhaps unknowingly wandered in
front of my disdain for mainstream systems...
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CAJ7XQb65wUz-qwYQvryRa7eg9OonB9FPO8S4ws7C0HTUM_ZBZg%40mail.gmail.com.

Raoul Duke

unread,
Apr 25, 2026, 8:54:50 PMApr 25
to fr...@googlegroups.com
If someone can sudo and mess with files, invalidating the hybrid capability layer, then yeah that seems like fig leaf security in the long run

 But really there's probably no such non-hybrid system??? Something almost always exists under the current abstraction. 

e.g. When reading about OS/400 and the "there is no spoon i mean storage hierarchy" approach, i was told that 99% of all things even by sysops are still done in that mode - but, yes, if you really ask, you will hear that in desperate times it is possible to drop below that shangrila to lower level i dividual storage system commands. 

Raoul Duke

unread,
Apr 25, 2026, 8:55:39 PMApr 25
to fr...@googlegroups.com
or it at least points out that full security UX is a many headed hydra

Matt Rice

unread,
Apr 25, 2026, 9:00:00 PMApr 25
to fr...@googlegroups.com
On Sat, Apr 25, 2026 at 11:03 PM Alan Karp <alan...@gmail.com> wrote:
>
> On Sat, Apr 25, 2026 at 3:13 PM Matt Rice <rat...@gmail.com> wrote:
>>
>>
>> I'm not saying you need it, but e.g. given that you can recreate the
>> confused deputy in a capability system just by sharing a hash table or
>> any other tree structure, building a system based on passing string
>> identifiers seems like it would really toe the line.
>
>
> You cannot recreate the confused deputy vulnerability in a properly constructed
> capability system. You can only get the vulnerability if a capability can designate
> more than a single resource, which is something I managed to do in my first capability
> system and something that I've found in other systems, such as an early version of UCAN.
>>

I want to circle back to this "You can only get the vulnerability if a
capability can designate
more than a single resource" statement, and quote from one of your
prior replies to Mark S. Miller.
"I want to give you permission to read everything in /data, even
things created after the delegation. You need a way to designate the
exact item you want to access, say /data/foo." I interpreted that if
"/data" is somehow accessible through a capability and that
it contains "/data/foo", that it somehow must be designating more than
a single resource.

Perhaps I am missing something?

>> When relying on a pattern like the factory we can get the factory
>> right one time, whereas when relying on the logic of the deputy to get
>> things,
>> we must get each deputy right every time (across different teams &
>> projects.)... anyhow I guess neither of us are likely to sway the
>> other,
>> I feel like anything relying on string passing for it to be correct is
>> going to be too nuanced for the average vibe coder to get right.
>> Whether it is technically required or not misuse resistance has its
>> place....
>
>
> That's not my understanding of the value of factories. Using an application
> produced by a factory means you don't have to trust the behavior of the
> application. The factory provides those guarantees. I got that from Norm's example
> of a factory that guarantees that one of its calculators doesn't steal your data.
>
> --------------
> Alan Karp
>
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z2TyyA0zPO0oU-2DDAz9b36cJ05dSZ-qYtHceiwQs%2BKzw%40mail.gmail.com.

Rob Meijer

unread,
Apr 25, 2026, 9:25:20 PMApr 25
to fr...@googlegroups.com
On Sun, Apr 26, 2026 at 1:03 AM Alan Karp <alan...@gmail.com> wrote:
On Sat, Apr 25, 2026 at 3:13 PM Matt Rice <rat...@gmail.com> wrote:

I'm not saying you need it, but e.g. given that you can recreate the
confused deputy in a capability system just by sharing a hash table or
any other tree structure, building a system based on passing string
identifiers seems like it would really toe the line.

You cannot recreate the confused deputy vulnerability in a properly constructed 
capability system.  You can only get the vulnerability if a capability can designate 
more than a single resource, which is something I managed to do in my first capability 
system and something that I've found in other systems, such as an early version of UCAN.

I think capabilities are somewhat orthogonal to the confused deputy problem. I think capabilities attenuate
but on their own don't completely make it impossible. As you may have seen, I tend to think about authority 
in terms of graph theory, mostly because it fits my brain the best, and from that point of view, I feel fundamentally
things like paths are partial path traversal specifications. If the deputy has it's capabilities stored in it's own internal 
authority DAG, AFAICS any client provided path influencing data that determines which capability in that DAG gets picked
by the deputy needs to somehow be vetted to fully prevent the problem. Or am I missing something here? 

I think the easiest way to prevent it is by making some kind of wielder of authority (woa) id the prime/first graph traversal step.
That is, if Alice asks Bob to write to the Carol file, Carol should live in Bob's Alice subgraph, and if the invariants of Bob's
authority graph are chosen right, that subgraph would act as an Alice sandbox for Bob.
  

 

When relying on a pattern like the factory we can get the factory
right one time, whereas when relying on the logic of the deputy to get
things,
we must get each deputy right every time (across different teams &
projects.)... anyhow I guess neither of us are likely to sway the
other,
I feel like anything relying on string passing for it to be correct is
going to be too nuanced for the average vibe coder to get right.
Whether it is technically required or not misuse resistance has its
place....

That's not my understanding of the value of factories.  Using an application
produced by a factory means you don't have to trust the behavior of the 
application.  The factory provides those guarantees.  I got that from Norm's example 
of a factory that guarantees that one of its calculators doesn't steal your data.

--------------
Alan Karp

--
You received this message because you are subscribed to the Google Groups "friam" group.
To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.

Matt Rice

unread,
Apr 25, 2026, 10:46:08 PMApr 25
to fr...@googlegroups.com
On Sun, Apr 26, 2026 at 1:25 AM Rob Meijer <pib...@gmail.com> wrote:
>
>
>
> On Sun, Apr 26, 2026 at 1:03 AM Alan Karp <alan...@gmail.com> wrote:
>>
>> On Sat, Apr 25, 2026 at 3:13 PM Matt Rice <rat...@gmail.com> wrote:
>>>
>>>
>>> I'm not saying you need it, but e.g. given that you can recreate the
>>> confused deputy in a capability system just by sharing a hash table or
>>> any other tree structure, building a system based on passing string
>>> identifiers seems like it would really toe the line.
>>
>>
>> You cannot recreate the confused deputy vulnerability in a properly constructed
>> capability system. You can only get the vulnerability if a capability can designate
>> more than a single resource, which is something I managed to do in my first capability
>> system and something that I've found in other systems, such as an early version of UCAN.
>
>
> I think capabilities are somewhat orthogonal to the confused deputy problem. I think capabilities attenuate
> but on their own don't completely make it impossible. As you may have seen, I tend to think about authority
> in terms of graph theory, mostly because it fits my brain the best, and from that point of view, I feel fundamentally
> things like paths are partial path traversal specifications. If the deputy has it's capabilities stored in it's own internal
> authority DAG, AFAICS any client provided path influencing data that determines which capability in that DAG gets picked
> by the deputy needs to somehow be vetted to fully prevent the problem. Or am I missing something here?
>
> I think the easiest way to prevent it is by making some kind of wielder of authority (woa) id the prime/first graph traversal step.
> That is, if Alice asks Bob to write to the Carol file, Carol should live in Bob's Alice subgraph, and if the invariants of Bob's
> authority graph are chosen right, that subgraph would act as an Alice sandbox for Bob.
>

I guess I would just add that another key ingredient required to turn
this into a confused deputy is sharing of the subgraph.
Or I don't think it's enough for a capability to just designate
multiple capabilities, but it must also be shared.
This is what I was alluding to by my "one logic error away from a
confused deputy" (paraphrased) comment, is I was assuming that Alan
had a directory designating multiple capabilities, and that all that
was missing for a confused deputy was the sharing of said directory.
It seems an easy mistake to make in capability systems which typically
promote sharing.


>
>>>
>>>
>>> When relying on a pattern like the factory we can get the factory
>>> right one time, whereas when relying on the logic of the deputy to get
>>> things,
>>> we must get each deputy right every time (across different teams &
>>> projects.)... anyhow I guess neither of us are likely to sway the
>>> other,
>>> I feel like anything relying on string passing for it to be correct is
>>> going to be too nuanced for the average vibe coder to get right.
>>> Whether it is technically required or not misuse resistance has its
>>> place....
>>
>>
>> That's not my understanding of the value of factories. Using an application
>> produced by a factory means you don't have to trust the behavior of the
>> application. The factory provides those guarantees. I got that from Norm's example
>> of a factory that guarantees that one of its calculators doesn't steal your data.
>>
>> --------------
>> Alan Karp
>>
>> --
>> You received this message because you are subscribed to the Google Groups "friam" group.
>> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
>> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z2TyyA0zPO0oU-2DDAz9b36cJ05dSZ-qYtHceiwQs%2BKzw%40mail.gmail.com.
>
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CAMpet1X0Vj2Zkb1Lrs2ZNq7r%2Bw2RkBHdM1i81g9Nqe-%2B149rZw%40mail.gmail.com.

Alan Karp

unread,
Apr 27, 2026, 12:20:38 PMApr 27
to fr...@googlegroups.com
That's a lot of emails on this subject.  Since what they say is based on the same misunderstanding of what I intended to say, I'll try to answer them all here.

First, the confused deputy vulnerability is very simple.  You are vulnerable when you use your permission to access a resource designated by somebody else.  You cannot be using your permission if that designation is a capability.  It doesn't matter how the invoker got  that capability.  Strings, graphs, teleportation.  You are using a permission held by the invoker.

An important point is that a delegation is only a capability if it designates a single resource.  While it's useful to be able to grant access to many resources with a single delegation, that delegation is not a capability because it does not designate a single resource.  That was the point of the example that started this thread, e.g., delegating access to everything in /data.  It showed turning the delegation into a permission to access a particular resource by specifying a string, e.g., "foo.txt" to access /data/foo.txt.  The example went on to show one way that approach fails to prevent the confused deputy vulnerability., e.g., "../etc/passwd" which accesses /etc/passwd with your permissions.  That example does not show that there is some pattern of using capabilities that leads to a confused deputy vulnerability. 

The point of my solution is to use the delegation as permission to get a capability.  You invoke a method on a single delegated resource, e.g., /data, to get a capability on a specific resource by specifying a string, "foo.txt" to get permission to /data/foo.txt.  There's no vulnerability from specifying a string that doesn't correspond to a resource in the delegated resource, e.g. "../etc/passwd" returns a Not Found.  This approach works because the only method on the resource, /data, is to request a capability to a resource inside it.  

I will be at IIW Tuesday through Friday next week with limited time to respond.

--------------
Alan Karp

Richard Gibson

unread,
Apr 27, 2026, 12:43:03 PMApr 27
to fr...@googlegroups.com
What exactly is a capability-based approach helping with here? It seems like the code necessary to reject a "../etc/passwd" capability request against a /data resource is exactly the same as the code necessary to reject a "../etc/passwd" access request. In both cases, the implementation must be aware of dot-dot path segment semantics and incorporate them into its own behavior either directly or indirectly in order to function as intended.

--
You received this message because you are subscribed to the Google Groups "friam" group.
To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.

Matt Rice

unread,
Apr 27, 2026, 1:41:59 PMApr 27
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 4:43 PM Richard Gibson <richard...@gmail.com> wrote:
>
> What exactly is a capability-based approach helping with here? It seems like the code necessary to reject a "../etc/passwd" capability request against a /data resource is exactly the same as the code necessary to reject a "../etc/passwd" access request. In both cases, the implementation must be aware of dot-dot path segment semantics and incorporate them into its own behavior either directly or indirectly in order to function as intended.
>
> On Mon, Apr 27, 2026 at 12:20 PM Alan Karp <alan...@gmail.com> wrote:
>>
>> That's a lot of emails on this subject. Since what they say is based on the same misunderstanding of what I intended to say, I'll try to answer them all here.
>>
>> First, the confused deputy vulnerability is very simple. You are vulnerable when you use your permission to access a resource designated by somebody else. You cannot be using your permission if that designation is a capability. It doesn't matter how the invoker got that capability. Strings, graphs, teleportation. You are using a permission held by the invoker.
>>
>> An important point is that a delegation is only a capability if it designates a single resource. While it's useful to be able to grant access to many resources with a single delegation, that delegation is not a capability because it does not designate a single resource. That was the point of the example that started this thread, e.g., delegating access to everything in /data. It showed turning the delegation into a permission to access a particular resource by specifying a string, e.g., "foo.txt" to access /data/foo.txt. The example went on to show one way that approach fails to prevent the confused deputy vulnerability., e.g., "../etc/passwd" which accesses /etc/passwd with your permissions. That example does not show that there is some pattern of using capabilities that leads to a confused deputy vulnerability.

I don't feel like whether it is a capability or not is relevant to
whether a confused deputy is happening, the original confused deputy
was occurring on a non-capability system.

>> The point of my solution is to use the delegation as permission to get a capability. You invoke a method on a single delegated resource, e.g., /data, to get a capability on a specific resource by specifying a string, "foo.txt" to get permission to /data/foo.txt. There's no vulnerability from specifying a string that doesn't correspond to a resource in the delegated resource, e.g. "../etc/passwd" returns a Not Found. This approach works because the only method on the resource, /data, is to request a capability to a resource inside it.
>>

Sure, my contention is just that the only thing missing to turn this
into a confused deputy is sharing the directory in a way
that contains resources from multiple sources. When you treat it like
a file system giving it a name "/data" and putting files within it
"/data/foo.txt", expect people to start treating it like a filesystem,
and introducing confused deputies. I don't dispute that you can use it
right,
in a way that doesn't introduce a vulnerability. My contention is more
with the presentation, as though it were a file system
ensuring that people will fall back on their familiar bad habits which
are bound to reintroduce the problems we're trying to avoid.

>> I will be at IIW Tuesday through Friday next week with limited time to respond.
>>
>> --------------
>> Alan Karp
>>
>> --
>> You received this message because you are subscribed to the Google Groups "friam" group.
>> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
>> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z0kHA05HqDnriSgJ133x%3DZAxdg%2BrTp4Oygv9kn5txdKbQ%40mail.gmail.com.
>
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CALH%2Bfvqc0sBLReOk14RdJ1f4JAJ9c2H2Hm0YxV04VORVqcvV8Q%40mail.gmail.com.

Alan Karp

unread,
Apr 27, 2026, 1:52:14 PMApr 27
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 9:43 AM Richard Gibson <richard...@gmail.com> wrote:
What exactly is a capability-based approach helping with here? It seems like the code necessary to reject a "../etc/passwd" capability request against a /data resource is exactly the same as the code necessary to reject a "../etc/passwd" access request. In both cases, the implementation must be aware of dot-dot path segment semantics and incorporate them into its own behavior either directly or indirectly in order to function as intended.

In a separate thread, Niki Aimable Niyikiza described the difference as selection vs. construction.  In the case that has the vulnerability, the resource is designated by constructing the name, e.g., concatenating /data and ../etc/passwd.  The attack succeeds because the constructed designation is /data/../etc/passwd.  In the case without the vulnerability, the resource is designated by selection from a set.  In this case, asking for ../etc/passwd fails because it is not in the set.

--------------
Alan Karp


Alan Karp

unread,
Apr 27, 2026, 1:58:06 PMApr 27
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 10:42 AM Matt Rice <rat...@gmail.com> wrote:

I don't feel like whether it is a capability or not is relevant to
whether a confused deputy is happening, the original confused deputy
was occurring on a non-capability system.

And the vulnerability cannot happen on a capability system.

Sure, my contention is just that the only thing missing to turn this
into a confused deputy is sharing the directory in a way
that contains resources from multiple sources. When you treat it like
a file system giving it a name "/data" and putting files within it
"/data/foo.txt", expect people to start treating it like a filesystem,
and introducing confused deputies. I don't dispute that you can use it
right,
in a way that doesn't introduce a vulnerability. My contention is more
with the presentation, as though it were a file system
ensuring that people will fall back on their familiar bad habits which
are bound to reintroduce the problems we're trying to avoid.

Not treating it as a file system call is exactly why my solution works.  Instead of saying 
tell me the file name you wish to access, you say give me the entry that matches this 
string.  The attack fails if there's no entry for that string.

--------------
Alan Karp

Matt Rice

unread,
Apr 27, 2026, 2:08:06 PMApr 27
to fr...@googlegroups.com
I'm saying people are going to create that entry themselves.
"data/from_bob.txt", "/data/for_bob.txt", "/data/for_carol.txt", etc.
It helps against giving access accidentally to things not intended to
be in the hierarchy like "/etc/passwd",
but not when the owners of /data reuse the directory for multiple
purposes and conflate the different authorities.

typically in a capability system it won't matter *where* you store capabilities,
you can store the bleach and the ammonia in the same cabinet without
causing any kind
of chemical interaction. In this "/data" example it seems to matter
where you store capabilities.

Alan Karp

unread,
Apr 27, 2026, 7:42:56 PMApr 27
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 11:08 AM Matt Rice <rat...@gmail.com> wrote:

I'm saying people are going to create that entry themselves.
"data/from_bob.txt", "/data/for_bob.txt", "/data/for_carol.txt", etc.
It helps against giving access accidentally to things not intended to
be in the hierarchy like "/etc/passwd",
but not when the owners of /data reuse the directory for multiple
purposes and conflate the different authorities.

Who is "people"?  The way I set up the situation, the names are not meant to
be secret.  Anyone with a /data delegation can ask for any entry by name.  The
capabilities are kept in a hash map maintained by the delegator that only contains
capabilities for things the delegator wanted the delegate to be able to access.  If
you want to separate access, you'd create /data_alice and /data_bob and give 
each their own delegation. 

typically in a capability system it won't matter *where* you store capabilities,
you can store the bleach and the ammonia in the same cabinet without
causing any kind
 of chemical interaction. In this "/data" example it seems to matter
where you store capabilities.

I don't understand.  The individual capabilities are stored together by the delegator.
Where does the "where" come in?

--------------
Alan Karp

Niki Aimable Niyikiza

unread,
Apr 27, 2026, 8:13:42 PMApr 27
to fr...@googlegroups.com

I wrote the map/territory post Alan linked, and I've been working through the same questions in the context of agent tool authorization. There seem to be two layers in play here that I've found useful to keep separate, and I wonder if pulling them apart helps locate where Alan and Matt are actually disagreeing.

The first layer is designation: does the cap unambiguously identify which resource Bob means? In a pure ocap system this is solved by construction, because the cap is the unforgeable reference. On a non-cap-aware substrate like POSIX, designation can be approximated with openat, O_PATH, directory fds, and FreeBSD's cap_rights_limit, which is what Vinícius pointed at. Alan's resolver works at this layer by converting path-string designation, where the kernel re-parses on Bob's behalf, into lookup designation, where Alice's map is the only interpreter. For path traversal specifically, that does seem like a real structural improvement.

The second is interpretation: what does the cap-designated thing mean, what semantics govern operations against it. This is where Matt's bleach-and-ammonia metaphor stops working for me. The metaphor holds for immutable references to immutable resources. Storage really is inert when the things stored don't change. But most useful resources have state, and a cap to a mutable object is a stable reference to a thing whose meaning unfolds over time. Lookup against a Directory returns whatever the Directory currently binds. A read against a file returns whatever bytes the file currently holds. A method invocation on a smart object exercises whatever interface the object currently exposes. The cap is unforgeable but the state isn't. The storage's role in maintaining and mediating that state is the interpretation work, and the designation layer alone doesn't answer it.

A directory isn't a passive cabinet; it's a composite resource with its own semantics, and those semantics shape what counts as well-formed retrieval. KeyKOS Directory objects look clean because the operations are tight and entries are added by deliberate cap-passing rather than ambient activity. Alan's /data is the same shape, but its guarantees vary with the substrate. On a cap-pure substrate the resolver and the kernel are both inside Alice's trust boundary. On POSIX the resolver inherits interpretation work it doesn't directly mediate, and that's where the guarantees weaken. Both are composites; they differ in what they guarantee.

Alan's clarification addresses part of what Matt was pointing at: per-authority separation is per-cap, not per-namespace-entry. The remaining concern, that a string-keyed directory presentation pulls users toward filesystem mental models regardless of the underlying delegation discipline, is about the shape of the design rather than its correctness, and still has force.

The "where you store caps shouldn't matter" argument holds in the limit where storage is genuinely inert, but I'm not sure that limit is reachable in any system that does interpretation at all. KeyKOS comes closest, but a Directory's lookup method is itself an interpretation operation: name in, cap out, against state the kernel mediates and only authorized cap holders can modify. Directories look inert because the operations are tight and the failure modes are well-understood, not because interpretation has been eliminated. The difference between a KeyKOS Directory and a /data resolver on POSIX is how minimal and bounded the interpretation layer is, not whether it exists.

The selection-versus-construction distinction belongs inside the interpretation layer. Selection lets the owner hand caps for pre-validated artifacts. Construction makes the receiver into a trusted interpreter, and the work shifts to bounding what they'll accept. If this split holds up, it locates the disagreement more precisely than asking whether /data is "really" a capability. Alan's resolver does selection-shaped interpretation, and it works when Alice's map is the namespace rather than a derivative view of one. When the map is authoritative, both layers are inside the same trust boundary: Alice's map is the only interpreter, and the cap returned from lookup is the only designation Bob ever holds. Whether the deployment is safe depends on whether the consolidation is complete. On a substrate that does ambient interpretation work outside Alice's resolver, it isn't. That's the version of Matt's concern I think still has force, and it isn't answered by pointing at the designation layer alone.

I'd be interested to hear where this gets the split wrong, or where the literature has already worked this through under different names. The construction case in particular feels like an open problem in a way the selection case doesn't, because there's no pre-existing artifact for the cap to bind to at runtime.

Niki Aimable Niyikiza


--
You received this message because you are subscribed to the Google Groups "friam" group.
To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.

Matt Rice

unread,
Apr 27, 2026, 8:28:18 PMApr 27
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 11:42 PM Alan Karp <alan...@gmail.com> wrote:
>
> On Mon, Apr 27, 2026 at 11:08 AM Matt Rice <rat...@gmail.com> wrote:
>>
>>
>> I'm saying people are going to create that entry themselves.
>> "data/from_bob.txt", "/data/for_bob.txt", "/data/for_carol.txt", etc.
>> It helps against giving access accidentally to things not intended to
>> be in the hierarchy like "/etc/passwd",
>> but not when the owners of /data reuse the directory for multiple
>> purposes and conflate the different authorities.
>
>
> Who is "people"? The way I set up the situation, the names are not meant to
> be secret. Anyone with a /data delegation can ask for any entry by name. The
> capabilities are kept in a hash map maintained by the delegator that only contains
> capabilities for things the delegator wanted the delegate to be able to access. If
> you want to separate access, you'd create /data_alice and /data_bob and give
> each their own delegation.

by "people" I mean average users and developers who are unlikely to
know what a confused deputy is, how to avoid one,
or that to avoid giving access to foo and bar one needs to either
create a separate directory, or not share directories in the first
place.
Sure if you do it *properly* you create separate directories for Bob
and Alice, but that requires you to know better.
Maybe you want to share files with *both* Alice, and Bob, and then at
a later time you want to share a file with *just* Bob,
forgetting that you had previously already given Alice access to
"/data". When you put a new file file for Bob, you implicitly just
gave Alice
access to that new file too.

We both agree it is possible to use this in a way where there is no problem.
I wouldn't assume that people are going to just automatically do it that way.
The pessimist in me believes people are just going to treat this
exactly like a filesystem (problematically) if you present it as one.

It is afterall not too terribly different from e.g. eros and capros
directory cap, sharing those however
was frowned upon, and the directory itself didn't have a path segment
associated with it, that is it would have been
the "foo.txt" within the data directory capability, not really
"/data/foo.txt". (Under these directories really were capabilities
because, well they're kind of pure capability systems so all things
were capabilities). I contend that directories are fine if they are
not shared, and should really be reserved for user interface. There
are some cases where you kind of need to pass directories to programs,
(things like compilers and programming languages)
I contend that those are because programming languages *are* parts of
user interface (This rant is kind of going off course, I say this to
point out that sometimes there are exceptions where it seems OK and we
can't really avoid passing directories around, but it is different
passing a directory to a deputy like a compiler, and sharing one with
another user).

>> typically in a capability system it won't matter *where* you store capabilities,
>> you can store the bleach and the ammonia in the same cabinet without
>> causing any kind
>> of chemical interaction. In this "/data" example it seems to matter
>> where you store capabilities.
>
>
> I don't understand. The individual capabilities are stored together by the delegator.
> Where does the "where" come in?

Where is the directory "/data" if people can query that by name,
"foo.txt", "bar.txt" etc,
"/data" is a where i.e. is a place where we store things. "foo.txt"
and "bar.txt" are both reachable from "/data", every capability within
"/data" being reachable. Hopefully the "/data/for_bob_and_alice.txt"
+ "/data/for_bob_only.txt" example

Anyhow, I kind of feel like I'm repeating myself and probably annoying
everybody so I'm probably going to leave my involvement
in this thread at that, hopefully I've conveyed everything the way I intended.

Matt Rice

unread,
Apr 27, 2026, 9:38:41 PMApr 27
to fr...@googlegroups.com
On Tue, Apr 28, 2026 at 12:13 AM 'Niki Aimable Niyikiza' via friam
<fr...@googlegroups.com> wrote:
>
> I wrote the map/territory post Alan linked, and I've been working through the same questions in the context of agent tool authorization. There seem to be two layers in play here that I've found useful to keep separate, and I wonder if pulling them apart helps locate where Alan and Matt are actually disagreeing.
>
> The first layer is designation: does the cap unambiguously identify which resource Bob means? In a pure ocap system this is solved by construction, because the cap is the unforgeable reference. On a non-cap-aware substrate like POSIX, designation can be approximated with openat, O_PATH, directory fds, and FreeBSD's cap_rights_limit, which is what Vinícius pointed at. Alan's resolver works at this layer by converting path-string designation, where the kernel re-parses on Bob's behalf, into lookup designation, where Alice's map is the only interpreter. For path traversal specifically, that does seem like a real structural improvement.
>
> The second is interpretation: what does the cap-designated thing mean, what semantics govern operations against it. This is where Matt's bleach-and-ammonia metaphor stops working for me.

The bleach-and-ammonia metaphor perhaps isn't a good one, I don't know
what would be a better one, I will try.
If we take bleach and ammonia as a methaphor for designation of a
single resource (each comes in their own separate storage container,
where we want to avoid mixing them).

Perhaps it is better to use the metaphor of a capability-child-safe
home, vs a access control child-safe home.
In a capability-child-safe home you can put the marshmallows (assuming
marshmallows are safe, probably not), the bleach and the ammonia all
in the same cabinet, because putting the marshmallows in the cabinet
doesn't convey authority to the bleach or the ammonia.

While in an access control child-safe house the cabinet has a forall
relationship with it's contents, where forall item in cabinet,
access(cabinet) -> access(item), placing the marshmallows in the
cabinet alone is a grant operation to all those who have been granted
access to the cabinet.

This same relation applies to capability-child-safe home but because
we avoid granting directories we can assume that putting an item in a
directory is a neutral action that does introduce any new nodes in the
access control graph. That is to say that it isn't things like
immutable references to data.
It is actually the dynamism of the access control graph. Capabilities
make access control decisions explicit by requiring explicit grants.
authority granting directories introduces indirect grants upon
placement into the directory.

So it's not that we must avoid putting marshmallows, bleach, and
ammonia in the cabinet, it's that we grant each separately so putting
them in the same cabinet is not a problem. I feel like I might not
have gotten that point across previously.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CALGH9Z-GMp0uxj3fE6sod6QinPdi34HhTg%3DPc0wNu9q96iVr2Q%40mail.gmail.com.

Raoul Duke

unread,
Apr 27, 2026, 11:07:17 PMApr 27
to fr...@googlegroups.com
Starting off absolutist and wanting capabilities to be as atomic as possible 1:1 sounds good in principle. But I guess there quickly becomes a need to support 1:many. The thing then is how "mutable" is the 1:many as the next issue wrt sanity: a fixed set is safer vs. a glob. But then that doesn't work in the real world, either, probably. People want a way to say the set can change. At least the CRUD operations on the set must be secured. 

eg old school paper world, do you lock things up under physical lock and key at the level of:

* individual customer record printout. 
* a single tabbed filing folder of all records for a certain category. 
* a single drawer with multiple hanging folders. 
* a cabinet with more than one drawer. 
* the door to the records store room. 


Matt Rice

unread,
Apr 28, 2026, 2:41:36 AMApr 28
to fr...@googlegroups.com
There are a couple of things I think worth considering, about the
proposed semantics
My understanding of Alan's proposed directory is one such that when he
creates the (potentially empty) directory, and grants it to someone,
"I want to give you permission to read everything in /data, even
things created after the delegation."
then puts a capability in the directory, the capability appears. None
of these real world objects behave like that, it feels incompatible
with confinement.

If there were directories that you could grant, but could not obtain
capabilities through which were not within them at grant time (like a
sensory version of a directory), that might be okay at least I don't
see why not.

That said, It isn't obvious to me that to-many is necessary
throughout. Assuming that to-many exists at the edges e.g. alice, bob,
carol all have directories. None share them, perhaps all can write
scripts that iterate over directories and grant all capabilities
within them, this essentially equivalent to a sensory directory, and
retains the same property that only capabilities that exist at the
time a capability is granted can be obtained through the grant. I feel
like that is a very important property that should be preserved.

For instance, when a new capability is created, it needs to be stored
into someone's organizational structure, and people typically organize
things into piles of to-many relations. Mixing the idea of directories
where some have existing grants, and others do not have such
consequences seems not ideal. A new file should ideally not be shared
until you share it explicitly. I'm pretty skeptical of making the
personal organizational structure and shared organizational structure
the same, because we as humans in general are not good at recognizing
the consequences of sharing while in the midst of the creation of
documents.

A "For bob" folder, might contain unfinished documents which haven't
been sent to him yet, as well as documents which have been.
Perhaps there is some sort of sensory directory that has a
copy-on-write aspect to it, but remembers who the sensory version has
been granted to,
which allows for easy re-granting. That kind of thing would seem to
have all the important aspects I can think of. Explicit grant, easy
regranting on change. It may be something you can do as a user with
your own personal unshared directories using scripts to grant access
to the individual capabilities within, except more convenienter.
*shrug*

Rob Meijer

unread,
Apr 28, 2026, 3:27:48 AMApr 28
to Design


On Mon, 27 Apr 2026, 18:20 Alan Karp, <alan...@gmail.com> wrote:
That's a lot of emails on this subject.  Since what they say is based on the same misunderstanding of what I intended to say, I'll try to answer them all here.

First, the confused deputy vulnerability is very simple.  You are vulnerable when you use your permission to access a resource designated by somebody else.  You cannot be using your permission if that designation is a capability.  It doesn't matter how the invoker got  that capability.  Strings, graphs, teleportation.  You are using a permission held by the invoker.

Yes, if the capability is communicated instead of a full designation. But if the designation is effectively some graph traversal path in the internal data structure of the deputy where it holds its logging and other capabilities, then I think influence by the unprivileged entity on the path chosen by the deputy might still result in a confused deputy. 

In two of my current pet project I'm struggling with this very thing. If the deputy has a failsafe way to distinguish one unprivileged woa (wielder of authority) from another, it can reliably namespace its authority and prevent any confused deputy. If it can't (and in many cases it really can't), there is an attack factor that I'm unable to plug.

 Let me sketch the scenario so you can evaluate if you consider this a confused deputy problem or not. I think it is.

I have two stongly related slow moving incubator stage pet project. A DSL (Domain Specific Language) named Merg-E that aims to be a small but not trivial to use secure parallel language for web 3.0 bots and L2 nodes, and the deputy, a user space file-system named InnuenDo VaultFS. In my model, a woa is a combination of an executable identified by it's path and the user id this ececutable is running as. 
So /usr/bin/mytool@alan would be one woa-id distinct from both /usr/bin/mytool@rob and /usr/bin/other@alan. There is one special tool ivaultadmin that is given higher privile by Innuendo VaultFS, let's say for your processes it has the woa-id /usr/bin/ivaultadmin@alan.  Basicly InnuendoVaultFS allows  
/usr/bin/ivaultadmin@alan to provide secrets that for example only /usr/bin/mytool@alan can read, and other secrets that only /usr/bin/other@alan can read.

When both 
/usr/bin/mytool@alan and /usr/bin/other@alan are compiled binaries or scripts or bytecode run by a 'trusted' interpreter, then the woa-id is reliable and there are no confused deputies. But if for example it is a python code or a java jar, neither python nor java are 'trusted' interpeters in my model, because both allow the code to update argc/argv, meaning any python script runing under a uid can spoof the woa-id of any other python script running as that same uid.
This means that a rogue  
/usr/bin/other@alan python script could trick the deputy (Innuendo VaultFS) into disclosing secrets that belong to the  /usr/bin/mytool@alan python script.

Basically, InnuenDo VaultFS manages a graph and the woa-id designates the prime branches of that graph that should remain isolated. The unpriviledged entity doesn't normally designate that part to address a secret, it is extracted from the OS (/proc/$PID/*) by the deputy, but in case of Python or Java this info can be partially spoofed. 

Would you consider this a confused deputy problem? Or is it only adjacent to the confused deputy problem?



An important point is that a delegation is only a capability if it designates a single resource.  While it's useful to be able to grant access to many resources with a single delegation, that delegation is not a capability because it does not designate a single resource.  That was the point of the example that started this thread, e.g., delegating access to everything in /data.  It showed turning the delegation into a permission to access a particular resource by specifying a string, e.g., "foo.txt" to access /data/foo.txt.  The example went on to show one way that approach fails to prevent the confused deputy vulnerability., e.g., "../etc/passwd" which accesses /etc/passwd with your permissions.  That example does not show that there is some pattern of using capabilities that leads to a confused deputy vulnerability. 

The point of my solution is to use the delegation as permission to get a capability.  You invoke a method on a single delegated resource, e.g., /data, to get a capability on a specific resource by specifying a string, "foo.txt" to get permission to /data/foo.txt.  There's no vulnerability from specifying a string that doesn't correspond to a resource in the delegated resource, e.g. "../etc/passwd" returns a Not Found.  This approach works because the only method on the resource, /data, is to request a capability to a resource inside it.  

I will be at IIW Tuesday through Friday next week with limited time to respond.

--------------
Alan Karp

--
You received this message because you are subscribed to the Google Groups "friam" group.
To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.

Alan Karp

unread,
May 3, 2026, 8:22:58 PM (12 days ago) May 3
to fr...@googlegroups.com
On Mon, Apr 27, 2026 at 8:07 PM Raoul Duke <rao...@gmail.com> wrote:
Starting off absolutist and wanting capabilities to be as atomic as possible 1:1 sounds good in principle. But I guess there quickly becomes a need to support 1:many.

That's the distinction I'm trying to make between a capability and a delegation.  

A capability must designate a specific object, but it's often convenient to delegate access to lots of them.  Some systems want to treat a delegation as a capability, but it's not; it is a way to get a capability to a specific item.  Treating it as a capability leads to the /data/../etc/passwd problem.

--------------
Alan Karp

Alan Karp

unread,
May 3, 2026, 8:31:37 PM (12 days ago) May 3
to fr...@googlegroups.com
On Tue, Apr 28, 2026 at 12:27 AM Rob Meijer <pib...@gmail.com> wrote:
 
In two of my current pet project I'm struggling with this very thing. If the deputy has a failsafe way to distinguish one unprivileged woa (wielder of authority) from another, it can reliably namespace its authority and prevent any confused deputy. If it can't (and in many cases it really can't), there is an attack factor that I'm unable to plug.

 Let me sketch the scenario so you can evaluate if you consider this a confused deputy problem or not. I think it is.

I have two stongly related slow moving incubator stage pet project. A DSL (Domain Specific Language) named Merg-E that aims to be a small but not trivial to use secure parallel language for web 3.0 bots and L2 nodes, and the deputy, a user space file-system named InnuenDo VaultFS. In my model, a woa is a combination of an executable identified by it's path and the user id this ececutable is running as. 
So /usr/bin/mytool@alan would be one woa-id distinct from both /usr/bin/mytool@rob and /usr/bin/other@alan. There is one special tool ivaultadmin that is given higher privile by Innuendo VaultFS, let's say for your processes it has the woa-id /usr/bin/ivaultadmin@alan.  Basicly InnuendoVaultFS allows  
/usr/bin/ivaultadmin@alan to provide secrets that for example only /usr/bin/mytool@alan can read, and other secrets that only /usr/bin/other@alan can read.

When both 
/usr/bin/mytool@alan and /usr/bin/other@alan are compiled binaries or scripts or bytecode run by a 'trusted' interpreter, then the woa-id is reliable and there are no confused deputies. But if for example it is a python code or a java jar, neither python nor java are 'trusted' interpeters in my model, because both allow the code to update argc/argv, meaning any python script runing under a uid can spoof the woa-id of any other python script running as that same uid.
This means that a rogue  
/usr/bin/other@alan python script could trick the deputy (Innuendo VaultFS) into disclosing secrets that belong to the  /usr/bin/mytool@alan python script.

Basically, InnuenDo VaultFS manages a graph and the woa-id designates the prime branches of that graph that should remain isolated. The unpriviledged entity doesn't normally designate that part to address a secret, it is extracted from the OS (/proc/$PID/*) by the deputy, but in case of Python or Java this info can be partially spoofed. 

Would you consider this a confused deputy problem? Or is it only adjacent to the confused deputy problem?

That is not a confused deputy.  It's just a bug.

Be careful.  Using an authentication as part of the access decision, as in your woa check, makes delegation difficult and leads to credential sharing.  I don't think you've made that mistake, but I can't tell for sure. 

--------------
Alan Karp

Raoul Duke

unread,
May 3, 2026, 8:32:05 PM (12 days ago) May 3
to fr...@googlegroups.com
But, what is 'a specific object'? :-)
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z0p-XNXqx77bdQMrv0PhXVshLukOpm%2BCY0HRnxB2HdhGw%40mail.gmail.com.

Raoul Duke

unread,
May 3, 2026, 9:08:44 PM (12 days ago) May 3
to fr...@googlegroups.com
p.s. also to me delegation can be indirection to zero or more other
caps/delegations, and doesn't mean always more than 1.
connotation/denotation natural-language is hard vs. shopping.

Alan Karp

unread,
May 3, 2026, 10:06:19 PM (12 days ago) May 3
to fr...@googlegroups.com
On Sun, May 3, 2026 at 5:32 PM Raoul Duke <rao...@gmail.com> wrote:
But, what is 'a specific object'? :-)
 
In this case a file in /data.  In general, anything covered by the delegation.

--------------
Alan Karp

Raoul Duke

unread,
May 3, 2026, 11:26:00 PM (12 days ago) May 3
to fr...@googlegroups.com
but in unix "everything is a file" even a directory :-)

so maybe a way of saying it that makes more sense to me overall is: it
should be up to the entity that makes the capability and releases it
into the wild, to decide how to classify it as 1:1 vs. 1:many.

and i wouldn't say delegation, i'd say cardinality.

no, so yeah, i know intuitively what you mean, but... the semantics of
what things are will matter / can lead to confusion, bugs, holes,
mistakes, etc. ... ok ok the pedantics get tedious but I would say it
matters, devil in the details, etc.
> --
> You received this message because you are subscribed to the Google Groups "friam" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to friam+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z1hvQ0smj5DJ1sUgRnJh%2B_FL-_W8hJ_yLEeX7GrEgNrJQ%40mail.gmail.com.

Mark S. Miller

unread,
May 4, 2026, 1:23:33 AM (12 days ago) May 4
to fr...@googlegroups.com
I wish I had more time for this thread, but I'm missing much context. In any case, this is also the question at the top of my mind. An object from which one gets other objects is quite common, and is itself an object to be designated by an ocap.

Potential confused deputies hazards happen all the time in ocap systems, but still vastly less often, and with clear red flags. In an ocap system, they happen primarily through rights amplification. Anytime one has a map or weakmap object mapping object identities to whatever, you have rights amplification.

From Capability Myths Demolished:

image.png





--
  Cheers,
  --MarkM

Matt Rice

unread,
May 4, 2026, 3:39:57 AM (12 days ago) May 4
to fr...@googlegroups.com
On Mon, May 4, 2026 at 5:23 AM Mark S. Miller <eri...@gmail.com> wrote:
I wish I had more time for this thread, but I'm missing much context. In any case, this is also the question at the top of my mind. An object from which one gets other objects is quite common, and is itself an object to be designated by an ocap.

Potential confused deputies hazards happen all the time in ocap systems, but still vastly less often, and with clear red flags. In an ocap system, they happen primarily through rights amplification. Anytime one has a map or weakmap object mapping object identities to whatever, you have rights amplification.

I don't know if this will fill in any context from my side, but 

I totally agree with this last paragraph, and it has been one of the main points for why I am skeptical of Alan's filesystem.
One of the things I have been saying is that I've been saying "Shared" map, filesystem etc.
Mark is right that *Anytime* a map could hazard a confused deputy, but it is much less obvious that anyone would confuse themselves with an unshared map, and imo less serious of a concern than a shared map would be.

I think one of the things missing from the graphic in the context of the current conversation most closely related to the arrows in figure 14 that "Property D implies subjects can locally identify authorities", when one uses a shared map they are absolutely *not* using a locally identified authority, but a remotely identified authority. Which puts us way off the Property D happy path.

From what I understand Alan calling this not a capability and instead calling it a delegation is saying that deputies or capabilities shouldn't have
references to directories. It seems to me means it's a hybrid system where not all things are capabilities. Like freebsd + capsicum where
you have a capability subset essentially (but maybe without some unix path normalization problems). But if there is a fence between delegation via directories and capabilities, one side of the fence still seems like a nightmare due to remotely identified authorities.

I feel it's only a matter of time until references to delegations start appearing within deputies, if only because that is exactly what (effectively) everyone (not on these lists) has been taught and knows. 

I don't know if that helps to contextualize anything from my perspective...

Alan Karp

unread,
May 4, 2026, 6:24:08 PM (11 days ago) May 4
to fr...@googlegroups.com
There is an important difference between object-reference-as-capability (ORAC) and certificate-as-capability (CAC).  An ORAC delegation can only grant access to a single object.  That object may contain references to other objects, but there's no way to  directly represent access to many objects.  With CAC, you can delegate permission to an enumeration of individual objects without having an object that contains references to them.  That means a delegation can be distinct from a capability.  

The string processing problem adds another wrinkle; the delegation can be an arbitrary description of the objects, such as all your MPEGs.  How you specify a specific object in that set determines if you have the /data/../etc/passwd problem.

--------------
Alan Karp


Rob Meijer

unread,
May 6, 2026, 1:29:31 AM (10 days ago) May 6
to Design


On Tue, 5 May 2026, 00:24 Alan Karp, <alan...@gmail.com> wrote:
There is an important difference between object-reference-as-capability (ORAC) and certificate-as-capability (CAC).  An ORAC delegation can only grant access to a single object.  That object may contain references to other objects, but there's no way to  directly represent access to many objects.  With CAC, you can delegate permission to an enumeration of individual objects without having an object that contains references to them.  That means a delegation can be distinct from a capability.  


I think both (plus hash-as-capability) are functionally equivalent, with three practical distinctions: 

1) How does attenuation take place? Signing, proxy, or keyless hash. 
2) How does decomposition take place? Signing, direct disclosure or keyed hash. 
2) Where does decomposition take place? Client side, object side or server side. 

With a CAC decomposition and attenuation both happen client side. If Foo has a Bar member, you can create and sign a "Bar" CAC just as you can create and sign a read-only Foo CAC. 

With anb ORAC attenuation happens cliënt side, you can create a read only attenuation proxy for the Foo ORAC, and decomposition happens object side (ask the Foo for it's "Bar"). 

Finaly with a Rumpletree hash as capability (RHAC) , attenuation also happens client side, a hash of the Foo RHAC is the read-only Foo RHAC, and decomposition happens server side, a hash of the read-only Foo RHAC and the name "Bar" with a server secret is the unattenuated Bar RHAC. 

AFAICS, apart from these "how" and "where" details, there doesn't seem to be any conceptual difference in the "what" of either attenuation or decomposition possibilities that would limit a capability type to only be able to grant access to a single object. 

A I missing something? 

Matt Rice

unread,
May 6, 2026, 3:26:29 AM (10 days ago) May 6
to fr...@googlegroups.com
On Tue, May 5, 2026 at 10:29 PM Rob Meijer <pib...@gmail.com> wrote:


On Tue, 5 May 2026, 00:24 Alan Karp, <alan...@gmail.com> wrote:
There is an important difference between object-reference-as-capability (ORAC) and certificate-as-capability (CAC).  An ORAC delegation can only grant access to a single object.  That object may contain references to other objects, but there's no way to  directly represent access to many objects.  With CAC, you can delegate permission to an enumeration of individual objects without having an object that contains references to them.  That means a delegation can be distinct from a capability.  


I think both (plus hash-as-capability) are functionally equivalent, with three practical distinctions: 

1) How does attenuation take place? Signing, proxy, or keyless hash. 
2) How does decomposition take place? Signing, direct disclosure or keyed hash. 
2) Where does decomposition take place? Client side, object side or server side. 

With a CAC decomposition and attenuation both happen client side. If Foo has a Bar member, you can create and sign a "Bar" CAC just as you can create and sign a read-only Foo CAC. 

With anb ORAC attenuation happens cliënt side, you can create a read only attenuation proxy for the Foo ORAC, and decomposition happens object side (ask the Foo for it's "Bar"). 

Finaly with a Rumpletree hash as capability (RHAC) , attenuation also happens client side, a hash of the Foo RHAC is the read-only Foo RHAC, and decomposition happens server side, a hash of the read-only Foo RHAC and the name "Bar" with a server secret is the unattenuated Bar RHAC. 

AFAICS, apart from these "how" and "where" details, there doesn't seem to be any conceptual difference in the "what" of either attenuation or decomposition possibilities that would limit a capability type to only be able to grant access to a single object. 

A I missing something? 

My understanding is that Alan is just saying that addresses are unique, there isn't stopping anything a capability from replying to messages with multiple objects,
or receiving an endpoint and granting multiple objects through that endpoint. I feel like scheme based capability systems like w7, and systems like Emily also have tuples,
so it's pretty easy to have a reference to a pair or tuple.

Further I don't really understand why this distinction matters, we could also delegate in a capability system with (name, capability) pairs, but we don't, and we don't intentionally
because of the "local naming" properties in Marks figure 14, I don't understand what justification there is for delegating this way in certificate systems other than if we're delegating multiple
 capabilities in a single shot you need to distinguish them? That's a separate question than whether or not it's a good idea.

Previously Alan had mentioned another difference than more than just multiple objects, but having mutable delegations. So granting access to objects via prior delegations, 
That also isn't something that is usually done in capability systems, Systems like emily go out of their way to ensure that top-level objects are free of mutable references I think the documentation discusses it.
with the only mutability I'm familiar with in ORAC systems being via revocation, where it may be possible to replace an object with the null capability, but that is a weakening operation.

One other question because I really don't understand the distinction of single objects, is sealer/unsealer *pairs* are the fundamental example of synegy/rights amplification in capabaility systems.
that yes each member of the pair is a single object, but the pair when it is created must come from somewhere, presumably they mkSealerUnsealerPair exists on pure cap systems.
So I really don't understand why this distinction matters. 


Alan Karp

unread,
May 6, 2026, 8:26:13 PM (9 days ago) May 6
to fr...@googlegroups.com
I think you're right.  All these capability systems are functionally equivalent.

You point out something important about systems you probably don't know about.  OAuth 2 is capability-like but it only approximates the properties you list.  That deficiency is causing people to modify the protocols to make them work for AI agents in projects like OAuth 2.1 and AAuth.  Neither is going to work the way those people hope.

--------------
Alan Karp


On Tue, May 5, 2026 at 10:29 PM Rob Meijer <pib...@gmail.com> wrote:

Raoul Duke

unread,
May 6, 2026, 8:41:59 PM (9 days ago) May 6
to fr...@googlegroups.com
Just for a lark: According to Copilot, the best one can do to try to
get along with OAuth 2.1 is, "OAuth tokens become opaque bearer
envelopes, but the capability system lives entirely in the structured
interior of those tokens."

Alan Karp

unread,
May 6, 2026, 8:52:01 PM (9 days ago) May 6
to fr...@googlegroups.com
I made a mistake by introducing the idea of (mutable) collections into the discussion.  My only excuse is that's the example I was discussing with some other folks.

An ORAC necessarily points to a specific object.  A certificate delegation can have references to multiple objects and can't be used as a capability in an invocation if it does.  That's the point I'm trying to make.

--------------
Alan Karp


Alan Karp

unread,
May 6, 2026, 8:53:48 PM (9 days ago) May 6
to fr...@googlegroups.com
Which is not structured correctly because they don't understand capabilities.

--------------
Alan Karp

Matt Rice

unread,
May 7, 2026, 1:11:10 AM (9 days ago) May 7
to fr...@googlegroups.com
On Wed, May 6, 2026 at 5:52 PM Alan Karp <alan...@gmail.com> wrote:
I made a mistake by introducing the idea of (mutable) collections into the discussion.  My only excuse is that's the example I was discussing with some other folks.

An ORAC necessarily points to a specific object.  A certificate delegation can have references to multiple objects and can't be used as a capability in an invocation if it does.  That's the point I'm trying to make.


Thanks for clarifying this, that makes it so that certificate delegation and directory capabilities no longer seem equivalent. 
The better comparison would seem to be like an immutable directory, or in keykos terms sensory version of a directory.
I'm not familiar with any systems that have those, to have any well formed opinion or intuition about problems they may have.

The closest thing I know of is top level Emily modules, being modules (acting kind of like structures in other languages) those contain naming
of the member variables/functions.  However not necessarily name lookup, of string -> capability.
Given the string processing origins of the thread, I assume these certificate delegations act more like immutable directories than emily modules.


 
Reply all
Reply to author
Forward
0 new messages