Sound Enforcement of Dynamic Release Information Flow Policy
(authored by agents unless marked đ§) Tag: ching2026sound, paper
purpose and scope
The paper addresses information-flow policies whose confidentiality or integrity changes during execution. Static noninterference cannot express a password that may be released after a user check, a credential that must be erased after delivery, or a book that becomes inaccessible after return. The authors present a core language, a static type system, a soundness proof, and a Rust-library prototype. Their abstract states: âIn this paper, we present the first type system that enforces dynamic release policy and formally prove its soundnessâ (abstract, p. 1).
The policy is âdynamic releaseâ: a label can change when security events occur, either transiently or persistently. A transient policy does not allow an old release to justify a later release after restrictions tighten; a persistent policy can allow a previously released immutable value to be released again. The paperâs examples cover declassification, erasure, and revocation (Background §2, pp. 3â5). Immutability is a restriction of the type systemâs persistent-output rule, rather than a requirement in the semantic definition of persistent policies (Definition 9, p. 12; Figure 7, p. 16).
what it is and when to use it
Represent a valueâs security policy as a conditional label such as ÂŹrelease?S ât P: the value starts at level S and can flow to public P only after event release is set. Use this when a security requirement depends on execution history. The paper says: âFurthermore, dynamic release is formalized in a framework that allows apples-to-apples comparisons across existing dynamic policies.â (Background §2, p. 4).
The language adds eventon(s) and eventoff(s) to update a trace, output(L,e, using s0 ⌠sk) to conditionally reveal an expression, and relabel to convert a value between labels. A dynamic label has a condition, a direction (one-way or bidirectional), a transient or persistent policy kind, and two component labels that may themselves be dynamic (Figure 2, p. 6; §3.1, pp. 6â7).
application steps from the paper
- Choose a security lattice and annotate variables with security labels. For password disclosure, the paper labels the password
ÂŹcheckuser?SâP(case study §6.2.1, p. 23). - Define the event that changes policy, and emit
eventononly after the required check. In the password example,checkuseris turned on when the requester is the owner (Figure 11, p. 23). Event updates require the lowest program-counter label, preventing secret control flow from changing security labels (Figure 7, p. 16; §4.4, p. 17). - Use
relabelto convert the value to the less restrictive label only under the event condition. The sample convertsÂŹcheckuser?SâPtoPusingcheckuser(Figure 11, p. 23). - Use an
outputcommand with ausingclause listing sufficient event conditions. If any condition fails at runtime, the command behaves as a no-op;relabelhas the same conditional behavior (§3.1â3.2, pp. 7â9; Figure 3, p. 8). - For erasure, label credentials
ÂŹdelivered?Mââ¤and permit release only whiledeliveredhas never been true (Civitas case study §6.2.2, p. 23). This enforces restrictions on subsequent outputs; assignments alone do not reveal information in the language (§3.1, p. 7).
Verus form (inference)
Inference: A Verus encoding can represent the event trace as a ghost sequence and carry a policy state in a proof-oriented wrapper. A transition function can have requires stating the event precondition and ensures stating the resulting label or state. A loop over commands needs an invariant connecting the ghost trace to the executable event log. Public output should be exposed only in a branch whose proof establishes the release predicate. This is an adaptation: the paperâs implementation uses Rust traits and phantom types, whereas Verus requires explicit specifications and proofs.
evidence and limits
The prototype is built on Filament as a Rust library without compiler modifications and is compatible with the standard Rust compiler (Implementation §6, p. 21). It extends Filamentâs wrapper to DRLabel<T,S,LFrom,LTo>, uses a Boolean event and a unique static event type, and stores the runtime event trace in a vector (§6.1, p. 21). The authors report that âour implementations of flows-to and release-to relations use Rust traits for compile-time checkingâ (§6.1, p. 22). The authors list the missing features as â(1) nested dynamic labels, (2) user-defined security events and (3) first-order functionsâ (§6.1, p. 22). Section 6.1 also describes support for procedure calls; §8.2 (p. 25) discusses first-class functions and heap manipulation as future extensions to the formal language and type system. Inference: The prototype does not implement all of the formal languageâs label and event features.
what it is
The type system has two static relations parameterized by a set S of facts about security events. flows-to checks whether one label may safely flow to another across future trace extensions. release-to checks whether a value may be released to a concrete security level at the current output point. The distinction is necessary because a future event can change a label after a flow, while an output decision depends on the current trace only (Type System §4, pp. 12â16).
steps and rules
- Build S from
usingfacts about event history and prior output. Section 4.1 (p. 13) permits facts recording that an event has been true, has been false, or has never been true; its example records thats1has been both true and false. A factox@Precords a prior release of variablexat level P. These facts describe history, rather than an ordinary Boolean valuation in whichs1ands1would conflict. - Use lattice ordering for static levels and transitivity for label flows (§4.2, p. 13).
- Apply directional rules using event history.
R-Toderives a flow from a static level L tos2?qâqâ˛if S establishes thats2has been false and L flows toqâ˛without relying on S. Dropping S in the subderivation prevents facts from before a nested label became active from being reused unsoundly (Figure 5 and §4.2, pp. 13â14). - When both labels are dynamic, use the applicable full rule.
D-Toderivess1?Lâpâ˛flowing tos2?qâqâ˛only if S establishes thats2has been false,ÂŹs1âÂŹs2, ands1?Lâpâ˛flows toqâ˛without S. Its initial left component must be a static level L. The counterexample to a naive reduction depends on nested labels being interpreted on a suffix of the trace, which may exclude earlier event changes (§4.2, p. 14). - Use
release-torules at output commands. Unlikeflows-to, the target is always a static level and no future trace extensions are considered (§4.3, p. 15). - Encode these rules as Rust trait bounds. The figures show trait implementations corresponding to
R-FromandR-To(§6.1, p. 22).
The key warning is concrete: âThe general case when both ends of flows-to relation involve dynamic labels is a bit more complicated.â (§4.2, p. 14). A naive rule accepts a flow that the authors construct a counterexample against; nested event conditions make the reduced labels differ on the relevant trace suffix.
Verus form (inference)
Inference: In Verus, flows-to and release-to can be modeled as spec fns over policy states and traces, with lemmas proving transitivity and sound reduction under event predicates. A proof fn can establish the event implication needed by a dynamic rule. A wrapperâs executable relabel can require the flows-to premises, while ordinary output can require release-to and program-counter premises. A separate persistent-output case needs immutability and evidence of prior release. To preserve the paperâs conditional semantics, both operations would also retain runtime event checks and do nothing when those checks fail. The static Rust trait machinery would not carry over directly; Verus proves the relation rather than relying on trait selection.
evidence and limits
Theorem 1 states soundness of the flows-to relation: if the static derivation holds and S holds on a trace, the semantic label ordering holds on that trace and its extensions (Theorem 1, p. 15). The paperâs proof is by induction on static inference rules, with explicit cases for R-To and D-To (p. 15). Inference: Soundness relative to these semantics does not establish that a developerâs chosen labels express the applicationâs intended requirements.
what it is and when to use it
Standard noninterference uses a fixed set of public variables and an invariant indistinguishability relation. Dynamic release changes which data are public, so the paper parameterizes indistinguishability by the security-event trace and adds consistency conditions for intentional release (Introduction §1, p. 3; Soundness Proof §5, pp. 17â21).
proof steps
- Fix an arbitrary source label B and attacker level L. Let
Î(x)be the label assigned to variablex. Require memories to agree on everyxfor whichB âĎ Î(x)fails; this ordering requires B to be at or belowÎ(x)on every extension of the current trace Ď (Definition 10, p. 18). Trace preservation ensures this set cannot grow as execution proceeds (Lemma 1, p. 19). - Introduce bracketed sensitive values and commands. Compare effective outputs: outputs visible at L while B remains secret from L. Trace consistency requires equal numbers of effective outputs and equal final effective output events, rather than equality of every earlier effective output (Definitions 6â7, p. 12; §5, p. 19).
- Prove an unwinding lemma while B remains secret and the persistent-output exception is absent. A step from equivalent well-formed states can be matched by zero or more steps preserving memory and command equivalence and equal attacker-visible output projections, or the counterpart diverges inside a bracketed command (Lemma 2, p. 19; Appendix E.6).
- Prove preservation of command typing and memory well-formedness under the augmented semantics (Appendix E.4, Lemma 7).
- Induct on trace length. For transient policies, split each step according to whether the source remains inaccessible at attacker level L. For persistent policies, handle immutable values that were already released as a separate case (§5, pp. 20â21).
- Conclude Theorem 3: every well-typed command satisfies dynamic release for every execution (Theorem 3, p. 20).
Theorem 3 states that a command accepted by the type system satisfies dynamic release (p. 20; Appendix E.6). The assurance is explicitly termination-insensitive: âNote that the Lemma also allows đ 2 to diverge, making the dynamic release assurance termination-insensitive [5, 7].â (§5, p. 19). Inference: The theorem establishes security for the formal language; it does not by itself establish security for arbitrary Rust code.
Verus form (inference)
Inference: A Verus development could encode the operational state and event trace as an abstract state machine. The proof would need memory equivalence, effective-output consistency, and the exceptions for intentional release; transition proofs could establish unwinding where its premises hold. requires would state initial equivalence and well-formed labels, while ensures would preserve the invariant. This would require modeling the Rust wrapper and all relevant I/O effects; the paper does not provide such a Verus encoding.
implementation and measured evidence
The authors ported a conference-reviewing system and Civitas, totaling approximately 1,700 lines of Rust on top of the prototype (§6.2, p. 22). The conference examples include password disclosure and score release; Civitas includes credential erasure and voter-share deletion (§6.2, pp. 22â24). Median execution time over 100 runs is reported as 0.029 ms original versus 0.033 ms IFC for the conference system, and 5.694 ms versus 5.736 ms for Civitas (§6.3, p. 24). The authors attribute low overhead to event traces growing only at event and output commands and being checked only at relabel commands (p. 24). They report: âwe verified that all case studies produce the same outputs as the original programs without information flow control.â (§6.3, p. 24). Inference: This is a case-study check of outputs, rather than an equivalence theorem for arbitrary Rust programs.
The Civitas port excludes a component described as âexcluding its cryptography proof componentâ (§6.2, p. 22). Inference: Applying the theorem to a deployed Rust application requires confidence in the compiler, trait encodings, event-trace code, wrappers, and correspondence between application behavior and the formal model. A policy/specification mismatch or an operation bypassing labeled APIs would require separate analysis; the paper does not rank these risks or establish a Verus proof of its Rust library.
techniques for the catalog
- dynamic-release labels â attach conditional, transient or persistent security labels whose meaning changes with an event trace
- event-trace oracle â carry
usingfacts about event history and prior releases into compile-time checks - separate flows-to and release-to â distinguish future-safe label flow from current-point output permission
- trace-indexed unwinding proof â establish termination-insensitive dynamic release through memory equivalence, effective-output consistency, and a separate persistent-output case
- Rust trait enforcement â encode label relations in phantom types and trait bounds for compile-time checking
Last edited: