ERC-1271 Signature Verification Remediation
Overview
Related Detector: ERC-1271 Signature Verification
ERC-1271 lets contracts (multisigs, smart accounts) validate signatures via isValidSignature(bytes32,bytes), which returns a 4-byte magic value on success. Verifiers that assume every signer is an EOA, or that ignore the magic value, either reject valid smart-account signatures or accept invalid ones. The remediation is to branch on whether the signer has code and to check the exact return value.
Recommended Fix
Before (Vulnerable)
function _check(address signer, bytes32 hash, bytes memory sig) internal view {
// Assumes an EOA — smart-contract signers can never authorize.
require(ECDSA.recover(hash, sig) == signer, "Bad sig");
}
After (Fixed — EOA and ERC-1271 paths, magic-value checked)
bytes4 constant MAGIC = 0x1626ba7e; // ERC-1271 isValidSignature selector
function _check(address signer, bytes32 hash, bytes memory sig) internal view {
if (signer.code.length == 0) {
require(ECDSA.recover(hash, sig) == signer, "Bad EOA sig");
} else {
require(IERC1271(signer).isValidSignature(hash, sig) == MAGIC, "Bad 1271 sig");
}
}
OpenZeppelin’s SignatureChecker.isValidSignatureNow implements exactly this dual path. Treat any return value other than the magic constant as failure.
Common Mistakes
- Checking only that
isValidSignaturedid not revert, instead of comparing the returned bytes4 to the magic value. - Allowing the verified contract to re-enter during
isValidSignatureand mutate state that the caller relies on. - Assuming a signature that validated once is single-use; enforce nonces/deadlines separately.