Open hats-bug-reporter[bot] opened 4 months ago
I've tested with foundry test, the mentioned issue does not exist.
EXTCODESIZE.t.sol
:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
import {Test, console2} from "forge-std/Test.sol";
contract Testing {
}
contract EXTCODESIZETest is Test {
address public user1;
address public user2;
Testing public testing_contract;
function _hasNoCode(address account) public view returns (bool result) {
// solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
result := iszero(extcodesize(account))
}
}
function setUp() public {
user1 = makeAddr("USER1");
user2 = makeAddr("USER2");
deal(user2, 1); //fund user2 with 1 wei.
testing_contract = new Testing();
}
function test_AccountHasNoCode() public {
console2.log(_hasNoCode(user1)); //true
console2.log("ETH balance of user 2: ", user2.balance);
console2.log(_hasNoCode(user2));
console2.log(_hasNoCode(address(testing_contract)));
}
}
Result:
Running 1 test for test/EXTCODESIZE.t.sol:EXTCODESIZETest
[PASS] test_AccountHasNoCode() (gas: 18585)
Logs:
true
ETH balance of user 2: 1
true
false
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.82ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
Noticed that the function _hasNoCode
returned true
for user2
with balance of 1 wei
, therefore the DoS situation is not valid.
extcodesize
is for getting the code length of an external account, and thus equivalent to account.code.length
.
I will mark this as invalid.
Github username: @shealtielanz Twitter username: shealtielanz Submission hash (on-chain): 0x206c952bef7f13b55cfc44a6bf5945ffd021bfaa60a8030113e1516614386332 Severity: high
Description: Description
On the call to
createSigner()
the function uses the opcodeextecodesize()
to check if the contract has been created, however, an attacker can trick the factory into thinking that the signer has already been created when actually it hasn't been created, thereby making the calls tocreateSigner()
useless as the signer cannot be created anymore.https://github.com/safe-global/safe-modules/blob/9a18245f546bf2a8ed9bdc2b04aae44f949ec7a0/modules/passkey/contracts/SafeWebAuthnSignerFactory.sol#L51C1-L59C6
https://github.com/safe-global/safe-modules/blob/9a18245f546bf2a8ed9bdc2b04aae44f949ec7a0/modules/passkey/contracts/SafeWebAuthnSignerFactory.sol#L94C1-L99C6
this
iszero(extcodesize(account))
check is insufficient to determine if an address has an existing code. According to EIP-1052, addresses without code only return a 0x0codehash
when they are empty:As seen from above, addresses without code can also return
keccak256("")
as itscodehash
if it is non-empty. EIP-161 states that an address must have a zero ETH balance for it to be empty:As such, if anyone transfers 1 wei to an address, .codehash will return keccak256("") instead of bytes32(0), making the checks shown above skip incorrectly.
Attack Scenario
createSigner()
with the given parameters to create the signer contract._hasNoCode()
the contract will assume that the address already has a code and skip creation.Mitigation
Fix for this is easy - just change from
result := iszero(extcodesize(account))
tox.code.length != 0
(ie. Check the code length of the address instead.