SCWE-106: Unauthenticated Meta-Transactions
Stable Version v1.0
This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Relationships¶
- CWE-347: Improper Verification of Cryptographic Signature
https://cwe.mitre.org/data/definitions/347.html
Description¶
Meta-transaction forwarders that relay calls without verifying the signer, nonce, chain, or expiry let relayers execute arbitrary actions on behalf of victims. Missing replay protection allows the same signed request to be executed multiple times.
Remediation¶
- Verify EIP-712 typed data signatures against the declared signer.
- Track and increment per-signer nonces; enforce deadlines and chainId.
- Restrict trusted forwarders and sanitize
msg.sender/msg.dataassumptions in downstream calls.
Examples¶
Vulnerable¶
pragma solidity ^0.8.0;
contract Forwarder {
function relay(address target, bytes calldata data) external {
(bool ok, ) = target.call(data); // no signature or nonce check
require(ok, "call failed");
}
}
Fixed¶
pragma solidity ^0.8.0;
contract Forwarder {
mapping(address => uint256) public nonces;
function relay(address target, bytes calldata data, uint256 nonce, uint256 deadline, bytes calldata sig) external {
require(block.timestamp <= deadline, "expired");
bytes32 digest = keccak256(abi.encode(target, data, nonce, block.chainid, deadline));
address signer = ECDSA.recover(digest, sig);
require(nonce == nonces[signer]++, "bad nonce");
(bool ok, ) = target.call(data);
require(ok, "call failed");
}
}