{"id":"f3c08782-e876-44f1-b838-c1bb866b6ab6","arxiv_id":"2506.11701","paper_version":1,"verdict":"CONDITIONAL","confidence":"MODERATE","novelty_score":6.0,"correctness_risk":"high","formal_verification":"none","parameter_count":0,"one_line_summary":"A token-based permission system for Rust that restricts library access to system I/O at compile time, with a proof of concept and acknowledged limitations.","lead":"PermRust proposes a way to attach permissions to Rust libraries using special token types checked at compile time. The idea is to stop third-party code from using system resources, like files or network, unless the app explicitly grants access.","discovery_kind":"new_application","skeptic_critique":{"model":"deepseek-v4-flash","headline":"Central guarantee fails because the app_ wrapper fabricates a token via unsafe transmute and is gated only by a nonexistent Cargo direct-dependency feature; feature unification can expose app_ to transitive dependencies, letting them perform I/O without tokens.","rationale":"The reader's weakest assumption identifies exactly the same load-bearing concern: the security of the permission-aware import layer depends on Cargo's nonexistent direct-dependency feature, and feature unification can enable app_ wrappers for transitive dependencies, causing privilege escalation. My reading of the full text confirms this is the most important flaw. The central claim of Sect. 4.1 is stated unconditionally, but the only counterexample to it in the paper is the app_ wrapper itself: a function that performs I/O without requiring a token from its caller. The wrapper's token is created by an unsafe transmute, so the unforgeability of tokens is broken inside the abstraction boundary; the system's safety therefore rests entirely on Cargo gating. The paper is unusually transparent about this, and even admits in Sect. 5 that feature unification undermines the direct-dependency assumption, but it does not offer a fix or an evaluation. Since the concern is already incorporated into the reader's CONDITIONAL verdict, and since the paper remains a useful concept proposal if these gaps are addressed, the verdict should remain CONDITIONAL rather than being changed. The concrete test above would settle whether the privilege escalation is real under current Cargo behaviour, and it should be run before any stronger claim of security is made.","tokens_in":7970,"tokens_out":3713,"duration_ms":35470,"concrete_test":"Create a minimal Cargo workspace: app depends directly on lib_a and lib_b, and lib_b also depends on lib_a. Give lib_a a public PermRust-generated app_read_something that reads a file, with lib_a's ReadPerm feature enabled by app but not by lib_b. Run cargo tree -e features to confirm that feature unification activates lib_a/ReadPerm for lib_b. Then compile lib_b, which has no permission declared, and call lib_a::app_read_something from lib_b. If the program compiles and the file read succeeds, the privilege escalation is real and the central claim fails. A secondary check is to see whether any transitive dependency can invoke an app_ function at all when no permission is set; the current design has no compiled gate preventing this beyond the nonexistent direct-dependency feature.","verdict_should_be":"UNCHANGED","load_bearing_attack":"The paper's central claim (Sect. 4.1) is that \"no function can perform any I/O operation in safe Rust without having the correct access tokens.\" This is not actually delivered by the design. Listing 1.6 defines app_read_something, which is a safe callable function that performs I/O and does not require the caller to provide a token; instead, it constructs token::ReadPerm via unsafe { std::mem::transmute(self) } from a locally defined type. Thus every app_ wrapper is a safe entry point through which a caller can exercise I/O without ever possessing a real token. The only mechanism that restricts app_ wrappers to authorized callers is the proposed Cargo feature \"direct-dependency\" that, as Sect. 4.3 states, does not exist today. The assumption that it is implementable is load-bearing, and the paper itself concedes in Sect. 5 that Cargo feature unification will activate features for a package that is simultaneously a direct and transitive dependency. Under those conditions, LibB, which has no permission for ReadPerm, could call LibA's app_ function and perform an I/O operation, exactly the privilege escalation the system is meant to prevent. The paper dismisses this as \"unclear\" and \"unlikely,\" but for a security guarantee it is decisive: the guarantee depends on an unprototyped Cargo extension and explicitly breaks under existing Cargo semantics. The unsafe transmute is not merely an implementation detail; it is the point where a token is forged, contradicting the capability-as-keys unforgeability requirement from Sect. 3.2.","agreement_with_reader":"agree"},"referee_report":{"model":"deepseek-v4-flash","summary":"PermRust proposes a token-based permission system for Rust that aims to restrict I/O operations per library at compile time. The paper formalizes the problem using the access matrix model, defines an abstract function tree, gives an O(|E|·|O|) algorithm to check whether a program is permission-respecting and privilege-escalation-free, and sketches a Rust proof-of-concept built from token types, proxy wrappers around standard-library I/O, and app_ entry points generated by a permissions macro. The authors claim that no function can perform any I/O operation in safe Rust without the correct access tokens, and position the system as a zero-cost mitigation against supply-chain attacks.","tokens_in":8291,"tokens_out":7519,"duration_ms":71550,"significance":"The formal access-control section is clean, and the algorithm in Theorem 1 is correct and clearly presented; the paper also makes its implementation available in a repository. The idea of encoding permissions as Rust types is attractive, and per-library granularity is potentially valuable for supply-chain scenarios. However, the central security guarantee is not demonstrated as stated. The app_ wrapper in Listing 1.6 fabricates tokens with an unsafe transmute, the enforcement depends on a Cargo 'direct-dependency' feature that does not exist, and the proxy standard-library example does not actually prevent calls to the original File::read. These are load-bearing gaps, not cosmetic issues. The paper reads best as a design sketch or position paper; the stated guarantee needs to be either substantially weakened or supported by a concrete design for the missing Cargo feature and a trusted token-minting path.","major_comments":[{"comment":"The paper's central claim — 'no function can perform any I/O operation in safe Rust without having the correct access tokens' — is contradicted by the app_read_something wrapper shown in Listing 1.6. This is a safe callable function that performs I/O and does not require the caller to provide a token; instead, it creates a localPerm and uses unsafe { std::mem::transmute(self) } to obtain a &token::ReadPerm. The unsafe transmute is a token-forging step, and because app_read_something is safe, any caller can invoke it and obtain I/O capabilities without ever possessing a real token. The claim must be restated to exclude the trusted app_ layer, or the token minting must be moved to a trusted root that cannot be called by untrusted code.","section":"Section 4.1, Listing 1.6"},{"comment":"The security of the permission-aware import layer rests entirely on a proposed Cargo feature, 'direct-dependency', that the paper admits does not exist. Under current Cargo semantics, feature unification will enable the feature for a package that is both a direct and a transitive dependency, and the paper itself concedes in Section 5 that this lets LibB call LibA's app_ functions and thereby escalate from no ReadPerm permission to full ReadPerm I/O. The authors call the real-world effect 'unclear' and 'unlikely', but for a security guarantee this is decisive: the guarantee is not delivered by current Cargo and depends on an unprototyped extension. The paper needs either a concrete design for the direct-dependency feature that resists feature unification, or a revised threat model that does not claim the guarantee.","section":"Sections 4.3 and 5 (Feature Unification)"},{"comment":"The proxy FileProxy is described as 'puts itself in front of the original standard library', but the original std::fs::File::read method remains available in the actual Rust standard library. A function that obtains a std::fs::File can still call read directly without any token, so the statement 'the standard library now expects the correct token' is only true in an idealized modified standard library, not in the proof-of-concept. This deployment assumption must be made explicit, and the paper should explain how the replacement of the standard library is enforced (e.g., through a toolchain change or a restricted prelude); without that, the central claim fails even before considering the app_ wrapper.","section":"Section 4.1, Listing 1.4"}],"minor_comments":[{"comment":"There are several typographical errors, including 'moderns software', 'a subjects has', 'theOSorthecompiler', and 'Consequentially'; these should be corrected.","section":"Sections 1 and 3"},{"comment":"Reference [15] is incomplete: it gives only a URL fragment and no document title or publication venue; reference [14] also lacks a year and venue.","section":"References"},{"comment":"The paper would benefit from showing the permissions macro implementation rather than only referencing the repository, since the macro is central to generating app_ functions; a short code listing or a commit hash would improve reproducibility.","section":"Section 4.3"},{"comment":"The terms 'capability-as-keys' and 'capabilities-as-keys' are used inconsistently; please standardize the terminology.","section":"Section 3.2"}],"recommendation":"major_revision","confidential_remarks":"This is a thought-provoking short paper, but the central security claim as stated is not supportable without additional design work. The formal model is sound, and the paper would be suitable as a position paper if the claim were scoped to a trusted app_ layer and an assumed Cargo extension. As an archival security result, the current version does not meet the bar because the key guarantee breaks under existing Cargo semantics and because the app_ wrapper forges tokens via unsafe code. The editor may wish to consider whether the venue's scope includes such design proposals; if not, a rejection may be more appropriate than a major revision."},"author_rebuttal":null,"desk_editor":{"model":"deepseek-v4-flash","letter":"Two things you should know. First, this is an unusually honest short concept paper: it lays out a capability-as-keys design for per-library I/O permissions in Rust, and Sect. 5 explicitly names its own limitations, including the feature-unification problem. Second, the central security claim in Sect. 4.1 — \"no function can perform any I/O operation in safe Rust without having the correct access tokens\" — is not delivered. The app_ macro in Listing 1.6 forges a ReadPerm token via unsafe transmute, making every app_ wrapper a safe entry point that performs I/O without the caller holding any token. The only restriction on who can call that entry point is a proposed Cargo \"direct-dependency\" feature that does not exist today, and the paper concedes that feature unification will activate it for packages that are simultaneously direct and indirect dependencies. That is the exact privilege escalation the system claims to prevent.\n\nThe theoretical core is in decent shape. The access-matrix adaptation is clean, the O(|E|·|O|) permission-check algorithm is correct, and the capability-as-keys framing maps naturally onto Rust's type system. The reference list covers OS-level sandboxes and capability languages and doesn't miss anything obvious. The authors also point to a proof-of-concept repository, which is good practice — though the code snippets in the paper itself already reveal the forge.\n\nThe soft spots are proportionate to the paper's size but fatal to the headline guarantee. The unsafe transmute is not a minor implementation detail; it is the point where a token is minted, violating the unforgeability criterion stated in Sect. 3.2. The Cargo direct-dependency feature is load-bearing and unprototyped. The attacker-model discussion dismisses the real-world impact as \"unclear\" and \"unlikely,\" but for a security guarantee that is not an answer. A malicious or compromised library would have no qualms about calling an app_ function if the union of features grants it access, and the paper itself says that can happen.\n\nThis is a paper for a niche audience: researchers thinking about language-level capability systems or Rust supply-chain defenses. Those readers will find the model worth discussing, but the current version does not substantiate the core guarantee. I would send it to peer review as a concept paper with a request for major revision — the authors need to prototype the Cargo extension and either prove the feature-unification case or reposition PermRust as a best-effort annotation tool rather than a security guarantee. As it stands, it is an interesting sketch, not a working permission system.","headline":"A candid concept paper whose central 'no I/O without tokens' guarantee is undermined by its own app_ macro forge and an unprototyped Cargo feature the paper admits breaks under feature unification.","tokens_in":8812,"tokens_out":2175,"would_cite":false,"duration_ms":22175,"reading_group":"maybe","serious_thinker":"yes","would_accept_peer_review":true},"rs_alignment":null,"lean_confirmation":null,"pith_extraction":{"msc":[],"pacs":[],"model":"deepseek-v4-flash","headline":"PermRust enforces per-library I/O permissions at compile time, so no safe-Rust function can access a system resource without the right token.","keywords":["capability-based security","Rust permissions","supply chain attacks","zero-cost abstraction","access matrix model","token types","compile-time enforcement","Cargo features"],"falsifier":"Take a project with direct dependency LibB and indirect dependency LibA, where LibA has a file-reading app_read_something generated by the permissions macro. If feature unification enables ReadPerm for LibA while LibB's Cargo.toml declares no ReadPerm, and the project still compiles and performs a file read through LibB's call to LibA's app_ function, then the package-level permission enforcement has been bypassed. That concrete build would falsify the claim that app_ entry points enforce declared permissions.","tokens_in":7771,"feed_emoji":"🔐","tokens_out":6759,"duration_ms":59425,"temperature":0.7,"pith_summary":"PermRust is a proposed permission system that moves access control for system resources from the operating system down to the level of individual Rust libraries. The paper's central claim is that if every I/O function in the standard library demands an unforgeable token argument, and token constructors are kept private, then no safe-Rust function can perform I/O without holding the matching permission. Permissions are declared per package in Cargo.toml and enforced by the compiler as a zero-cost abstraction, with no runtime overhead. If the approach holds, third-party libraries would be unable to secretly access the filesystem, network, or other system resources, which would blunt a class of supply-chain attacks exemplified by Log4Shell. The paper is a concept with a proof-of-concept implementation and explicitly leaves evaluation to future work.","feed_headline":"Rust permission tokens block hidden I/O in libraries at compile time","feed_subtitle":"Unforgeable tokens make I/O access as broad as each library's declared permissions.","key_machinery":"The central object is the token type, a zero-sized struct with a private field created only inside a trusted token module. It is what makes permissions unforgeable in safe Rust, and because it occupies no memory the entire check is a compile-time, zero-cost abstraction. The argument hangs together through the abstract function tree (the program's call graph obtained by contracting all edges that do not end in a function) and the permission matrix over functions-as-subjects and I/O entry points-as-objects, with the single right 'call'. The type checker is claimed to execute Algorithm 1, checking that every call to an I/O object is permitted and that no callee holds rights its caller lacks, while compiling the program.","core_discovery":"The paper establishes a capability-as-keys design for Rust. Each system resource is guarded by a token type: a zero-sized struct whose field is private, so safe Rust code outside the trusted token module cannot construct it. The standard library is wrapped so that every I/O function takes the corresponding token as an argument; consequently, the only way to call such a function is to possess the token, and the only way to obtain a token is through the app_ entry points, which the permissions macro generates only for the permissions declared in a package's Cargo.toml. To prevent transitive dependencies from minting tokens through app_ functions, the design introduces a Cargo feature called direct-dependency that only the root package can enable; the paper acknowledges this feature does not exist today and would need to be added to Cargo. The paper formalizes the desired property using the access matrix model and the abstract function tree: a program is permission respecting if every call edge to an I/O object carries the 'call' right, and privilege escalation free if no caller has fewer rights than its callee. Because safe Rust cannot forge tokens, the type checker itself is claimed to execute this permission check at compile time.","pith_inferences":["A practical test of the design would be to build the trust anchor as a sealed, audited crate for std's I/O surface and measure how many existing crates.io packages compile unchanged under PermRust annotations; the paper does not report such a measurement.","The same token mechanism could be extended to other ambient authorities beyond system I/O, such as environment variables, process spawning, or DNS lookups, since the token type does not care what the resource is.","An object-capability variant would yield finer-grained path- or IP-scoped permissions than the token model, at the cost of requiring all resources to be obtained at program start; the paper notes this trade-off but does not evaluate it.","If the direct-dependency feature cannot be added to Cargo, a compiler or package-manager plugin that rewrites the dependency graph could enforce the invariant, giving a concrete fallback for the paper's main open assumption."],"forward_implications":["In the intended configuration, a library whose Cargo.toml does not declare ReadPerm cannot perform a file read, because every read path in the wrapped standard library demands a ReadPerm token that no app_ wrapper will mint for it.","Enforcement is zero-cost at runtime: tokens vanish at compile time, so the only costs are compile time and the annotation burden on library developers.","Common supply-chain attacks that hide resource access inside popular libraries, such as a logging library reaching out to a remote server, would be stopped unless the package's declared permissions include that access.","The system does not claim to stop malicious code using unsafe Rust, which can transmute or construct arbitrary tokens; its stated target is accidental or hidden I/O in otherwise safe libraries.","Feature unification is an acknowledged weak point: if a package is both a direct and transitive dependency, the direct-dependency flag can become active for it, letting a transitive caller use its app_ functions and potentially escalate privileges."],"supporting_citations":[{"why":"Defines the access matrix model and the ACL/capability distinction that the paper adapts for per-function permissions.","marker":"[9]"},{"why":"Supplies the formal definition of the access matrix used in Definition 1.","marker":"[5]"},{"why":"Provides the capability-as-keys versus object-capabilities comparison and the ambient-authority criterion the paper relies on to choose tokens.","marker":"[10]"},{"why":"Lists the criteria for a capability-secure language (memory safety, encapsulation, explicit authority) that PermRust claims safe Rust satisfies.","marker":"[15]"},{"why":"The Cargo Book documents feature unification, which the paper identifies as a limitation for its direct-dependency mechanism.","marker":"[16]"},{"why":"Retrospective analysis of Log4Shell and SolarWinds that motivates the supply-chain attack scenario PermRust targets.","marker":"[3]"},{"why":"The proof-of-concept implementation of the permissions macro and app_ wrappers is available there; the paper's concrete claims about the macro refer to this code.","marker":"[7]"}],"fun_headline_variants":["Rust tokens: per-library I/O access without runtime cost","Capability-style tokens put Rust library I/O under compile-time control","Rust's type system turns declared permissions into unforgeable I/O keys","Token-based permissions: Rust libraries can only do their declared I/O","Rust zero-cost tokens make library I/O permission-aware at compile time"],"cache_read_input_tokens":3200,"weakest_assumption_plain":"The load-bearing premise is that Cargo can be extended with a direct-dependency feature that is set only for direct dependencies and can never be enabled by a transitive dependency; the paper states this feature does not exist today and assumes it could be implemented because Cargo builds the dependency tree.","fun_headline_variants_meta":{"raw":{"variants":["Rust tokens: per-library I/O access without runtime cost","Capability-style tokens put Rust library I/O under compile-time control","Rust's type system turns declared permissions into unforgeable I/O keys","Token-based permissions: Rust libraries can only do their declared I/O","Rust zero-cost tokens make library I/O permission-aware at compile time"]},"model":"deepseek-v4-flash","effort":"low","cost_usd":0.000472,"raw_usage":{"total_tokens":2318,"prompt_tokens":887,"completion_tokens":1431,"prompt_tokens_details":{"cached_tokens":384},"prompt_cache_hit_tokens":384,"prompt_cache_miss_tokens":503,"completion_tokens_details":{"reasoning_tokens":1338}},"tokens_in":503,"tokens_out":1431,"duration_ms":12692,"temperature":1.0,"reasoning_tokens":1338,"cache_read_input_tokens":384,"cache_creation_input_tokens":0},"cache_creation_input_tokens":0},"created_at":"2026-08-07T04:03:13.177139+00:00","model_set":{"reader":"deepseek-v4-flash"},"falsifier":"Take a project with direct dependency LibB and indirect dependency LibA, where LibA has a file-reading app_read_something generated by the permissions macro. If feature unification enables ReadPerm for LibA while LibB's Cargo.toml declares no ReadPerm, and the project still compiles and performs a file read through LibB's call to LibA's app_ function, then the package-level permission enforcement has been bypassed. That concrete build would falsify the claim that app_ entry points enforce declared permissions.","supporting_citations":[{"cited_title":"SIGOPS Oper","cited_arxiv_id":null,"evidence_quote":"Defines the access matrix model and the ACL/capability distinction that the paper adapts for per-function permissions."},{"cited_title":"de Gruyter (2023)","cited_arxiv_id":null,"evidence_quote":"Supplies the formal definition of the access matrix used in Definition 1."},{"cited_title":null,"cited_arxiv_id":null,"evidence_quote":"Provides the capability-as-keys versus object-capabilities comparison and the ambient-authority criterion the paper relies on to choose tokens."},{"cited_title":null,"cited_arxiv_id":null,"evidence_quote":"Lists the criteria for a capability-secure language (memory safety, encapsulation, explicit authority) that PermRust claims safe Rust satisfies."},{"cited_title":null,"cited_arxiv_id":null,"evidence_quote":"The Cargo Book documents feature unification, which the paper identifies as a limitation for its direct-dependency mechanism."},{"cited_title":"Better Call Saltzer \\& Schroeder: A Retrospective Security Analysis of SolarWinds \\& Log4j","cited_arxiv_id":"2211.02341","evidence_quote":"Retrospective analysis of Log4Shell and SolarWinds that motivates the supply-chain attack scenario PermRust targets."},{"cited_title":null,"cited_arxiv_id":null,"evidence_quote":"The proof-of-concept implementation of the permissions macro and app_ wrappers is available there; the paper's concrete claims about the macro refer to this code."}],"review_version":1}