cross-chain-messaging
Skill36 starsChanged 5 months agoMITView on GitHub
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.
In this repository44 other files it gives its agents.
- access-controlSkill
- approval-issuesSkill
- caching-and-incrementalSkill
- centralization-riskSkill
- confidence-scoringSkill
- cosmwasmSkill
- cross-contract-stateSkill
- delegatecall-risksSkill
- diamond-eip2535Skill
- dos-vectorsSkill
- erc1271-contract-signaturesSkill
- erc4337-account-abstractionSkill
- erc4626-inflationSkill
- false-positive-feedback-loopSkill
- fee-on-transferSkill
- flash-loan-attacksSkill
- initializationSkill
- inline-assemblySkill
- integer-issuesSkill
- intents-erc7683Skill
- known-good-comparisonSkill
- liquidation-cascadeSkill
- mev-frontrunningSkill
- mev-pbsSkill
- multi-pass-self-critiqueSkill
- oracle-manipulationSkill
- oracle-redundancySkill
- permit2-patternsSkill
- pragma-and-addressesSkill
- progress-and-streamingSkill
- reentrancySkill
- restaking-eigenlayerSkill
- selfdestruct-eip6780Skill
- signature-malleabilitySkill
- signature-replaySkill
- solana-anchorSkill
- storage-layoutSkill
- stylus-rustSkill
- token-compatibilitySkill
- tx-context-misuseSkill
- unchecked-callsSkill
- ve-lock-governanceSkill
- vyper-specificSkill
- zk-verifier-bugsSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 70
If setTrustedRemote is onlyOwner and owner is an EOA, the bridge can be silently rerouted.
- Very specific: line 91
Always validate srcChain and srcAddress against an allowlist.
- Distinctive: line 92
Always include destination chainId in the verified payload.
- Distinctive: line 95
Use chainId-aware helpers for L2 block number / time.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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
srcChainandsrcAddressagainst 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)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

