fix(kernel): reject circular safe definitions and pin IxVM rejection - #637
Merged
Merged
Conversation
The Rust kernel could accept a safe declaration whose value was a reference to itself: looking up the reference returned its declared type without establishing that its definition was well founded. For example, with only P : Prop as an axiom, `theorem loop : P := loop` was accepted. Raw Ixon can also encode an axiom-free circular definition of `forall P : Prop, P`, or put the same attack in a singleton or mutually dependent definition block. This is a soundness defect: invalid proofs were accepted. Port the Rust admission guard from #630 (2f0b47c). Before typechecking a safe definition, traverse definition references in both its type and value, including binder domains, let initializers, shared syntax, and projection heads. Explicit worklists distinguish active declarations from completed ones and reject cycles, including cycles spanning internal blocks. Expression traversal deduplicates shared syntax without recursive host-stack calls. The host traversal fails closed at one million dependency tasks. Axioms, inductives, constructors, and recursors retain their own admission rules; partial and unsafe definitions retain their existing policy. IxVM is already protected against this attack: ingress gives safe definitions neither a standalone self-reference slot nor mutual peer slots. Add hash-bound Ixon exploit fixtures to demonstrate that protection through the production verify_claim entrypoint, using both the bytecode interpreter and generated executor. Cover self-reference in definitions, theorems, and opaque declarations; mutual cycles; cycles hidden in types, let initializers, and sharing; and misleading theorem/opaque safety bytes. A closed identity proof must be accepted as a positive control. These tests require successful witness construction before checking rejection. No IxVM implementation, generated code, or FFT pin changes are needed. The Rust unit regressions reproduced acceptance before the fix. They now reject the attacks and cover projection-head dependency collection and preservation of partial/unsafe behavior. The serialized fixtures also run through the Rust checker with hash verification enabled, requiring the cycle diagnostic for invalid targets. Positive Rust controls retain valid acyclic forward references and shared dependencies. Exported structural, well-founded, and mutual recursion fixtures check all 33, 1350, and 26 targets respectively, with no omitted requested definitions. The shared fixtures run in the focused kernel-dependencies runner and the IxVM suite. Validation: - cargo test --locked --release -p ix-kernel: 846 passed, 8 ignored. - lake test --wfail -- --ignored kernel-dependencies: 44 checks passed. - cargo clippy --locked --release --workspace --all-targets --features ix-ffi/parallel,ix-ffi/net,ix-ffi/test-ffi -- -D warnings: passed. - cargo fmt --all -- --check and git diff --check: passed. - ix codegen --check: all three generated targets are up to date. Co-authored-by: John C. Burnham <john@agathic.com>
arthurpaulino
enabled auto-merge
September 17, 2026 14:22
johnchandlerburnham
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Rust kernel could accept a safe declaration whose value was a reference to itself: looking up the reference returned its declared type without establishing that its definition was well founded. For example, with only P : Prop as an axiom,
theorem loop : P := loopwas accepted. Raw Ixon can also encode an axiom-free circular definition offorall P : Prop, P, or put the same attack in a singleton or mutually dependent definition block. This is a soundness defect: invalid proofs were accepted.Port the Rust admission guard from #630 (2f0b47c). Before typechecking a safe definition, traverse definition references in both its type and value, including binder domains, let initializers, shared syntax, and projection heads. Explicit worklists distinguish active declarations from completed ones and reject cycles, including cycles spanning internal blocks. Expression traversal deduplicates shared syntax without recursive host-stack calls. The host traversal fails closed at one million dependency tasks. Axioms, inductives, constructors, and recursors retain their own admission rules; partial and unsafe definitions retain their existing policy.
IxVM is already protected against this attack: ingress gives safe definitions neither a standalone self-reference slot nor mutual peer slots. Add hash-bound Ixon exploit fixtures to demonstrate that protection through the production verify_claim entrypoint, using both the bytecode interpreter and generated executor. Cover self-reference in definitions, theorems, and opaque declarations; mutual cycles; cycles hidden in types, let initializers, and sharing; and misleading theorem/opaque safety bytes. A closed identity proof must be accepted as a positive control. These tests require successful witness construction before checking rejection. No IxVM implementation, generated code, or FFT pin changes are needed.
The Rust unit regressions reproduced acceptance before the fix. They now reject the attacks and cover projection-head dependency collection and preservation of partial/unsafe behavior. The serialized fixtures also run through the Rust checker with hash verification enabled, requiring the cycle diagnostic for invalid targets. Positive Rust controls retain valid acyclic forward references and shared dependencies. Exported structural, well-founded, and mutual recursion fixtures check all 33, 1350, and 26 targets respectively, with no omitted requested definitions. The shared fixtures run in the focused kernel-dependencies runner and the IxVM suite.
Validation: