xanoutas/solidity-security-findings huggingface dataset:
ExecutorPlugin missing payable when execute the transaction
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L68
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L90


# Vulnerability details

## Impact
Detailed description of the impact of this finding.

## Proof of Concept

[executeTransaction](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L68) in ExecutorPlugin is meant to execute transaction

but in [_executeTxnAsModule](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L90)

```solidity
function _executeTxnAsModule(address _account, Types.Executable memory _executable)
        internal
        returns (bytes memory)
    {
        (bool success, bytes memory txnResult) = IGnosisSafe(_account).execTransactionFromModuleReturnData(
            _executable.target,
            _executable.value,
            _executable.data,
            SafeHelper._parseOperationEnum(_executable.callType)
        );
        if (!success) revert ModuleExecutionFailed();
        return txnResult;
    }
```

the code does not forward ETH when execute the transaction,

executeTransaction does not have payable keywords as well, meaning the plugin is not capable of attaching ETH when execute the transaction

## Tools Used

Manual Review

## Recommended Mitigation Steps

add payable keywords in function executeTransaction and forward the ETH when execute the transaction

```solidity
(bool success, bytes memory txnResult) = IGnosisSafe(_account){value: msg.value}.execTransactionFromModuleReturnData(
            _executable.target,
            _executable.value,
            _executable.data,
```


## Assessed type

ETH-Transfer
Registered wallet and sub account cannot be removed
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/WalletRegistry.sol#L35
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/WalletRegistry.sol#L49
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/PolicyRegistry.sol#L52


# Vulnerability details

## Impact

Registered wallet and sub account cannot be removed

## Proof of Concept

In WalletRegistry,

the wallet can be [registered](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/WalletRegistry.sol#L35) by calling registerWallet

the sub account can be [registered](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/WalletRegistry.sol#L49) as well by calling registerSubAccount

However, once registered, the wallet or sub account can never be removed

a registered wallet or sub account can always can senstive function such as [updatePolicy](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/PolicyRegistry.sol#L52) from PolicyRegistry.sol

even later the owner find that the registered wallet or sub account is hacked or misbehave and owner want to remove the account, he / she cannot do so

## Tools Used

Manual Review

## Recommended Mitigation Steps

add the function to remove registered wallet / sub account


## Assessed type

Access Control
SafeDeployer : calling the function `_genNonce` would overflow.
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L228
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L240
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L253


# Vulnerability details

## Impact

Genosis safe account can not be created due to overflow of [_genNonce](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L253)

## Proof of Concept

The contract `SafeDeployer` deploy the Genosys safe account. To this, there are set of function which accomplish this task.

First the function `deployConsoleAccount` will be called with relevant input parameters. This calls the `_createSafe` function to create the safe account.

when we look at the `_createSafe` function, it has the logic to calculate and deploy the Genosys safe account.

nonce value is generate  based on owners and user provided salt.

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L219-L245

```solidity
    function _createSafe(address[] calldata _owners, bytes memory _initializer, bytes32 _salt)
        private
        returns (address _safe)
    {
        address gnosisProxyFactory = AddressProviderService._getAuthorizedAddress(_GNOSIS_PROXY_FACTORY_HASH);
        address gnosisSafeSingleton = AddressProviderService._getAuthorizedAddress(_GNOSIS_SINGLETON_HASH);
        bytes32 ownersHash = keccak256(abi.encode(_owners));


        // Generate nonce based on owners and user provided salt
        uint256 nonce = _genNonce(ownersHash, _salt); -------------------->> find here
        do {
            try IGnosisProxyFactory(gnosisProxyFactory).createProxyWithNonce(gnosisSafeSingleton, _initializer, nonce)
            returns (address _deployedSafe) {
                _safe = _deployedSafe;
            } catch Error(string memory reason) {
                // KEK
                if (keccak256(bytes(reason)) != _SAFE_CREATION_FAILURE_REASON) {
                    // A safe is already deployed with the same salt, retry with bumped nonce
                    revert SafeProxyCreationFailed();
                }
                emit SafeProxyCreationFailure(gnosisSafeSingleton, nonce, _initializer);
                nonce = _genNonce(ownersHash, _salt); -------------------------------------->> find here
            } catch {
                revert SafeProxyCreationFailed();
            }
        } while (_safe == address(0));
    }
```

as mentioned in above function, the nonce value is calculated by calling the function [_genNonce](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L253). when we look at the function 

h
A malicious actor can Block stuff the chain until the validator signature expires. 
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/PolicyValidator.sol#L100-L142


# Vulnerability details

## Impact
The signature of a validator is time bound of which after the expiration period the transaction becomes invalid, a malicious user might notice a time bound transaction made by the sub account and decide to block stuff the network until the validator signature becomes invalid, which in turn invalids the entire transaction. 

This is a serious problem because stuffing a whole block with dummy transactions is very cheap on Binance Smart Chain. According to https://www.cryptoneur.xyz/en/gas-fees-calculator, 15M gas - whole block - costs $14~$15 on BSC. Because BSC is a centralized blockchain, there are no private mempools and bribes directly to the miners (like in FlashBots); hence, other users are very limited concerning the prohibitive actions.

## Proof of Concept
        // Ensure transaction has not expired
        if (expiryEpoch < uint32(block.timestamp)) {
            revert TxnExpired(expiryEpoch);
        }
Validator signatures are time bound, so malicious user can terminate transactions at will on affected chain. 

## Tools Used
Manual 

## Recommended Mitigation Steps
Make the validation expiration window wide enough (yet safe) that it makes block stuffing a transaction unprofitable. 


## Assessed type

Timing
There is still a risk that operators or executors can backdoor the subaccount.
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/TransactionValidator.sol#L181


# Vulnerability details

## Impact
The `_checkSubAccountSecurityConfig` function ensures that the guard and fallback handler have not been disabled or updated, and that the owner console as a module has not been disabled by any operators or executors. This helper function is used as a last resort if the trusted validator mistakenly signs malicious transactions, given that there is only one trusted validator in the system. However, it does not check if operators or executors has enabled new modules to the subaccount, which can execute any transactions without any validations. As a result, any new module introduced is free to execute whatever it wishes on the subaccount. It constitutes a serious backdoor threat. Hence, it is important to add the following invariant to the system:

Subacount should not allow operators and executors to intruduce any modules on it.

## Proof of Concept
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/TransactionValidator.sol#L181

## Tools Used
None

## Recommended Mitigation Steps
Check that no new modules have been introduced to the subaccount, using the getModulesPaginated() utility.



## Assessed type

Access Control
Account should be able to add max time it would want its transaction to be executed. 
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L68-L77


# Vulnerability details

## Impact
Account is not allowed to specify the expiration time for its request execution, since most request run arbitrary calls, which might be time bound.  

## Proof of Concept
Alot of transaction or calls on the blockchain are time bound, lets say for example Alice wants to allow the sub account to participate in a time bound auction, with the current round expiring in the next ten minutes before another round starts which would be more expensive than the previous, Alice signs a request execution and the request remains in the mempool (for those chains with a public mempool), for more time than the current round, and when miners finally execute the transaction it falls into another round, which might cost Alice more that bargained. 

## Tools Used
Manual 

## Recommended Mitigation Steps
There should be an option to specify request execution expiration. 


## Assessed type

Timing
FallbackHandler remains unset in _setupConsoleAccount()
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L118-L130


# Vulnerability details

## Impact
According to the docs, the fallback handler provides compatibility between pre-1.3.0 and 1.3.0+ Safe contracts, and additionally, also ensures policy validation guarantees required for ConsoleAccounts/SubAccounts that have policy validation enabled. If not set, this functionality will not be available. 

## Proof of Concept
In ConsoleOpBuilder.enablePolicyOnConsole(), it was explicitly stated what needs to be done if policy is enabled:
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ConsoleOpBuilder.sol#L25C5-L25C124
``` 
* @dev Enables policy, by updating policy on `PolicyRegistry`, setting guard on Safe, setting fallback handler on Safe
```
This was implemented as stated in ConsoleOpBuilder.enablePolicyOnConsole(), a function that returns the multicall bytecode for enabling policy on brahma console account. https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ConsoleOpBuilder.sol#L53-L56
```
txns[2] = Types.Executable({
            callType: Types.CallType.CALL,
            target: account,
            value: 0,
            data: abi.encodeCall(
                IGnosisSafe.setFallbackHandler,
                (AddressProviderService._getAuthorizedAddress(_CONSOLE_FALLBACK_HANDLER_HASH))
                )
        });
```

However, in SafeDeployer._setupConsoleAccount(), if policy is enabled, fallback handler address is obtained but not set in safe., only guard was set there. https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L118-L130
```
if (_policyHashValid) {
            txns = new Types.Executable[](2);
            fallbackHandler = AddressProviderService._getAuthorizedAddress(_CONSOLE_FALLBACK_HANDLER_HASH);

            // Enable guard on console account
            txns[1] = Types.Executable({
                callType: Types.CallType.DELEGATECALL,
                target: AddressProviderService._getAuthorizedAddress(_SAFE_ENABLER_HASH),
                value: 0,
                data: abi.encodeCall(
                    IGnosisSafe.setGuard, (AddressProviderService._getAuthorizedAddress(_SAFE_MODERATOR_OVERRIDABLE_HASH))
                    )
            });
```

## Tools Used
Manual review.

## Recommended Mitigation Steps
Plsease kindly Include setting the fallBack on safe in the multicall transaction when policy is being set, thank you.
```
  if (_policyHashValid) {
            txns = new Types.Executable[](3);
            fallbackHandler = AddressProviderService._getAuthorizedAddress(_CONSOLE_FALLBACK_HANDLER_HASH);

            // Enable guard on console account
            txns[1] = Types.Executable({
                callType: Types.CallType.DELEGATECALL,
Contract data cannot be migrated to the new address during contract upgrading.
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/ExecutorPlugin.sol#L58
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L45


# Vulnerability details

## Impact
According to [this document](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/docs/Core.md#address-provider), the AddressProvider contract manages and updates addresses of authorized contracts and registries within the system.  If security vulnerabilities are discovered or functional upgrades are needed in a contract, the government can deploy a new version of the contract and then use the `setAuthorizedAddress` function to update the contract's address.
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/AddressProvider.sol#L77-L90
```
    function setAuthorizedAddress(bytes32 _key, address _authorizedAddress, bool _overrideCheck) external {
        _onlyGov();
        _notNull(_authorizedAddress);

        /// @dev skips checks for supported `addressProvider()` if `_overrideCheck` is true
        if (!_overrideCheck) {
            /// @dev skips checks for supported `addressProvider()` if `_authorizedAddress` is an EOA
            if (_authorizedAddress.code.length != 0) _ensureAddressProvider(_authorizedAddress);
        }

        authorizedAddresses[_key] = _authorizedAddress;

        emit AuthorizedAddressInitialised(_authorizedAddress, _key);
    }
```
It should be noted that, in addition to deploying a new version of the contract, data from the old contract needs to be migrated to the new contract; otherwise, the new contract won't function properly. Brahma does not provide a method for data migration.

The method I can think of is to use `eth_getLogs` to query the contract's log information, retrieve the contract data from the logs, and then migrate it to the new version of the contract. Here is an example:

The data to be migrated is the `commitments`. The PolicyRegistry contract defines an event: `event UpdatedPolicyCommit(address indexed account, bytes32 policyCommit, bytes32 oldPolicyCommit);`. When a policy commit is added, this event is emitted. By using `eth_getLogs`, you can query all policy commits and then migrate the data to the new version of the contract.
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/PolicyRegistry.sol#L66-L69
```
    event UpdatedPolicyCommit(address indexed account, bytes32 policyCommit, bytes32 oldPolicyCommit);

    /// @notice account addresses mapped to their policy commits
    mapping(address account => bytes32 policyCommit) public commitments;

    function _updatePolicy(address account, bytes32 policyCommit) internal {
>>>        emit UpdatedPolicyCommit(account, policyCommit, commitments[account]);
        commitments[account] = policyComm
The `_validateExecutionRequest()` function does not include a check for expiration signatures.
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/ExecutorPlugin.sol#L106


# Vulnerability details

## Impact
To maintain validity, user signatures must have an expiration or timestamp deadline. Otherwise, the signature grants the message a "lifetime license."

The `_validateExecutionRequest()` function needs to include a check for expiration signatures. Otherwise, executors can execute signed transactions even in unfavorable market conditions.

## Proof of Concept
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/ExecutorPlugin.sol#L106

## Tools Used
None

## Recommended Mitigation Steps
Signature implementations should always include an expiration timestamp.


## Assessed type

Access Control
Lack of Input Validation on threshold and _owners
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L82
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L56


# Vulnerability details

## Impact
Unvalidated inputs can lead to unexpected contract behaviors, including but not limited to, incorrect configurations, locked funds, or erroneous operations. In extreme cases, it could also lead to security vulnerabilities if malicious actors can exploit these oversights to their advantage.

## Proof of Concept
In the deployConsoleAccount and deploySubAccount function, the threshold and _owners parameters are used without validation checks. The threshold is critical as it sets the number of owner approvals required for executing transactions. A zero or very high threshold could lock funds or make the safe unusable. Similarly, an empty _owners array or duplicate owner addresses could also lead to undesired behaviors.

```
function deployConsoleAccount(address[] calldata _owners, uint256 _threshold, bytes32 _policyCommit, bytes32 _salt)
    external
    nonReentrant
    returns (address _safe)
{
    //...
    _safe = _createSafe(_owners, _setupConsoleAccount(_owners, _threshold, _policyHashValid), _salt);
    //...
} 
```



Hypothetical steps to cause the issue:

-A user calls the deployConsoleAccount function with a threshold of 0 and a valid _owners array.
The contract deploys a new Gnosis Safe with a threshold of 0, meaning no approvals are required to execute transactions, which could lead to a lack of control and potential fund loss.

Or,

-A user calls the deployConsoleAccount function with an empty _owners array.
The contract attempts to deploy a new Gnosis Safe with no owners, which could lead to a locked contract with no one able to execute transactions.

## Tools Used
Manual

## Recommended Mitigation Steps
Implementing input validation checks can mitigate the risks associated with incorrect or malicious inputs. Here are some steps:

Validate Threshold:

Ensure that the threshold is greater than 0 and less than or equal to the number of owners.
```
require(_threshold > 0 && _threshold <= _owners.length, "Invalid threshold value");
Validate Owners Array:
```
Ensure that the _owners array is not empty and does not contain duplicate addresses.
```
require(_owners.length > 0, "Owners array is empty");
for (uint i = 0; i < _owners.length; i++) {
    for (uint j = i + 1; j < _owners.length; j++) {
        require(_owners[i] != _owners[j], "Duplicate owner address");
    }
}
```
By adding these validation checks at the beginning of the deployConsoleAccount and deploySubAccount function, you can prevent incorrect or malicious inputs from causing undesired behaviors or vulnerabilities within the contract.


## Assessed type

Invalid Validation
registerWallet() does not validate the sender
Audit: 2023-10-brahma-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/registries/WalletRegistry.sol#L35


# Vulnerability details

## Issue
registerWallet() in WalletRegistry.sol does not guarantee that the sender is the safe deployer. registerWallet() should be called from the safe deployer, in the context of [deployConsoleAccount()](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L144)
        `// Register Wallet
        /// @dev This function is being packed as a part of multisend transaction as, safe internally performs
        // a delegatecall during initializer to the target contract, so direct call doesnt work. Multisend is
        // supposed to be delegatecall
        txns[0] = Types.Executable({
            callType: Types.CallType.CALL,
            target: AddressProviderService._getRegistry(_WALLET_REGISTRY_HASH),
            value: 0,
            data: abi.encodePacked(WalletRegistry.registerWallet.selector)
        });`

## Impact 
SafeDeployer will call enableModule/setGuard for an arbitrary sender, which hasn't been deployed as a Console Account. This may lead to confusion of privileged access roles.
[in SafeDeployer](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L181) 
        `// Enable Brhma Console account as module on sub Account
        txns[0] = Types.Executable({
            callType: Types.CallType.DELEGATECALL,
            target: safeEnabler,
            value: 0,
            data: abi.encodeCall(IGnosisSafe.enableModule, (_consoleAccount))
        });`
## Fix
    `/**
     * @notice Registers a wallet
     * @dev Can only be called by safe deployer or the wallet itself
     */
    function registerWallet() external {
        if (msg.sender != AddressProviderService._getAuthorizedAddress(_SAFE_DEPLOYER_HASH)) revert InvalidSender();
        if (isWallet[msg.sender]) revert AlreadyRegistered();
        if (subAccountToWallet[msg.sender] != address(0)) revert IsSubAccount();
        isWallet[msg.sender] = true;
        emit RegisterWallet(msg.sender);
    }`


## Assessed type

Access Control