There is loss of meta-transaction context in the _msgSender() implementation creating a security vulnerability that compromises the contract's ability to properly authenticate users executing transactions through meta-transactions. When transactions are executed via executeMetaTransaction(), the contract fails to correctly identify the original signer, instead defaulting to the direct msg.sender. This breaks the core functionality of gasless transactions and could lead to privilege escalation where unauthorized addresses gain access to restricted functions. In the context of this OWP Identity contract, this means functions protected by MINTER_ROLE could be accessed by addresses that don't actually possess the role, potentially allowing unauthorized minting or burning of tokens.
The issue stems from an incomplete implementation of the meta-transaction context recovery in the _msgSender() function. The current implementation only performs a basic check for whether the caller is the contract itself (msg.sender == address(this)) but fails to properly integrate with the meta-transaction execution flow. When executeMetaTransaction() is called, it appends the original signer's address to the calldata, but the current _msgSender() implementation's assembly code block doesn't correctly extract this appended address. This creates a disconnect between the meta-transaction execution layer and the sender verification layer, effectively breaking the security model of the gasless transaction system.
The meta-transaction context loss in _msgSender() represents a critical vulnerability that could lead to privilege escalation and unauthorized access to privileged functions. In a practical scenario, this vulnerability could be exploited as follows:
An attacker could:
Create a meta-transaction to call the mint() function
Sign this transaction with any address
Execute it through executeMetaTransaction()
Due to the faulty _msgSender() implementation, the contract would incorrectly validate the MINTER_ROLE
Successfully mint tokens without actually having the MINTER_ROLE permission
Consider this attack scenario:
The broken _msgSender() implementation means that when checking onlyRole(MINTER_ROLE), the Access Control system receives an incorrect sender address, effectively bypassing the role check completely. This allows unauthorized minting of tokens, which could have severe economic implications for the protocol.
https://github.com/Cyfrin/2024-11-one-world/blob/main/contracts/OWPIdentity.sol#L82
The fix explicitly overrides both parent contracts (ERC1155 and NativeMetaTransaction) and ensures proper handling of the meta-transaction context. The key changes include:
Adding the 'virtual' keyword to allow further overrides if needed
Explicitly specifying the override for both parent contracts
Using super._msgSender() instead of msg.sender in the else clause to maintain the proper inheritance chain
Returning the sender immediately after the assembly block to prevent any potential manipulation
The fix ensures proper meta-transaction context preservation and role validation. After implementing the fix, the previous attack scenario would fail as the contract would correctly identify the transaction signer and validate their MINTER_ROLE status.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.