Skip to content
Kavachकवच

Capabilities: Narrower file access

● Intermediate4 min

Fs can be granted in part: Fs.read only reads, Fs.write only changes, and Fs("./data") stays inside one folder.

Fs.read and Fs.write are checked by the compiler. A function that may only read can't write:

use std.fs

pub fn read_config() -> String ! FsError uses Fs.read {
    try fs.write_text("config.txt", "reset")
    try fs.read_text("config.txt")
}

The compiler refused the program:

kavach run cap-read-only.kav

error: `read_config` uses Fs.write, but its `uses` clause doesn't list it: add `Fs.write` to `uses` (spec 8.1)
cap-read-only.kav: Kavach code, then what running it prints

A folder is checked while the program runs, since paths are values. Every file operation must name a path inside the folder, or it fails with Denied. .. can't climb out:

use std.fs

fn load_report(name: String) -> String ! FsError uses Fs.read("./reports") {
    try fs.read_text("./reports/{name}.txt")
}

fn main() ! Error {
    try fs.create_dir("reports")
    try fs.write_text("reports/june.txt", "sales: 42")
    try fs.write_text("secrets.txt", "the safe code")
    print(try load_report("june"))
    print(load_report("../secrets") catch e => "refused: {e}")
}

The program ran and printed:

kavach run cap-folder.kav

sales: 42refused: Denied(path: "./reports/../secrets.txt")
cap-folder.kav: Kavach code, then what running it prints

The folder also covers everything the function calls, and the tasks it starts. A symbolic link that points outside the folder is refused too.