example-fork-detection
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on `<your trigger keywords or…
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),
$ npx -y skills add omermaksutii/RugProof --skill cross-chain-messaging --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/cross-chain-messagingContext preview
The summary Claude sees to decide when to auto-load this skill.
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),
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.
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)`.
function ccipReceive(Any2EVMMessage calldata m) external { // ← public, no router check
_execute(m.data);
}Required: `require(msg.sender == address(router))`.
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.
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.
Same payload accepted on multiple destination chains. Include destination `chainId` in the signed/verified payload.
Application doesn't set explicit DVN set (LayerZero V2) or ISM (Hyperlane). Default configs are often weak. Look for explicit `setSendLibrary`, `setReceiveLibrary`, `setEnforcedOptions`, `setInterchainSecurityModule`.
LayerZero EIDs ≠ chainIds. CCIP uses chainSelectors. Map wrong → message goes to wrong chain or stuck forever.
Receiver runs out of gas → message stuck (LayerZero V2 retry semantics).
Anyone can force-include an L1→L2 transaction. If app assumes only sequencer can trigger certain flows, force-include breaks the assumption.
Optimism: 7-day challenge. Arbitrum: 7-day. App that assumes funds arrive instantly L2→L1 → invariant broken.
Single pause for all routes vs per-route → over- or under-blast-radius.
`_lzReceive` triggering a compose call back into `lzCompose` re-enters during the same message. Treat composed messages as reentrant calls.
If `setTrustedRemote` is `onlyOwner` and owner is an EOA, the bridge can be silently rerouted. See [[centralization-risk]].
| 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** |
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
Repo: omermaksutii/RugProof
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on `<your trigger keywords or…
Detect unsafe assumptions about Solady's gas-optimized ERC20/ERC2612 permit and DN404 metadata. Solady's ERC20 uses custom storage slots, returns bools via…
Detect front-runnable ownership initialization in Solady Ownable / OwnableRoles. Solady's `_initializeOwner` is a guarded one-time setter (it reverts with…
Detect Solady SafeTransferLib calls that assume the token has code. SafeTransferLib.safeTransfer/safeTransferFrom/safeApprove deliberately skip the EXTCODESIZE…
Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates (BeforeSwapDelta, afterSwap hookDelta,…
Detect Uniswap V4 hooks whose address-encoded permission flags don't match the callbacks the hook actually implements. In V4 the hook's permissions live in the…