Skip to content
Security
Skill

/cross-chain-messaging

Detect cross-chain messaging bugs — replay protection gaps, untrusted-remote acceptance, default-config inheritance, validator-set misconfig, force-include vulnerabilities, chainId / domain-separator omissions. Activate on `_lzReceive`, `ccipReceive`, `handle` (Hyperlane),

From plugin
rugproof
1052 skills23 agents45 commands4 hooks

Claude Code

$ npx -y skills add omermaksutii/RugProof --skill cross-chain-messaging --agent claude-code

SKILL.md

cross-chain-messaging.SKILL.md
name: cross-chain-messaging
description: Detect cross-chain messaging bugs — replay protection gaps, untrusted-remote acceptance, default-config inheritance, validator-set misconfig, force-include vulnerabilities, chainId / domain-separator omissions. Activate on `_lzReceive`, `ccipReceive`, `handle` (Hyperlane), `receiveMessage`, `verifyVAA`, IRouterClient, IMailbox, EndpointV2, OApp/OFT, LayerZero / CCIP / Hyperlane / Wormhole / Axelar / Polyhedra integration code.

Cross-chain messaging detection

When this applies

  • Any application built on LayerZero, CCIP, Hyperlane, Wormhole, Axelar, Polyhedra ZKBridge
  • Native L1↔L2 messengers (Optimism, Arbitrum, Base, zkSync, Linea, Scroll)
  • Custom bridges / message-passing layers

Detection patterns

`_lzReceive` accepts any remote (CRITICAL — LayerZero)

function _lzReceive(bytes calldata srcAddr, bytes calldata payload) internal {
    // no allowlist of trusted remote
    _executeMint(payload);   // ← any chain can mint
}

Required: `require(trustedRemote[srcChainId] == srcAddr)`.

CCIP `ccipReceive` callable directly (CRITICAL)

function ccipReceive(Any2EVMMessage calldata m) external {   // ← public, no router check
    _execute(m.data);
}

Required: `require(msg.sender == address(router))`.

Hyperlane `handle` without ISM check (CRITICAL)

Hyperlane's default ISM is permissive. Apps must set their own. If `handle` is called by mailbox without app-side validation, anyone can spoof messages.

Wormhole VAA double-spend (CRITICAL)

function complete(bytes calldata vaa) external {
    IWormhole.VM memory vm = wormhole.parseAndVerifyVM(vaa);
    _mint(vm.payload.to, vm.payload.amount);   // ← no per-VAA seen check
}

Required: track `usedVAAs[vm.hash] = true` after first use.

Replay across chains (CRITICAL)

Same payload accepted on multiple destination chains. Include destination `chainId` in the signed/verified payload.

Default DVN / ISM / config inheritance (HIGH)

Application doesn't set explicit DVN set (LayerZero V2) or ISM (Hyperlane). Default configs are often weak. Look for explicit `setSendLibrary`, `setReceiveLibrary`, `setEnforcedOptions`, `setInterchainSecurityModule`.

chainId mapping mistakes (HIGH)

LayerZero EIDs ≠ chainIds. CCIP uses chainSelectors. Map wrong → message goes to wrong chain or stuck forever.

Insufficient gas in `_lzSend` / `_options` (MEDIUM)

Receiver runs out of gas → message stuck (LayerZero V2 retry semantics).

Force-include on L1↔L2 messengers (HIGH)

Anyone can force-include an L1→L2 transaction. If app assumes only sequencer can trigger certain flows, force-include breaks the assumption.

L2→L1 withdrawal delay assumption (MEDIUM)

Optimism: 7-day challenge. Arbitrum: 7-day. App that assumes funds arrive instantly L2→L1 → invariant broken.

Pause authority not granular (MEDIUM-HIGH)

Single pause for all routes vs per-route → over- or under-blast-radius.

LayerZero V2 compose reentrancy (HIGH)

`_lzReceive` triggering a compose call back into `lzCompose` re-enters during the same message. Treat composed messages as reentrant calls.

Trusted remote table update authority (HIGH)

If `setTrustedRemote` is `onlyOwner` and owner is an EOA, the bridge can be silently rerouted. See [[centralization-risk]].

Severity rubric

| Pattern | Severity | |---|---| | Receive function accepts any remote | **Critical** | | Receive function callable directly (not router/mailbox) | **Critical** | | VAA / message not marked seen → double-spend | **Critical** | | Cross-chain replay (no destination chainId binding) | **Critical** | | Default ISM / DVN config (no app-side override) | **High** | | chainId/EID/chainSelector mapping mistake | **High** | | Compose reentrancy in LayerZero V2 | **High** | | Force-include L1→L2 assumption | **High** | | L2→L1 withdrawal-delay assumption | **Medium** | | Single-key trusted-remote update authority | **High** | | Insufficient gas in send → message stuck | **Medium** |

Remediation patterns

  • Always validate `msg.sender == router/mailbox/endpoint`.
  • Always validate `srcChain` and `srcAddress` against an allowlist.
  • Always include destination chainId in the verified payload.
  • Mark messages seen by `(srcChain, srcAddr, nonce/hash)`.
  • Configure DVN / ISM / executor explicitly per chain.
  • Use chainId-aware helpers for L2 block number / time.
  • Per-route pause + global emergency pause.
  • Trusted-remote updates via timelock + multisig.

False-positive notes

  • Canonical OApp / OFT / OFT-Adapter from LayerZero Labs handle most of the above; verify the app didn't override unsafely.
  • CCIP RouterClient / ARM are well-tested; the bug surface is in the app's `ccipReceive`.

Related

  • [[crosschain-messaging-specialist]] (subagent)
  • [[signature-replay]]
  • [[bridge-specialist]] (asset bridges built on top)
Read more
@omermaksutii
Ships withrugproof

Rugproof your code before someone else does. 🌐 Live site: omermaksutii.github.io/RugProof 📦 Latest: v1.0.0 — 45 commands · 23 agents · 45 skills · 13 MCP servers · tested, offline-first, with rule packs, a benchmark, non-EVM coverage, and post-deploy

1052 skills23 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
10
Star history of omermaksutii/RugProof on GitHub, a chart by star-history.com

Other skills on rugproof.

More skills from other plugins.

api-security

api-security

Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…

@zhaoxuya520@zhaoxuya520Install Skill
nemoclaw-user-guide

nemoclaw-user-guide

Find official NemoClaw documentation for installation, configuration, operation, or troubleshooting. Also handles requested docs…

nemoclaw10d23k
@nvidia@nvidiaInstall Skill

Questions about cross-chain-messaging.

Which coding agents can use cross-chain-messaging?
cross-chain-messaging installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.