Map vs. Territory
Let’s look at the core problem:
The Map: The string the LLM gives you.
/data/../etc/passwdThe Territory: The inode the OS actually opens.
/etc/passwdThe Vulnerability: Security checks usually validate the Map. Execution touches the Territory. When they disagree, attacks slip through.
--
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.
--
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/CANpA1Z1BXV29N1i5mfx_zFbacbzhq9dFS9fExqWgVyZXNsyiHA%40mail.gmail.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.
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 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.
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.
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.
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....
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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CAJ7XQb5pTUE2tSOKAgNpArgpzkb_JEO1%3DqvcvF_pQ7Hc2mOM_g%40mail.gmail.com.
> 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.
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 constructedcapability system. You can only get the vulnerability if a capability can designatemore than a single resource, which is something I managed to do in my first capabilitysystem 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 applicationproduced by a factory means you don't have to trust the behavior of theapplication. The factory provides those guarantees. I got that from Norm's exampleof 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/CANpA1Z0kHA05HqDnriSgJ133x%3DZAxdg%2BrTp4Oygv9kn5txdKbQ%40mail.gmail.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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CALH%2Bfvqc0sBLReOk14RdJ1f4JAJ9c2H2Hm0YxV04VORVqcvV8Q%40mail.gmail.com.
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.
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'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.
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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z1EBjbnfNUPL8nkPpSs8uzLfv5o_BW0XsRcW3maH09Fjw%40mail.gmail.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
--
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.
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.
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?
But, what is 'a specific object'? :-)

To view this discussion visit https://groups.google.com/d/msgid/friam/CAJ7XQb5_wUqRSyjmgZbVeBb-AJ7t%3DdU0_13wFZ-LGMyLSreqWA%40mail.gmail.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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CAK5yZYj9rVqm%2BjjnVr-NcfWwfRX8%2B2iLBm%2B18cWUoFK6kYfqTg%40mail.gmail.com.
To view this discussion visit https://groups.google.com/d/msgid/friam/CAK5yZYj9rVqm%2BjjnVr-NcfWwfRX8%2B2iLBm%2B18cWUoFK6kYfqTg%40mail.gmail.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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z18gsHG0YiN7G62kyiALTty%2BggGzOkSJK7hQGVju0dOVA%40mail.gmail.com.
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?
To view this discussion visit https://groups.google.com/d/msgid/friam/CAMpet1UmVfpPFiTWCBMRBka%3DDr4NtG5qygftdKp4NuYad-43ug%40mail.gmail.com.
To view this discussion visit https://groups.google.com/d/msgid/friam/CAMpet1UmVfpPFiTWCBMRBka%3DDr4NtG5qygftdKp4NuYad-43ug%40mail.gmail.com.
To view this discussion visit https://groups.google.com/d/msgid/friam/CACTLOFqNzJOGzOaU4g0BRm01m%2BmG5q9CqxkFw%3DKB8oVcR%2Bhm1w%40mail.gmail.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.
To view this discussion visit https://groups.google.com/d/msgid/friam/CANpA1Z1FHemReacknWBWtK0ddrZBwjNo4Bcx%3DVcgWLpmeSETPw%40mail.gmail.com.