Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
rocq-cve-poc-22024 — CVE-2026-72704 — Rocq Guard Checker Trusts Corrupted Recursive Tree After Transport | Kitploit
Tools/GitHubGitHub/endrazine/rocq-cve-poc-22024
Vulnerability AnalysisExploitationCryptographyPapers & Research
GitHubendrazine/rocq-cve-poc-22024

rocq-cve-poc-22024

CVE-2026-72704 — Rocq Guard Checker Trusts Corrupted Recursive Tree After Transport

View Repository
1 day agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-72704 — Rocq Guard Checker Trusts Corrupted Recursive Tree After Transport

Proving 0 = 1 from consistent axioms via guard checker fixpoint rectree corruption.

FieldValue
Bug reportrocq-prover/rocq#22024
FixPR #22027 (open)
AffectedRocq ≤ 9.2.0 / Coq 8.x (all versions with guard checker)
CVSS 3.1AV:L/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N — 7.1
CWECWE-670 (Always-Incorrect Control Flow Implementation)
CVECVE-2026-72704

Vulnerability Summary

The Rocq Prover's guard checker (termination checker for fixpoints) fails to recheck the rectree representation of inductive type arguments when they are modified through transport (rew). A fixpoint can silently corrupt the rectree for an inductive's type parameter, and a second fixpoint that calls the first will trust the corrupted rectree without verification, accepting a non-terminating definition as structurally decreasing.

The exploit uses two axioms that are consistent with CIC — they are direct consequences of the univalence axiom (the bijection swapping 0↔1 gives a path nat = nat in Type along which transport sends 0 to 1). A sound guard checker must not derive False from consistent axioms.

The exploit:

  • Uses only two consistent axioms (consequences of univalence)
  • Print Assumptions reports only those two axioms — no False, no sorry
  • No plugins, unsafe features, or universe manipulation
  • The guard checker is the sole source of unsoundness

Usage

docker build -t rocq-cve-poc-22024 .
docker run --rm rocq-cve-poc-22024

Expected output on a vulnerable Rocq version:

[*] Compiling ZeroEqOne.v with rocq compile ...

zero_eq_one is defined
Axioms:
e : nat = nat
e1 : rew [fun T : Type => T] e in 0 = 1

[!] VULNERABILITY CONFIRMED

    zero_eq_one : 0 = 1
    Axioms used: e (nat = nat), e1 (transport sends 0 to 1)
    These axioms are consistent (consequences of univalence).
    A sound guard checker must not derive False from them.

    Bug class:  Guard checker rectree corruption (CWE-670)
    Root cause: fixpoints can alter rectrees via transport; nested
                fixpoints trust the corrupted rectree without recheck
    Bug report: https://github.com/rocq-prover/rocq/issues/22024

Impact

Any system that trusts Rocq's kernel-checked proofs and uses axioms consistent with univalence is affected:

  • HoTT developments: any Rocq project using the univalence axiom (or propositional extensionality, which may trigger the same class of bug) could have its guard-checked fixpoints silently accepted despite non-termination.
  • Formally verified software: CompCert, CertiKOS, Iris, and any project that adds custom axioms consistent with CIC is at risk if the guard checker is the only termination guarantee.
  • Proof-carrying code: a malicious dependency can introduce the two axioms and the corrupted fixpoint, then use False downstream.

Technical Details

The Guard Checker Bug

Rocq's guard checker verifies that fixpoints are structurally decreasing by building a rectree — a tree that tracks which subterms of the recursive argument are available at each recursive call. The bug is a two-step failure:

  1. Rectree corruption: weird is a fixpoint on Box A that applies rew [Box] e (transport along e : A = A) to the recursive argument in the wrap case. The guard checker accepts this because the transport preserves the inductive type Box, but the rectree for the parameter A is silently altered — after transport, the guard checker's internal model no longer accurately tracks what values flow through A.

  2. Unchecked trust: loop calls weird loop e (wrap _ (box _ n)). The guard checker verifies loop's own recursive calls but trusts weird's rectree for the nested call. Since weird's rectree has been corrupted by the transport, the guard checker incorrectly concludes that loop is structurally decreasing.

The Contradiction

With the guard checker fooled, loop is accepted despite being non-terminating. The proof then shows:

loop 1 = S (loop 1)

by unfolding loop and weird, and using e1 to show that transport sends box nat 0 to box nat 1, which feeds back into loop. Since ∀ n, n ≠ S n is provable by induction, loop 1 = S (loop 1) yields False, and from it 0 = 1.

Why the Axioms Are Consistent

The two axioms:

e  : nat = nat :> Type
e1 : rew [fun T => T] e in 0 = 1

are consequences of the univalence axiom. Under univalence, any bijection f : nat → nat gives a path nat = nat in Type, and transport along that path acts as f. The bijection swap01 that sends 0↦1, 1↦0, and n↦n for n≥2 is such a bijection, with swap01 0 = 1 witnessing e1.

Univalence is known to be consistent with CIC (validated by cubical type theory models). Therefore these axioms cannot be the source of the contradiction — the guard checker is.

Comparison with Other PoCs

AspectRocq #22024 (this bug)Rocq #22287Lean #14484
Bug classGuard checker rectree corruptionUniverse checking state desyncInference cache poisoning
Axioms needed2 (consistent with univalence)NoneNone
Exploit complexity~30 lines6 lines~20 lines
ComponentGuard checker (fixpoint)Module system (ugraph flag)Type checker (opaque decl)
Fix statusPR #22027 (open)OpenFixed (PR #14498)

Credits

  • Bug discovery: Yann Leray (@yannl35133)
  • PoC packaging: Jonathan Brossard (@endrazine)
Download Tool