Canto — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for Canto, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 14
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 14 closed, publicly disclosed Canto reports indexed on CoinBuggie. Nothing here is active or unpatched — every entry was published by the programme or the researcher after remediation.
The findings concentrate in Logic error, Integer overflow / underflow, Access control, Governance attack, across Cosmos-SDK, EVM-Solidity. Reading a single protocol end to end is the fastest way to see which assumptions its codebase repeatedly gets wrong, which is usually a better predictor of where the next finding lives than the category alone.
Use the vulnerability class links below to compare these findings against the same bug class in other protocols.
What reviewers look for
- Logic error findings disclosed against Canto
- Integer overflow / underflow findings disclosed against Canto
- Access control findings disclosed against Canto
- Governance attack findings disclosed against Canto
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
Canto: Incorrect names provided in `RegisterConcrete` calls break `LegacyAmino` signing method
Canto's upgrade to Cosmos SDK v0.50 changed the Amino JSON codec, and to preserve legacy serialization behavior the team added amino.name tags to proto message types. This report catalogs mismatches between those proto tags and the names passed to RegisterConcrete in each module's RegisterInterfaces function, spanning coinswap, csr, erc20, inflation, onboarding, evm, and feemarket. Because the registered and encoded names differ, LegacyAmino-signed transactions carry an unexpected type prefix, so signatures/tx encoding for those messages break. The author proves this by adapting the SDK's generative aminojson verification test and provides a bash harness reproducing 14 failures, with the first showing coinswap/coinswap/MsgAddLiquidity encoded where canto/MsgAddLiquidity was expected.
Canto: `Govshuttle` module does not register its transaction `MsgServer`
Canto's x/govshuttle Cosmos SDK module defines two governance-proposal messages, MsgLendingMarketProposal and MsgTreasuryProposal, handled by its keeper, but its AppModule.RegisterServices only registers the QueryServer and never the MsgServer. Because no message handler is routed to the govshuttle keeper, approved governance proposals carrying those messages silently execute nothing. This is a configuration/availability defect confirmed by Canto as mid severity, with a patch planned before the v0.50 production release, rather than a directly exploitable security issue.
Canto: `MsgSwapOrder` will never work for Canto nodes
Canto's coinswap module defines a MsgSwapOrder whose nested Input message omits the cosmos.msg.v1.signer annotation, and no DefineCustomGetSigners resolver was registered for it in app.go, so the chain cannot derive the signer and the transaction can never be delivered. Because MsgSwapOrder is unusable, the only executing swap path is the keeper-directed one-way IBC auto-swap from the ibc voucher to canto during onboarding, leaving no working arbitrage mechanism to pull a drifted pool price back to fair value. Once drift grows large enough, subsequent onboarding swaps fail their slippage and maxSwapAmount checks, degrading availability of the onboarding functionality. The sponsor initially rated this QA on the basis that direct price manipulation is hard, but the judge re-confirmed Medium given the availability impact.
Canto: An attacker can DoS a coinswap pool
Canto's coinswap module computes pool escrow balances by calling GetAllBalances, which iterates over and sorts every token denomination held at the escrow address. Because Canto is IBC-connected, an unprivileged attacker can deposit an arbitrarily large number of distinct token denoms into a pool's escrow, causing AddLiquidity, RemoveLiquidity and swap transactions to exhaust gas and fail. The sponsor confirmed the flaw but argued pool creation is whitelist-restricted, narrowing practical impact to the auto-swap during onboarding; the judge nevertheless adjudicated the issue group as Medium given the permissionless IBC-driven DoS. The agreed fix replaces the unbounded GetAllBalances query with direct balance lookups for only the standard, counterparty and LP denoms.
Canto: If a gauge that a user has voted for gets removed, their voting power allocated for that gauge will be lost
A regression in the Canto GaugeController's vote_for_gauge_weights function permanently traps user voting power. When governance removes a gauge that a user has voted for, the user can no longer withdraw their zero-weight vote from that gauge because a recently added require statement demands a non-zero gauge type for the target address, which always fails for removed gauges. This leaves the user's staked voting power locked to a nonexistent gauge for the remainder of their veCRV-style lock, preventing reallocation to other gauges and degrading their governance influence.
Canto: Truncation exploitation of partial transfer system
Canto's LendingLedger tracks per-user lending rewards by recording amount and accrued-reward debts, updated via sync_ledger for partial position transfers. The transfer path rounds down the incremental debt of (_delta * accCantoPerShare) / 1e18, so a carefully chosen small delta can be moved repeatedly while booking zero debt. Because reward claims use the cumulative user.amount, repeated truncations compound into a non-truncated value that a user with no genuine balance can instantly claim as profit. The report recommends making truncation penalize rewards rather than debt by rounding the added debt upward on the addition path while rounding down on the subtraction path.
All reports in this group
- Canto: `GaugeController::remove_gauge` will always revert whenever the gauge it's being called or has any weight attached to itInteger overflow/underflow$0
- Canto: When the `unlockOverride` flag is true, users can "freely" vote for gauge weights.Access control$0
- Canto: Improper adjustment of Lending Ledger configurationGovernance attack$0
- Canto: Improper parallel time systemLogic error$0
- Canto: secRewardsPerShare Insufficient precisionInteger overflow/underflow$0
- Canto: update_market() market weight incorrectLogic error$0
- Canto: Loss of precission when calculating the accumulated CANTO per shareInteger overflow/underflow$0
- Canto: update_market() nextEpoch calculation incorrectLogic error$0