OMEGA V4 Security Audit · V0.7 GA

41 findings.
All resolved.

Full adversarial audit of the Covenant compiler before V0.7 public launch. Every finding is documented, reproducible, and public.

5 Critical — resolved
8 High — resolved
8 Medium — resolved
6 Low — resolved
9 Informational
5 Audit phases
01 — Methodology

OMEGA V4: assume every guarantee is a lie

OMEGA V4 is Kairos Lab's internal adversarial audit framework. It is not a checklist. It's a mindset: assume every guarantee the compiler claims to enforce is a lie, and try to prove it. The question is never "does the source look right?" — it's "does the emitted bytecode contain the bytes the source promised?"

02 — Critical Findings

Five failures that would have made every contract a honeypot

These findings share a pattern: the source looked correct, the tests passed, the contracts deployed — but the generated bytecode did not enforce the guarantee the source promised. Silent codegen failures are the worst class of bug.

KSR-CVN-011
Critical Resolved

IrGuard never codegenned — access control was fiction

Covenant's access control system lets developers write only(owner), when(condition), and given(proof) clauses on actions. These should emit a CALLER + EQ + ISZERO + JUMPI pattern targeting the revert path before any function body executes.

The IR builder accepted and type-checked the clause, but the emit_only_assert function was never called. Every deployed Covenant contract with an access control clause would silently accept calls from any address.

Before — emitted bytecode
; withdraw_all() — NO ACCESS CHECK
JUMPDEST
PUSH1 0x00
SLOAD         ; load balance
CALLER        ; push msg.sender
; (transfer — no guard before it)
PUSH1 0x00
PUSH1 0x00
SSTORE        ; clear balance
STOP
After — with guard
; withdraw_all() — GUARDED
JUMPDEST
CALLER        ; msg.sender
PUSH32 …      ; stored owner
SLOAD
EQ
ISZERO
PUSH2 revert  ; revert if ≠
JUMPI
; (transfer follows)

Fix: emit_only_assert in covenant-ir/src/builder.rs now emits LoadCaller → LoadPrincipal → Eq → Assert. The EVM backend lowers Assert to ISZERO + JUMPI → __revert__. Regression test in covenant-evm-backend/tests/guard_codegen.rs asserts every only() in source produces the CALLER + EQ + ISZERO + JUMPI pattern in the bytes.

KSR-CVN-012
Critical Resolved

Proxy initializer had no re-init guard — one transaction hijack

Covenant supports UUPS upgradeable proxy patterns. An initializer action is supposed to be callable exactly once. But the bytecode had no re-init guard — initialize() could be called repeatedly, overwriting owner and treasury with attacker-controlled addresses.

Fix: emit_initializer_guard wraps every initialize action with a slot-based flag. The slot is keccak256("covenant.proxy.initializer.<ModuleName>") — EIP-7201 namespaced, unique per module. The bytecode reads the slot, reverts if already set, then sets it before executing the body. Phase 3 is terminal — no re-entry possible.

KSR-CVN-013 + 014
Critical Resolved

Precompile call safety — PQ signature bypass via stale memory

Cryptographic precompiles (FHE ops, Dilithium verify, ZK proof check) are invoked via STATICCALL. Two separate failures combined into a full bypass of post-quantum authentication:

CVN-013: The STATICCALL success flag was popped and discarded. A precompile that reverted (invalid input, out of gas) was treated as successful.

CVN-014: Before STATICCALL, the return memory slot was not zeroed. A failed STATICCALL left stale memory that MLOAD read as a nonzero value — interpreted as "signature verified".

Combined exploit: An attacker submits a forged Dilithium signature. The precompile reverts. The success flag is dropped. The MLOAD reads stale memory containing a nonzero value from a prior operation. Authentication succeeds. One transaction, deterministic in deployments with prior operations.

; Three-layer defense added to every precompile call:
PUSH0 PUSH0 MSTORE ; 1. zero the return slot
(args setup)
STATICCALL
ISZERO ; 2. check success flag
PUSH2 revert_label
JUMPI
RETURNDATASIZE
PUSH1 32
EQ ; 3. check return size == 32
ISZERO
PUSH2 revert_label
JUMPI

Bytecode differential: runtime bytecode grew from 835 → 1336 bytes. The ISZERO opcode count went from 9 → 47. That's 38 new safety checks, one per precompile call site. CI now asserts ISZERO count as a lower bound.

KSR-CVN-001
Critical Resolved

Ceremony phase transitions unchecked — cryptographic amnesia bypass

Covenant implements ERC-8228 (Cryptographic Amnesia Interface). Amnesia ceremonies have a strict four-phase state machine: idle → gathering → finalized → destroyed. Only phase reads were checked; phase transitions had no guards. An attacker could call destroy() at phase 0, jump to phase 3, and have is_destroyed() return true without a key ever having existed.

