{"id":15401137,"url":"https://github.com/sunfishcode/pathbox","last_synced_at":"2025-07-24T07:03:30.194Z","repository":{"id":39883664,"uuid":"494595011","full_name":"sunfishcode/pathbox","owner":"sunfishcode","description":"wasi argv and env var experiment","archived":false,"fork":false,"pushed_at":"2023-03-28T18:35:42.000Z","size":45,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-19T06:37:40.042Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sunfishcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-05-20T20:12:38.000Z","updated_at":"2023-03-28T18:35:59.000Z","dependencies_parsed_at":"2023-07-31T09:52:41.501Z","dependency_job_id":null,"html_url":"https://github.com/sunfishcode/pathbox","commit_stats":null,"previous_names":["sunfishcode/pathbox"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sunfishcode/pathbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Fpathbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Fpathbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Fpathbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Fpathbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sunfishcode","download_url":"https://codeload.github.com/sunfishcode/pathbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Fpathbox/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266806956,"owners_count":23987420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-24T02:00:09.469Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T15:56:35.363Z","updated_at":"2025-07-24T07:03:30.151Z","avatar_url":"https://github.com/sunfishcode.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"One of the things we've learned from wasi\\_snapshot\\_preview1 was that\nthe `--dir=` preopen system is inconvenient, awkward, and prone to misuse.\n\nAnd it's especially inconvenient in use cases like binfmt\\_misc where users\nwant to treat it like a \"regular\" executable where they don't have to pass\nextra `--dir=` flags.\n\nThis repo contains a possible alternative approach which preserves the\nuseful properties of preopens while being more convenient.\n\n### Example\n\nexamples/grep.rs is a simple grep-like program:\n\n```\n$ cargo run --quiet --example grep dep Cargo.toml\n\u003e\u003e\u003e external args: [\"dep\", \"Cargo.toml\"]\n\u003e\u003e\u003e internal args: [\"dep\", \"9b60de2d-fb3f-4cc8-bc9b-0d959f615a0d.toml\"]\nCargo.toml: [dependencies]\nCargo.toml: [dev-dependencies]\n```\n\nThe first two `\u003e\u003e\u003e` lines contain debugging output. They show the arguments\npassed to the host process (external args) and the arguments that would\nbe passed to a WASI program (internal args). The remaining lines are the\nnormal grep output.\n\nIn the internal args, notice that \"Cargo.toml\" has been replaced by\n\"9b60de2d-fb3f-4cc8-bc9b-0d959f615a0d.toml\". That hides the path\nfrom the application, since paths might contain user-identifying or\nhost-identifying information. And notice also that the application's stdout\nhas translated the UUID string back into \"Cargo.toml\", so that this is\nmostly transparent to end users.\n\nThis relies on some heuristics to determine which arguments are likely to\nrefer to filesystem paths. It should work in most cases, however it won't\nwork in all. For example, a string like \"file.silly!\" might be a valid\nfilename, but does not satisfy the heuristics because \"silly!\" is not a\ncommon filename extension:\n\n```\n$ echo \"Avoid implicit dependencies\" \u003e file.silly!\n$ cargo run --quiet --example grep dep file.silly!\n\u003e\u003e\u003e external args: [\"dep\", \"file.silly!\"]\n\u003e\u003e\u003e internal args: [\"dep\", \"file.silly!\"]\n[ERROR stderr] Error: cannot open file 'file.silly!': File is not available\n$\n```\n\nHere, the \"file.silly!\" argument was not replaced by a UUID string, and the\nopen fails.\n\nUsers can always override the heuristics by prefixing paths with `./`:\n\n```\n$ cargo run --quiet --example grep dep ./file.silly!\n\u003e\u003e\u003e external args: [\"dep\", \"./file.silly!\"]\n\u003e\u003e\u003e internal args: [\"dep\", \"5f021ccc-88d1-4c08-84c3-c87db42f4815.silly!\"]\n./file.silly!: Avoid implicit dependencies\n```\n\nThe path \"./file.silly!\" was substituted, and the program was able to open it.\n\nConversely, an argument might be interpreted as a filename when it is\nnot. Prefixing an argument with `%verbatim:` makes the remainder of the\nargument a verbatim argument, even if it looks like a path:\n\n```\n$ cargo run --quiet --example grep dep %verbatim:./Cargo.toml\n\u003e\u003e\u003e external args: [\"dep\", \"%verbatim:./Cargo.toml\"]\n\u003e\u003e\u003e internal args: [\"dep\", \"./Cargo.toml\"]\n[ERROR stderr] Error: cannot open file './Cargo.toml': File is not available\n```\n\nHere, \"./Cargo.toml\" is passed through verbatim, though it cannot be\nopened as such because it's not replaced.\n\n`%` at the beginning of an argument is reserved for special features.\n - `%verbatim:` suppresses all inference and passes the rest of the string through as-is.\n - `%read:` translates the path and makes the file only openable for reading.\n - `%write:` translates the path and makes the file only openable for creating, truncating, and writing.\n - `%append:` translates the path and makes the file only openable for appending.\n\nFor example, the `cp` example copies from an input file to an output file;\nthe following gives it explicit access to just read from the input and\njust write to the output:\n\n```\n$ cargo run --quiet --example cp %read:Cargo.toml %write:foo\n\u003e\u003e\u003e external args: [\"%read:Cargo.toml\", \"%write:foo\"]\n\u003e\u003e\u003e internal args: [\"87b21ff3-551a-4a40-b5d4-5357f8ddbc1e.toml\", \"19fdaf83-bd73-419f-bca3-223606a8f2bf\"]\n```\n\nOther `%` forms may be added in the future to provide more control for\nadvanced use cases.\n\n### Why?\n\nThis is a much more convenient interface than the `--dir=`. In most cases,\nit should let things Just Work without the user having to do WASI-specific\nthing. In cases where it doesn't, adding `./` or `%verbatim:` in-band is easier\nin many situations than adding out-of-band `--dir=` arguments to the Wasm\nruntime.\n\nAnd it eliminates the temptation to do `--dir=.` or `--dir=/`, which\nlargely disable the sandbox.\n\nThe goal is to make sandboxing convenient enough that people can just\nuse it, without having it be something they have to opt into, or\nconfigure. VFS's or seccomp sandboxes or user namespaces can be set\nup to do similar sandboxing, but they all require up-front\nconfiguration.\n\nUsers are already specifying which files they want their programs to\naccess: it's the files they pass in as arguments. This automatically\nallows programs to access just those files, and no others, without\nany manual user intervention.\n\n### But what if the application writes a filename into a file?\n\nNot many applications do this, though some do. What will happen?\nThey'll write a meaningless UUID string, which other programs will\nbe unable to do anything with.\n\nThere are a few potential ways to approach this:\n\n - UUID strings in stdout are currently translated back into original\n   filenames. This functionality could optionally be made available to\n   other streams as well.\n\n - Writing a filename into a file is making an assumption, that readers\n   of the file will have the same namespace as the writer. Where we're\n   going, this will be an increasingly unreliable assumption, so it's\n   worth pushing back on applications and asking whether this is something\n   they really need to do.\n\n - In the future, WASI should have better ways to persist data containing\n   references to other data, which should be an alternative to storing\n   filenames.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunfishcode%2Fpathbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsunfishcode%2Fpathbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunfishcode%2Fpathbox/lists"}