skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md
- Contract uses `ecrecover` directly (not via OpenZeppelin's ECDSA library)
npx skillsauth add apegurus/solidity-argus unexpected-ecrecover-null-addressInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ecrecover directly (not via OpenZeppelin's ECDSA library)address(0)address(0))contract Vault {
address public signer; // Uninitialized — defaults to address(0)
function withdrawWithSig(uint256 amount, uint8 v, bytes32 r, bytes32 s) external {
bytes32 hash = keccak256(abi.encodePacked(msg.sender, amount));
// ecrecover returns address(0) for invalid signatures
// (e.g., v != 27 && v != 28)
address recovered = ecrecover(hash, v, r, s);
// If signer is uninitialized (address(0)) and recovered is address(0),
// this check passes — anyone can withdraw
require(recovered == signer, "invalid signature");
_withdraw(msg.sender, amount);
}
}
ecrecover( calls in the codebaseaddress(0) — flag if notaddress(0)? (uninitialized, never set, cleared by admin)ECDSA.recover is used instead — it reverts on null recovery automaticallyinitialize() — if initialize is never called, signer remains address(0)require(recovered != address(0)) check is present after ecrecoverECDSA.recover is used (handles null address internally)address(0) (validated on set)require(recovered != address(0), "invalid signature") after ecrecoverECDSA.recover which reverts on invalid signatures and null recoveryaddress(0) at any pointimport {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
function withdrawWithSig(uint256 amount, bytes memory sig) external {
bytes32 hash = keccak256(abi.encodePacked(msg.sender, amount));
bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash);
address recovered = ECDSA.recover(ethHash, sig); // Reverts if address(0)
require(recovered == signer, "invalid signature");
_withdraw(msg.sender, amount);
}
testing
Specialist profile for mechanically applying the attack-vector deck and classifying vectors as skip, drop, or investigate.
tools
Specialist profile for libraries, helpers, base contracts, adapters, encoders, wrappers, and integration glue.
testing
Specialist profile for rounding, scale, decimal, downcast, and arithmetic accounting edge cases.
testing
Specialist profile for extracting conservation laws and state couplings, then searching for violating paths.