Last updated: September 15, 2025
    
    
    
    
                  
  
  SCWE-055: Missing Protection against Signature Replay Attacks
Stable Version v0.0.1
This content is in the version-(v0.0.1) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
 Send Feedback
 
Relationships
Description
Signature replay attacks occur when a valid signature from a previous transaction is reused in a different context, such as a different transaction or contract call. Without proper protection, an attacker can capture and replay a signature, potentially bypassing authentication checks and causing unauthorized actions or transactions.
To prevent signature replay attacks, include additional checks that ensure the signature is valid for a specific transaction or context. This can be done by incorporating unique identifiers like a nonce, timestamp, or a unique transaction hash into the signature to bind it to a specific use. Always verify that the signature is only valid for the intended action.
Vulnerable Contract Example
contract ReplayAttackExample {
    mapping(address => uint256) public nonces;
    function authenticate(bytes32 message, uint8 v, bytes32 r, bytes32 s) public {
        address signer = ecrecover(message, v, r, s);
        require(signer == msg.sender, "Invalid signature");
        // No protection against replay attacks; attacker can reuse the same signature
    }
}
 
Fixed Contract Example
  pragma solidity ^0.8.0;
  import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
  contract SecureReplayProtectionExample {
      using ECDSA for bytes32;
      mapping(address => uint256) public nonces;
      function authenticate(bytes32 message, bytes memory signature) public {
          uint256 nonce = nonces[msg.sender]++;
          bytes32 messageWithContext = keccak256(abi.encodePacked(message, nonce, block.chainid));  
          address signer = messageWithContext.toEthSignedMessageHash().recover(signature);
          require(signer == msg.sender, "Invalid signature");
      }
  }
 
Fixes Implemented:
-  Binds signature to a nonce (ensuring it's only usable once).
-  Includes chainId (prevents cross-chain replay attacks).
- Uses OpenZeppelin’s ECDSA library (avoids signature malleability risks).