Skip to content

feat(lint): add arbitrary-send-eth lint#14943

Open
stevencartavia wants to merge 5 commits into
masterfrom
steven/arbitrary-send-eth-lint
Open

feat(lint): add arbitrary-send-eth lint#14943
stevencartavia wants to merge 5 commits into
masterfrom
steven/arbitrary-send-eth-lint

Conversation

@stevencartavia
Copy link
Copy Markdown
Collaborator

Flags functions that send ETH to a caller-controlled destination without restricting who can call them.

Copy link
Copy Markdown
Collaborator

@mablr mablr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some clanker findings, I've been able to repro locally.

FN-1 — Numeric address literals accepted as safe destinations

Source: arbitrary_send_eth.rs#L246

The destination safety check matches LitKind::Address(_) | LitKind::Number(_). Any address(N) expression resolves to a LitKind::Number node and is silently accepted as safe — the lint never warns. Only address(0) and checksummed address literals are genuinely safe destinations; arbitrary numeric casts are not.

payable(address(1)).transfer(amt); // no warning emitted — should warn

FP-1 — Trailing return; disqualifies a valid caller-restriction helper

Source: arbitrary_send_eth.rs#L827

function_no_arg_returns rejects any helper body that contains a return statement, including a no-op trailing return;. A helper like if (msg.sender != owner) revert(); return; is semantically identical to the same function without the final statement, but the modifier is not recognised as caller-restricting and the transfer is falsely flagged.

function _checkOwner() internal view {
    if (msg.sender != owner) revert();
    return; // ← causes the whole helper to be ignored
}
modifier onlyOwner() { _checkOwner(); _; }
function withdraw(address payable to, uint256 amt) external onlyOwner {
    to.transfer(amt); // falsely flagged
}

FP-2 — Named return variable not recognised as a msg.sender-returning helper

Source: arbitrary_send_eth.rs#L800

function_no_arg_returns only matches StmtKind::Return(Some(e)) as the sole statement. A helper that assigns the named return variable instead of using an explicit return expression produces a different HIR shape and is not recognised, so the modifier is ignored and the transfer is falsely flagged.

function _msgSender() internal view returns (address r) { r = msg.sender; }
modifier onlyOwner() { require(_msgSender() == owner); _; }
function withdraw(address payable to, uint256 amt) external onlyOwner {
    to.transfer(amt); // falsely flagged
}

Comment thread crates/lint/src/sol/high/arbitrary_send_eth.rs
Comment thread crates/lint/src/sol/high/arbitrary_send_eth.rs Outdated
Comment thread crates/lint/src/sol/high/arbitrary_send_eth.rs
Comment thread crates/lint/src/sol/high/arbitrary_send_eth.rs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants