Claim Hyperlane infrastructure ownership for governance

Hey @igorveras1 - I am leaving my research about the proposal here in this thread - so the others can use it to

What the Proposal Does

Your proposal claims to execute a claim endpoint on 8 contracts that have underlying code IDs using the governance account as executor.

Research Questions and Answers

  • Do the on-chain wasm codes of the involved contracts match the compiled source? Yes. All 8 code IDs rebuild byte-for-byte with cosmwasm/optimizer:0.15.0 from upstream many-things/cw-hyperlane tag v0.0.7-rc0.
  • Is claim_ownership malicious? No. It only sets the owner to governance and emits one event (as per the above mentioned repository).
  • Other concerns? Yes, one pre-existing security issue: the deployed multisig ISM predates upstream fix #142, which stops one validator’s signature being counted more than once (see below).

Recommendation: Vote for the proposal. Once governance owns the contracts, it should follow up by migrating the ISMs to fixed code.

Code-hash verification

On-chain Code vs. Release Artifacts

The wasm was downloaded from the LCD (/cosmwasm/wasm/v1/code/<id>). The sha256 of each download equals the chain-reported data_hash, and also equals the official GitHub release many-things/cw-hyperlane v0.0.7-rc0 (published 2024-06-26).

code_id Contract sha256
11371 hpl_mailbox b6d789c1a31ee79548fd736bad241dbcd3b8b319d66a776f31479743fe49eb01
11374 hpl_ism_multisig 32b07207c733ba7469f49d321c30cf00bacb8c9560dc92accd35df61e5e3a531
11376 hpl_ism_routing 0881d65f470425290990e53b87044477eaf704e0f2da8481eb4150c6e8c8143c
11377 hpl_igp 34313c90c9e08d2c342061412fafe4d064ad783f9be606255d0720590e6fad0b
11378 hpl_hook_aggregate 9dfbe1ba3e0dde5ea82cb0daee819214e46afb2ac78075c4f26523e6879a5004
11379 hpl_hook_fee c981467b9af207d09aac90716598ed51c547526b8b82189148a24e1704e7956e
11381 hpl_hook_pausable 0f53c4193be46b15eca53ff8cb2004dcc571bf74b345b2b7af2775b6fa99b6c2
11390 hpl_warp_native 34b5deb86937f51d4b04ddc572597b95ffd1b3ce094df8a73dc1cf20babc7e55

Reproducible build from source

The code was rebuilt independently on my local machine. Result: all 20 release wasms reproduce byte-for-byte, including all 8 code IDs above, each compared directly against the downloaded on-chain code. To reproduce the build I have the following remarks:

  • Source: github.com/many-things/cw-hyperlane tag v0.0.7-rc0, commit eb791b56db03dae27da5b58faa034274d813bb24.
  • Builder: cosmwasm/optimizer:0.15.0. This is the same image the upstream release.yaml / make ci-build uses.
  • Lockfile: the repo ships no Cargo.lock, and CI ran cargo generate-lockfile at release time. That resolution was recreated in two steps:
    1. cargo +nightly -Zunstable-options generate-lockfile --publish-time 2024-06-26T04:55:00Z
    2. Pin the versions that have since been yanked, identified from the dependency paths embedded in the release wasm: cosmwasm-std/-crypto/-derive/-schema(-derive) 1.5.5, keccak 0.1.5, bytes 1.6.0, bnum 0.10.0.
  • Non-output-affecting tweaks: the integration-test crate was removed from the workspace, and the [dev-dependencies] sections were stripped. Dev-deps are not compiled into release wasm under resolver v2, and today’s versions need a newer cargo than the one in the image.

Relationship to terra-classic-hyperlane/cw-hyperlane

The fork’s contracts/ and packages/ match upstream main as of January 2025, not the deployed tag. The fork contains 4 upstream commits the deployed code lacks:

Upstream PR Change Severity
#142 Multisig ISM: stop counting duplicate validator signatures High (see §4)
#138 Mailbox Process event emits origin domain instead of local domain Cosmetic
#139 Pausable ISM event name fix Cosmetic
#143 Allow unsetting ISM/hook Feature

A build of the fork’s current main would not match the on-chain hashes. The deployed code is exactly upstream v0.0.7-rc0, which is also what the fork’s own deployment docs state (cw-hpl upload remote v0.0.7-rc0).

Pre-existing issue: multisig ISM duplicate signatures (code 11374)

In the deployed v0.0.7-rc0 contracts/isms/multisig/src/query.rs::verify_message, every signature from an address in the validator set decrements the threshold. There is no check for a validator that has already been counted:

for signature in metadata.signatures {
    let pubkey = deps.api.secp256k1_recover_pubkey(&hashed_message, &signature[..64], signature[64] - 27)?;
    if validators.contains(&eth_addr(pubkey.into())?) {
        threshold -= 1;
        if threshold == 0 { break; }
    }
}

Impact: the relayer supplies the metadata. Repeating one validator’s valid signature N times therefore satisfies an N-of-M threshold. A single compromised or malicious validator key on the ETH, BSC or SOL inbound set could get arbitrary inbound messages accepted, including warp transfers that release native LUNC/USTC.

Upstream fixed this in PR #142 (commit d07e55e, 2024-11-11) using a HashSet of matched validators. The fix is present in the fork’s source but not in the deployed code.

Recommended Follow-Up

After this proposal passes, governance should migrate the three multisig ISMs, and optionally the mailbox and pausable ISM, to a verified build that includes #142.