Skip to content

Object capabilities for capsec-std and capsec-tokio? #62

Open

Description

@JonasCir

Hi,
thank you for creating this interesting project!

My question is if object capabilities for file/network access etc. will be eventually supported by this crate? Currently, methods in capsec-std and capsec-tokio are all guarded by a certain CapProvider. The actual arguments, however, like for example paths in capsec-std::fs are all of the form impl AsRef<Path>and can be freely chosen/are not subject to access control as provide_cap seems to discard _target in the macro and always return Ok(Cap::new()).

Being able to reason about program IO is already a great improvement, I just feel that this could also be extended to the actual (file, network, etc.) objects in the Rust program code.

So instead of having

let root = capsec::root();
let cap = root.grant::<FsRead>();
let data = capsec_std::fs::read(from_some_potentially_untrusted_input, &cap).unwrap();

I think it would be beneficial to introduce something like

struct FileObjectCap<O: AsRef<Path>, P: Permission>{
   file_object: Box<O>, // <- or anything appropriate to hold the object
   permission: Cap<P> // <- can still be zero size
}

impl <O: AsRef<Path>> CapProvider<FsRead> for FileObjectCap<O,FsRead> {
    fn provide_cap(&self) -> Result<Cap<FsRead>, CapSecError> {
        Ok(Cap::new())
    }
}

pub fn read <O: AsRef<Path>>(fs_cap: &FileObjectCap<O,FsRead>) -> Result<Vec<u8>, CapSecError> {
    let _proof: Cap<FsRead> = cap.provide_cap()?;
    Ok(std::fs::read(fs_cap.file_object())?)
}

fn main() {
    let root = capsec::root();

    let mut fs_namespace = Vec::new();

    // not just general FsRead IO of the program is subject to access control,
    // but the actual file objects in the program code as well
    let cap = root.grant::<FsRead>("/tmp/example.txt");
    fs_namespace.push(cap);

   // get untrusted path which should be subject to access control
   let untrusted_path = ...;

   // just for demonstration purposes, Namespace should be a dedicated
   // container type listing all the capabilities available to the program code
   let found_cap = fs_namsepace.iter().filter(|c| c.fs_object() == untrusted_path).one().unwrap();

   let data = capsec_std::fs::read(&found_cap).unwrap();
}

What do you think?

Activity

  1. bordumb commented on Jul 28, 2026

    @bordumb
    Collaborator

    @JonasCir thanks for reaching out with this, and apologies for this slowness

    I originally started this project as a means to help enforce some rules for myself in another project related to decentralize identity and credentials. I got capsec working "well enough" for that purpose, and it's taken a bit of a backseat

    Digression aside...

    I agree with you.

    Cap<FsRead> currently represents permission to perform filesystem reads as a category. An unscoped CapProvider<FsRead> ignores the target, so it does not bind that authority to a particular file, directory, or network endpoint.

    Attenuated<P, S> with DirScope and HostScope adds target-based checks:

    let cap = root
        .grant::<FsRead>()
        .attenuate(DirScope::new("/tmp")?);
    
    let data = capsec_std::fs::read(untrusted_path, &cap)?;

    Based on that understanding, I worked with ChatGPT Sol 5.6 (Extra High) to create this spec:
    #63

    Feel free to do either of the following:

    • Review/give feedback on the spec
    • Start a PR based on the spec

    Thanks again for pointing this out!

  2. JonasCir commented on Aug 17, 2026

    @JonasCir
    Author

    Hi,
    thank you for your detailed answer (and the Twitter follow :D).

    I took a first pass at #63, I will write down my thoughts about it when I have time.

    I really think that a proper object capability implementation would have it's place in the ecosystem if done and advertised right.

  3. bordumb commented on Aug 20, 2026

    @bordumb
    Collaborator

    @JonasCir sounds good

    Take your time and feel free to reach out with any ideas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions