code-423n4 / 2023-07-axelar-findings

2 stars 0 forks source link

`AxelarServiceGovernance` can only be called cross chain #342

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L107 https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/InterchainGovernance.sol#L87-L103

Vulnerability details

Description

According to this flow chart in the docs:

flowchart
    subgraph "Destination Chain Contracts"
        direction TB
        PE{{InterchainProposalExecutor Contract}}
        PE -.->|Calls| TargetA
        PE -->|Calls| TargetB
        PE -.->|Calls| Target
        TargetA[Contract ..]
        TargetB[Contract A]
        Target[Contract ..]
    end

    subgraph "Axelar Interchain Proposal Sender"
        direction TB
        IPS -->|Encode & Submit| AxelarGateway
        AxelarGateway -.->|Emit Events| Relayer
        Relayer -.->|Execute| PE
    end

    subgraph "Source Chain Governance"
        direction TB
        Dev -->|Propose| Gov[Governor Contract]
        Gov -->|Vote & Queue| Timelock[Timelock Contract]
        Timelock -.->|Execute Proposal| IPS{{InterchainProposalSender Contract}}
    end

Cross chain commands will be proposed by "Gov" contract to "Timelock" on the same chain. Since AxelarServiceGovernance is the only contract in scope that inherits Timelock (through InterchainGovernance) we must assume this is the contract referred to as "Timelock"

The issue is that proposals can only be added through a cross chain command. Thus, if there is an urgent task, any proposal will always need to be passed through a relayer first adding time to the task.

Impact

Urgent actions will take longer since they need to be passed through relayer before being timelocked or added to multisigApprovals.

Proof of Concept

AxelarServiceGovernance inherits InterchainGovernance which in turn inherits AxelarExecutable.

A proposal is registered in AxelarServiceGovernance::_processCommand (which overrides _processCommand in InterchainGovernance):

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L107

File: cgp/governance/AxelarServiceGovernance.sol

 72:    function _processCommand(
 73:        uint256 commandId,
 74:        address target,
 75:        bytes memory callData,
 76:        uint256 nativeValue,
 77:        uint256 eta
 78:    ) internal override {
 79:        if (commandId > uint256(type(ServiceGovernanceCommand).max)) {
 80:            revert InvalidCommand();
 81:        }
 82:
            // ... commands adding
107:    }

This is only triggered from InterchainGovernance::_execute where it is enforced that the command is passed from governanceChainHash and governanceAddressHash:

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/InterchainGovernance.sol#L87-L103

File: cgp/governance/InterchainGovernance.sol

 87:    function _execute(
 88:        string calldata sourceChain,
 89:        string calldata sourceAddress,
 90:        bytes calldata payload
 91:    ) internal override {
 92:        if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash)
 93:            revert NotGovernance();
 94:
            // ... extract data from payload and validate `target` != `address(0)`
101:            
102:        _processCommand(command, target, callData, nativeValue, eta);
103:    }

_execute is in turn only called from AxelarExecutable::execute which requires it to be registered in AxelarGatway

Thus, a call to schedule a proposal in Timelock needs to be passed to a relayer first. This will unecessary time to each proposal, specially multisigApprovals who don't need to pass Timelock. It is also not in line with how the docs portray the setup.

Tools Used

Manual audit

Recommended Mitigation Steps

Consider adding a way to schedule multisigApprovals and timelock proposals from "home" chain. I.e have AxelarServiceGovernance deployed on the same chain as the "Gov" contract (as the documentation suggests).

Assessed type

Governance

c4-pre-sort commented 1 year ago

0xSorryNotSorry marked the issue as primary issue

c4-sponsor commented 1 year ago

deanamiel marked the issue as sponsor disputed

deanamiel commented 1 year ago

Proposals are meant to be created only via the governance address on Axelarnet, there is no intention for proposals to be created from the source chain itself.

c4-judge commented 1 year ago

berndartmueller marked the issue as unsatisfactory: Invalid