Signature Verification
Detects improper ECDSA signature verification patterns including missing checks, incorrect hash construction, and unsafe recovery.
Signature Verification
Overview
The signature verification detector identifies contracts that use ECDSA signatures for authorization but implement the verification incorrectly. Common issues include: not checking the recovered signer against the expected address, using abi.encodePacked for hash construction (which allows hash collisions with dynamic types), and failing to include sufficient context in the signed message (missing chain ID, contract address, or nonce).
Why This Is an Issue
Signatures are a primary authorization mechanism for meta-transactions, gasless relays, permit approvals, and governance voting. If verification is flawed, an attacker can forge authorization, replay signatures across contracts or chains, or cause the wrong signer to be accepted. The consequences range from unauthorized token transfers to complete protocol takeover.
How to Resolve
// Before: Vulnerable — packed encoding, no domain separation
function execute(address to, uint256 amount, bytes memory sig) external {
bytes32 hash = keccak256(abi.encodePacked(to, amount));
address signer = ECDSA.recover(hash, sig);
require(signer == owner, "Not owner");
_transfer(to, amount);
}
// After: Fixed — EIP-712 structured data with domain separator
bytes32 constant EXECUTE_TYPEHASH = keccak256("Execute(address to,uint256 amount,uint256 nonce)");
function execute(address to, uint256 amount, uint256 nonce, bytes memory sig) external {
require(!usedNonces[nonce], "Nonce used");
usedNonces[nonce] = true;
bytes32 structHash = keccak256(abi.encode(EXECUTE_TYPEHASH, to, amount, nonce));
bytes32 digest = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(digest, sig);
require(signer == owner, "Not owner");
_transfer(to, amount);
}
Detection Methodology
- Ecrecover usage: Identifies all ecrecover precompile calls and library wrappers.
- Hash construction analysis: Checks whether
abi.encodePackedis used with dynamic types (strings, bytes, arrays), which can produce collisions. - Signer comparison: Verifies that the recovered address is compared against an expected value, not used blindly.
- Domain separation: Checks for EIP-712 domain separator usage or equivalent chain/contract binding.
Limitations
False positives: Contracts that implement custom but correct signature schemes outside EIP-712 may be flagged for missing domain separation. False negatives: Signature verification performed entirely in assembly or via precompiled contract calls with non-standard patterns may be missed.
Related Detectors
- Signature Malleability — detects s-value and v-value validation issues
- Signature Replay — detects missing nonce/deadline replay protection
- Access Control — detects missing authorization broadly