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)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")
The folder also covers everything the function calls, and the tasks it starts. A symbolic link that points outside the folder is refused too.