Downstream integrations (GDPR compliance, regulatory data erasure, institutional key destruction proofs) rely on is_destroyed() being trustworthy. With transitions unchecked, the state machine was decorative.

Fix: Every ceremony function now checks its required precondition phase via emit_assert_phase_eq(expected_phase). Phases are enforced at bytecode level via SLOAD + EQ + ISZERO + JUMPI. Phase 3 is terminal — no function takes phase 3 as a valid input state.

03 — High Findings

Eight high-severity issues

High findings caused incorrect or insecure behaviour without being fully exploitable in isolation. Several had been present since early compiler versions with no visible test failures.

ID Finding Commit
KSR-CVN-015 FheCmpNe and FheCmpLe dispatched to wrong precompile addresses — aliasing EQ and LT. Every encrypted != and <= returned an incorrect result. d378297
KSR-CVN-016 CSE optimizer collapsed distinct FheEncryptFresh calls. Two ciphertexts from "fresh" encryption were collapsed to one — the "fresh" guarantee was destroyed. f3a5277
KSR-CVN-017 Same CSE bug collapsed PqRand calls — post-quantum nonces reused across operations that required distinct randomness. f3a5277
KSR-CVN-018 Reentrancy lints didn't cover the ExternalCall opcode — cross-contract reentrancy went undetected by the linter. d88910c
KSR-CVN-019 No EXTCODESIZE canary before CALL to external contracts — EOA and self-destruct patterns went undetected. 5ee93a8
KSR-CVN-020 No 4-byte ABI selector prefix on precompile calldata — precompile ABI versioning not enforced at call sites. 5ee93a8
KSR-CVN-021 @slot(N) annotation silently ignored — layout guarantees promised to developers were not enforced in emitted bytecode. 0eb1ad8
KSR-CVN-027 External CALL and STATICCALL success flags discarded — same class as CVN-013, affecting user-invoked external calls. 5eb1c38
04 — Medium · Low · Informational

23 further findings — the long tail of defense

Medium findings affected correctness and developer safety. Low and Informational findings strengthened tooling, diagnostics, and supply chain. All resolved before V0.7 GA.

KSR-CVN-022, 023 — Shamir / VDF hard-fail: Shamir Secret Sharing and Wesolowski VDF opcodes emitted broken stubs that silently succeeded without performing any cryptographic work. Rather than emit silent fiction, the compiler now hard-fails with E516/E517 for these opcodes until V0.8 chain support ships. "Deploy no code" beats "deploy broken code."

KSR-CVN-024, 025 — P4/P5 invariant detectors: Privacy invariants P4 (nonce reuse) and P5 (monotonicity) had no lint detectors in the security pass. Detectors added.

KSR-CVN-026 — FheBootstrap eliminated by DCE: Dead Code Elimination was removing FheBootstrap calls (which refresh FHE ciphertext noise budget) because they appeared to have no side effects. DCE now marks FHE refresh ops as side-effecting.

Storage / supply chain: @slot(N) collision detection wired (E423), annotation validation, PRECOMPILE_ABI_VERSION marker in bytecode, Cargo.lock pinning, per-chain version binding. Full list in covenant-audits.

05 — What the audit taught us

Four lessons that change how we write tests

06 — Known limitations

What V0.7 does not yet support

Shipping broken stubs is worse than shipping nothing. These features are deliberately disabled until they can be implemented correctly.

Shamir Secret Sharing (E516)
Contracts using shamir_split, shamir_recover, or @shamir_threshold will not compile. Full implementation requires Aster Chain support (V0.8).
Wesolowski VDF (E517)
Contracts using vdf_eval or @vdf_locked will not compile. Same dependency on Aster SDK for chain-native VDF verification.
🔧
Aster Chain bytecode emission (V0.7 foundation only)
--target-chain aster compiles to a placeholder artifact (COV7\x01 magic + metadata). Full bytecode emission requires Aster SDK GA. V0.7 artifacts are not deployable on-chain.
🔧
External audits (V0.9 target)
OMEGA V4 was a self-audit. V0.9 will bring independent audits from two external firms. Self-audit is not a substitute for independent verification — this is the roadmap, not a guarantee.
07 — Access the full report

Everything is public. PoCs included.

The full OMEGA V4 report is public at github.com/Valisthea/covenant-audits. Every finding has a finding ID, severity, description, annotated bytecode PoC, remediation commit, and regression test. If OMEGA V4 missed something, that's a welcome problem — the bounty program is in the same repo.

QUICK INSTALL

cargo install covenant-cli