Skip to content
Security
Skill

/cosmos-ibc-security

L1 trigger - audits IBC / ibc-go cross-chain entry points for ICS-23 / Merkle proof gaps, ordered-channel sequence integrity, escrow burn<->mint synchronization, light-client version downgrade, and timeout/ack handler reentrancy.

From plugin
plamen
276160 skills12 agents4 commands
Install
$ npx -y skills add PlamenTSV/plamen --skill cosmos-ibc-security --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cosmos-ibc-security

Context preview

The summary Claude sees to decide when to auto-load this skill.

L1 trigger - audits IBC / ibc-go cross-chain entry points for ICS-23 / Merkle proof gaps, ordered-channel sequence integrity, escrow burn<->mint synchronization, light-client version downgrade, and timeout/ack handler reentrancy.

SKILL.md

cosmos-ibc-security.SKILL.md
name: "cosmos-ibc-security"
description: "L1 trigger - audits IBC / ibc-go cross-chain entry points for ICS-23 / Merkle proof gaps, ordered-channel sequence integrity, escrow burn<->mint synchronization, light-client version downgrade, and timeout/ack handler reentrancy."

Injectable Skill: Cosmos IBC Security

> **L1 trigger**: `L1_PATTERN=true` AND `IBC` (ibc-go / `/ibc/` / ics23 / IBC channels detected) > **Inject Into**: `depth-consensus-invariant`, `depth-external` > **Language**: Go (Cosmos-SDK / ibc-go) > **Finding prefix**: `[IBC-N]` > **Status**: v0.1

Orchestrator Decomposition Guide

  • Sections 1, 4: depth-external (cross-chain proof / version trust boundary — the bytes that cross the chain boundary)
  • Sections 2, 3, 5: depth-consensus-invariant (channel sequence, escrow accounting, handler reentrancy — all chain-state / safety class)
  • A single bug can span both lenses; record it once and cross-reference.

When This Skill Activates

Recon detects an IBC integration: `go.mod` requires `github.com/cosmos/ibc-go/...`, the tree has an `/ibc/` subtree, an `ics23` / `23-commitment` / `02-client` / `04-channel` path, or IBC application modules (`OnRecvPacket`, `OnAcknowledgementPacket`, `OnTimeoutPacket`, `IBCModule` impls). IBC is the trust boundary where bytes from a *foreign* chain enter local state via a verified proof — proof-verification gaps and packet-handler bugs are the highest-severity class here (forged value acceptance, fund theft, chain halt). Severity baseline is Medium; proof-bypass / fund-loss / chain-halt classes upgrade to High/Critical per `docs/l1-mode/severity-matrix.md`.

An IBC entry path is any code reachable from `OnRecvPacket`, `OnAcknowledgementPacket`, `OnTimeoutPacket`, `OnChanOpenInit/Try/Ack/Confirm`, `OnChanCloseInit/Confirm`, a relayer-submitted `MsgRecvPacket` / `MsgAcknowledgement` / `MsgTimeout` / `MsgUpdateClient`, or any keeper method consuming a commitment proof. Everything in those paths consumes attacker-influenceable bytes (the relayer is untrusted; the counterparty chain may be malicious) and MUST verify proofs against the correct path/prefix before acting.

1. Merkle / ICS-23 Proof Verification

**Check**: Every consumption of a cross-chain value must verify a full membership (or non-membership) proof against the counterparty's committed root, using the **correct commitment path PREFIX** and validating the **emitter / source** is the expected chain/channel. A proof verified against the wrong path, with a missing prefix, or without binding the value to the expected source, lets a forged value pass (ICS-23 / Dragonberry-class).

**Methodology**: 1. From `caller_map.md` / `callee_map.md` / `function_summary.md`, enumerate every call to `VerifyMembership`, `VerifyNonMembership`, `VerifyProof`, `ics23.VerifyMembership`, `commitment.VerifyMembership`, or any keeper method that takes a `proof []byte` / `MerklePath` / `MerkleProof` argument. 2. For each, confirm ALL of:

  • The proof type matches intent: a *presence* claim uses membership, an *absence* claim (e.g. "this receipt was NOT written", non-receipt-based timeout) uses **non-membership** — a membership check substituted for non-membership (or vice versa) is a finding.
  • The commitment path is built from the **full prefix** (`commitmenttypes.NewMerklePath` with the client's stored prefix / `GetCommitmentPrefix()`), not a bare key or a hardcoded/empty prefix.
  • The value bound into the proof is the value the handler then acts on (no "verify proof of X, then act on Y").
  • The proof is verified against the **client state for the expected counterparty** (correct `clientID` / connection / channel), so a value committed by a *different* chain cannot be replayed in.

3. Flag any `VerifyProof` / `VerifyMembership` call with no full path/prefix construction, with no emitter==expected-chain (clientID/channel) binding, or where membership/non-membership is mismatched to the claim.

Tag: `[IBC-PROOF-GAP:{call}:{file}:{line}:{missing:prefix|emitter|membership-kind}]`

2. Channel Sequence Integrity

**Check**: For an **ORDERED** channel, packet sequences must be processed contiguously and monotonically — sequence `n+1` must not be delivered before `n`, and a delivered sequence must not be re-delivered. For **UNORDERED** channels, the receipt store must prevent replay. Missing seq-gap / monotonicity handling lets packets be skipped, reordered, or replayed.

**Methodology**: 1. Identify the channel ordering (`channeltypes.ORDERED` / `UNORDERED`) for each in-scope channel/module and how the handler branches on it. 2. For ORDERED channels: locate the `nextSequenceRecv` (and `nextSequenceSend`/`nextSequenceAck`) read/increment. Confirm `OnRecvPacket` rejects any packet whose sequence != the expected next, and that the counter increments by exactly one. Flag a missing contiguity check or an increment that can skip/gap. 3. For UNORDERED channels: confirm a per-packet receipt (`SetPacketReceipt` / `GetPacketReceipt` / `HasPacketReceipt`) blocks replay before any state effect. 4. Verify timeout and close paths keep the sequence bookkeeping consistent (a timed-out ordered packet must close the channel or advance state per spec — a silent gap is a finding).

Tag: `[IBC-SEQ:{channel-kind}:{file}:{line}:{gap|replay|nonmonotonic}]`

3. Escrow Burn <-> Mint Synchronization

**Check**: In transfer-style IBC apps, the source chain escrows (or burns) on send and the sink chain mints a voucher on recv; on the return path the voucher is burned and the escrow released. These must be atomic and balanced: `burnAmt <= escrowBal`, every mint on the sink corresponds to an escrow on the source, and a refund (timeout/failed-ack) returns exactly the escrowed amount. An overburn, a mint without a paired escrow record, or a desync between escrow ledger and module balance leaks or destroys funds.

**Methodology**: 1. Locate the escrow/voucher accounting: escrow module address (`GetEscrowAddress`), `Mi

Read more
Ships withplamen

Autonomous Web3 security auditor for Claude Code and OpenAI Codex CLI. Orchestrates 18-100 AI agents across 40+ phases to produce audit reports with verified PoC exploits — for smart contracts and L1 node-client infrastructure.

Get the whole plugin