xanoutas/solidity-security-findings huggingface dataset:
SafeDeployer.sol : Missing the correct type caste for _WALLET_REGISTRY_HASH when setup the console account could lead issue in accessing the functions from  `WalletRegistry`
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
Incorrect address type caste would lead to setting the console account which can not access the function from `WalletRegistry.sol`.

## Proof of Concept

The SafeDeployer contract facilitates the deployment of Gnosis Safe accounts and configuring them as console accounts (i.e, registers them on WalletRegistry etc.). It allows creating console accounts with optional policy commitments and registering them, as well as sub-accounts with policy commitments, and also registers them.

`deployConsoleAccount` calls the `_setupConsoleAccount` function where the appropriate input arguments are set for console account and bytes data is prepared using the _WALLET_REGISTRY_HASH and _GNOSIS_MULTI_SEND_HASH addresses.

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

Later this bytes data is used as initializer parameter for `_createSafe` function which calls the genosis proxy to create the genosis safe account.

The issue is, when preparing the initializer input for  `_createSafe`, the function `_setupConsoleAccount` does not type case the `_WALLET_REGISTRY_HASH` correctly.

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

```solidity
        txns[0] = Types.Executable({
            callType: Types.CallType.CALL,
            target: AddressProviderService._getRegistry(_WALLET_REGISTRY_HASH), ------->> audit find
            value: 0,
            data: abi.encodePacked(WalletRegistry.registerWallet.selector)
        });
```

other places it is handled properly. refer below line
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L91

## Tools Used

Manual review

## Recommended Mitigation Steps

Update the codes in [Line](https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L142C51-L142C51)

```solidity
            txns[0] = Types.Executable({
            callType: Types.CallType.CALL,
            target: WalletRegistry(AddressProviderService._getRegistry(_WALLET_REGISTRY_HASH)), --->> updated
            value: 0,
            data: abi.encodePacked(WalletRegistry.registerWallet.selector)
```


## Assessed type

Context
Enabled modules after been activated cannot subsequently be disabled
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
Modules are third party accounts and they have some level of access to the GnosisSafe depending on configuration by the account owner. Therefore, they are created and assigned by account owners and they can execute transactions independently but they cannot always be trusted and in such case whereby a module is being controlled by a malicious third party, there should be a logic implemented to disable them, which is present in the original Safe bytecode but it isn't implemented in SafeEnabler.sol. 
## Proof of Concept
Contract is acclaimed to be in very similar comparisons with the original safe 1.3.0 
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeEnabler.sol#L10-L16 
but it doesn't ensure similar security guidelines to halt loss of user funds or operations of malicious transactions. However this was implemented in the original safe 1.3.O, by disabling a module peradventure it's been controlled by a malicious actor.
https://github.com/safe-global/safe-contracts/blob/186a21a74b327f17fc41217a927dea7064f74604/contracts/base/ModuleManager.sol#L32C5-L53

## Tools Used
 Manual review, Vscode
## Recommended Mitigation Steps
Logic to remove a module from the whitelist should be implemented in the SafeEnabler.sol. To halt fraudulent activities by malicious third party

```solidity
function disableModule(address prevModule, address module) public authorized {
    // Validate module address and check that it corresponds to module index.
    require(module != address(0) && module != SENTINEL_MODULES, "GS101");
    require(modules[prevModule] == module, "GS103");
    modules[prevModule] = modules[module];
    modules[module] = address(0);
    emit DisabledModule(module);
}




## Assessed type

Access Control
Executor can effectively bypass _checkSubAccountSecurityConfig by adding a new Module
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
An Executor is an account authorized to perform module execution on a subAccount through the ExecutorPlugin. Gnosis Safe Modules manage to bypass the entire guard logic (Safe 1.5 has that new guard hook, but there's also no hook logic done in Brahma). For this reason, `TransactionValidator.validatePostExecutorTransaction` is present as a similar post-execution guard mechanism. As the comment states:

```
* @notice Provides on-chain guarantees on security critical expected states of subAccount for executor plugin
```

A more explicit comment can be found in `_checkSubAccountSecurityConfig`:

```
* @dev Ensures that guard has not been disabled/updated and the owner console as a module has not been disabled
```

Though this assures us that the executed transaction did not remove the guard nor disabled the `ownerConsole` as a module, it does let pass the potential enabling of a new module, since Gnosis Safe contracts allow multiple modules to be enabled (contrary to guards). For this reason, the Executor role can actually remove the guard and the `ownerConsole` as a module by doing the following:

1. craft a transaction where a malicious module gets enabled.
2. execute that transaction through the ExecutorPlugin.
3. on a following transaction or call, use the new module to remove the guard, disable the `ownerConsole` module, or any other action really (for example, change signers).

## Proof of Concept
Here's a potential malicious module:

```
contract MaliciousModule {
    address owner;

    constructor() {
       owner = msg.sender;
    }

    function executeTxnAsModule(address _account, Types.Executable calldata _executable)
        external
    {
        require(owner == msg.sender);
        (bool success, bytes memory txnResult) = IGnosisSafe(_account).execTransactionFromModuleReturnData(
            _executable.target,
            _executable.value,
            _executable.data,
            SafeHelper._parseOperationEnum(_executable.callType)
        );
    }
}
```

The MaliciousModule contract is really just a gateway to the execution inside of the Gnosis Safe. Next we need to craft that enabling module transaction:

```
Types.Executable memory tx = Types.Executable({
    callType: Types.CallType.CALL,
    target: _account,
    value: 0,
    data: abi.encodeCall(IGnosisSafe.enableModule, (address(maliciousModule)))
});
ExecutionRequest memory request = ExecutionRequest({
    exec: tx,
    account: _account,
    executor: _executor,
    executorSignature: execSig,
    validatorSignature: valSig
});
executorPlugin.executeTransaction(request);
```

Here, `_account` is the subAccount where the Executor (through ExecutorPlugin) is allowed to send a transaction. Once the module gets enabled, all the attacker needs to do is call `MaliciousModule.executeTxnAsModule` with data as the disabl
Unauthorized account can update policy of any account without a policy
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/PolicyRegistry.sol#L47-L47
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/Constants.sol#L56-L60


# Vulnerability details

## Impact
Unauthorized account can update policy of any account without a policy

## Proof of Concept
`
 if (
            currentCommit == bytes32(0)
                && msg.sender == AddressProviderService._getAuthorizedAddress(_SAFE_DEPLOYER_HASH)
        ) 
`
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/registries/PolicyRegistry.sol#L47-L47

The argument passed into _getAuthorizedAddress - _SAFE_DEPLOYER_HASH - is a pre-defined constant:

`
    /// @notice keccak256("SafeDeployer")
    bytes32 internal constant _SAFE_DEPLOYER_HASH = 0x6a361f18b7bdd4971167a9db369c1357f3ebc95ef7fca81cd1aebfaeb988666d;

`
An account without a policy can be updated as a result once the msg.sender matches the constant hash address.
   

## Tools Used
Manual review

## Recommended Mitigation Steps
The account of a safe deployer should be used instead. And the code can be simplified.


## Assessed type

Access Control
Malicious sub-account operators can perform cross-chain signature replay attack 
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeModerator.sol#L47-L60
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/TransactionValidator.sol#L95-L97
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/TransactionValidator.sol#L210-L224
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/PolicyValidator.sol#L54-L80
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/PolicyValidator.sol#L100-L141


# Vulnerability details

## Impact
Malicious sub-account operators can perform policy or transactions not allowed to the specific chain but allowed in other chain. This is possible due to cross-chain signature replay attack.

## Proof of Concept
To describe the attack, for example, let us have two chains , chain A and chain B. 
In chain A, there is a policy commitment (transactions) in the registry that is not allowed or not found in the registry of chain B. This policy registry is supposed to restrict the sub-account operations, that's why it has been created. 
However, malicious operators can maneuver this restriction by selecting transactions in chain A that are favorable to them in chain B. These restricted transactions may involve trading risky assets, that's why it is dangerous. They can just copy the parameters used in chain A and apply it to chain B. Since the operators are the same in both chains, msg.sender is also the same which is a great advantage on how to properly execute this. Please see the checktransaction parameters needed below.

  function checkTransaction(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation,
        uint256 safeTxGas,
        uint256 baseGas,
        uint256 gasPrice,
        address gasToken,
        address payable refundReceiver,
        bytes memory signatures,
        address msgSender
    ) external view override {
        TransactionValidator(AddressProviderService._getAuthorizedAddress(_TRANSACTION_VALIDATOR_HASH))
            .validatePreTransaction(
            TransactionValidator.SafeTransactionParams({
                from: msg.sender,
                to: to,
                value: value,
                data: data,
                operation: operation,
                safeTxGas: safeTxGas,
                baseGas: baseGas,
                gasPrice: gasPrice,
                gasToken: gasToken,
                refundReceiver: refundReceiver,
                signatures: signatures,
                msgSender: msgSender
            })
        );
    }

Another important thing for this exploit to become possible is because of constant trusted validator. Here's the definition of trusted validator:

An externally owned validator account that validates transactions to be executed on sub accounts and console accounts. It signs a validator signature that is verified in PolicyValidator before execution.

As per checking, thi
Cross-Chain Signature Replay Attack
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact

1. User operations can be replayed on smart accounts accross different chains. This can lead to user's loosing funds or any unexpected behaviour that transaction replay attacks usually lead to.
2. Mistakes made on one chain can be re-applied to a new chain. For example, if a user does `deployConsoleAccount` or `deploySubAccount` using the wrong network, an attacker can replay the action on the correct chain, and steal the funds a-la the wintermute gnosis safe attack, where the attacker can create the same address that the user tried to, and steal the funds from there

## Explanation

The `SafeDeployer.sol` contract is designed to create and manage Gnosis Safe accounts within the Brahma.fi platform. It provides two key functions:

1. **[`deploySubAccount()`](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L56-L71) Function:**

   - Deploys a Sub Account within Brahma.fi.
   - Requires owners, a threshold, and a policy commitment.
   - Checks sender's wallet registration.
   - Registers the Sub Account and sets its policy.

   ```jsx
    function deploySubAccount(address[] calldata _owners, uint256 _threshold, bytes32 _policyCommit, bytes32 _salt)
        external
        nonReentrant
        returns (address _subAcc)
    {
        // Policy commit is required for Sub Account
        if (_policyCommit == bytes32(0)) revert InvalidCommitment();

        // Check if msg.sender is a registered wallet
        WalletRegistry _walletRegistry = WalletRegistry(AddressProviderService._getRegistry(_WALLET_REGISTRY_HASH));
        if (!_walletRegistry.isWallet(msg.sender)) revert NotWallet();

        // Deploy Sub Account
        _subAcc = _createSafe(_owners, _setupSubAccount(_owners, _threshold, msg.sender), _salt);

        // Register Sub Account to wallet
        _walletRegistry.registerSubAccount(msg.sender, _subAcc);

        // Update policy commit for Sub Account
        PolicyRegistry(AddressProviderService._getRegistry(_POLICY_REGISTRY_HASH)).updatePolicy(_subAcc, _policyCommit);
        emit SubAccountDeployed(_subAcc, msg.sender);
    }
   ```

2. **[`deployConsoleAccount()`](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L82-L103) Function:**

   - Deploys a console account within Brahma.fi.
   - Requires owners, a threshold, and an optional policy commitment.
   - Sets the policy if provided.

   ```jsx
       function deployConsoleAccount(address[] calldata _owners, uint256 _threshold, bytes32 _policyCommit, bytes32 _salt)
        external
        nonReentrant
        returns (address _safe)
    {
        bool _policyHashValid = _policyCommit != bytes32(0);

        _safe = _createSafe(_owners, _setupConsole
`ExecutorPlugin.executeTransaction()` is prone to cross-chain replay attacks.
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

The function `executeTransaction()` is used by executors to validate and execute transactions via a module transaction. the function takes in the input `ExecutionRequest` and does no validation of the `msg.sender`. therefore this creates an opening in which a malicious can take the input provided and perform a replay attack on another chain as the protocol will be deployed on several chains.
```solidity
function executeTransaction(ExecutionRequest calldata execRequest) external nonReentrant returns (bytes memory) {
        _validateExecutionRequest(execRequest);

        bytes memory txnResult = _executeTxnAsModule(execRequest.account, execRequest.exec);

        TransactionValidator(AddressProviderService._getAuthorizedAddress(_TRANSACTION_VALIDATOR_HASH))
            .validatePostExecutorTransaction(msg.sender, execRequest.account);

        return txnResult;
    }

```
The function lacks the `chain id` of the origin chain, therefore any other chain in which the `executor` (that is the main signer) is registered is prone to attack.
## Impact
Cross-chain Replay attacks can be performed by any malicious actor, thereby performing unwanted and unauthorised transactions on the new chain.

## Proof of Concept
* Executor performs appropriate transaction passing in the `ExecutionRequest`.
* A malicious observer copies the `ExecutionRequest` and runs the same transaction on a different chain.
* `msg.sender` and the `chainid` are not tracked so as long as the executor is also approved on that chain the transaction succeeds.
* A malicious actor can simply wait till the executor performs a suitable transaction, then perform the cross-chain replay attack.


## Tools Used
Manual Review

## Recommended Mitigation Steps
A check should be added to ensure that the `msg.sender` is the `executor` or the `chain id` should be added and checked to be valid before the transaction is run.




## Assessed type

Other
DoS issue presented in Brahma's latest audit still has potential control flow paths that can lead to same vulnerability 
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

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

## Proof of Concept
Following the "ConsoleAccount execTransaction" flow outlined via Brahma's **[Architecture diagram](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/docs/Architecture.md)**, as we can see: calling execTransaction() calls checkTransaction() function on `SafeModeratorOverridable`, and then the `SafeModeratorOverridable` guard transfers control to `TransactionValidator`, and so on and so forth through to the end of the flow that ultimately executes a transaction and does any post-transaction checks afterward. 

Via Brahma's previous **[audit](https://github.com/Brahma-fi/brahma-security/blob/master/audits/brahma-fi-consolev2-audit-10-23-ackee.pdf)**, the H1 finding (a combo of the following M1 and L1 findings) that states "if the `SafeModeratorOverridable` guard is enabled on a Safe console and the current policy is the zero policy, the console account is permanently locked and cannot send any transaction"; namely, this is a DoS scenario for the given Safe account.

Via the recommended fix for the associated M1 finding, msg.sender argument in `_isGuardBeingRemoved` function (now called `_isConsoleBeingOverriden`) is replaced with `SafeTransactionParams.from` field, as (via the audit report), "msg.sender is never the Safe account because the TransactionValidator contract is not directly called by the Safe account but through the SafeModeratorOverridable contract". 

Here, I introduce a possible execution path that does not follow Brahma's intended "ConsoleAccount execTransaction" control flow and can bypass the changes made after the recent audit, to still trigger the same DoS vulnerability. 

## Exploit:

Rather than following the flow outlined Brahma Console account via the **[Architecture diagram](https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/docs/Architecture.md)**, the account can call validatePreTransactionOverridable directly with the correct arguments for the desired transaction, given that this function is `external`. This can return relevant data on whether the policy signature is valid or not. If the user thus calls `validatePreTransactionOverridable` directly, rather than via a call to `SafeModeratorOverridable.checkTransaction`, with calldata where txParams.from == msg.sender, then this will trigger the same DoS issue on the calling Console account that was outlined in the previous audit. 

The fix introduced from this previous audit involves passing calldata that includes txParams.from == msg.sender, where msg.sender is the address of the SafeModeratorOverridable contract, NOT the Safe account's wallet's address.

This is because in the expected execution path, it is the `SafeModeratorOverridable` guard that passes control to `TransactionValidator`, and not the Safe account di
getModulesPaginated does not return the correct data
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

### Impact
In `ConsoleFallbackHandler`, you can call `getModules()`  to return the first 10 modules:
```javascript
function getModules() external view returns (address[] memory) {
        GnosisSafe safe = GnosisSafe(payable(msg.sender));
        (address[] memory array,) = safe.getModulesPaginated(SENTINEL_MODULES, 10);
        return array;
    }
```
However, there is a bug in the external call `safe.getModulesPaginated`.  In the version that Brahma is using of Safe contracts, version 1.3.0, the function `GnosisSafe.getModulesPaginated` returns the wrong `next` pointer, leading to wrong data being returned.

This has been [fixed](https://github.com/safe-global/safe-contracts/blob/main/CHANGELOG.md?plain=1#L196) in the newer versions of Safe contracts. Brahma still uses the old version 1.3.0
### Tools Used
Manual Review
## Recommended Mitigation Steps
Upgrade to a more recent version of Safe.


## Assessed type

Context
Nonce update
Audit: 2023-10-brahma-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details




return uint256(keccak256(abi.encodePacked(_ownersHash, ownerSafeCount[_ownersHash]++, _salt, VERSION)));



here ownerSafeCount[_ownersHash]++ is used as nonce for different ownerSafeCount mapping if _ownersHash is 0 or 1 the mapping will be 0 for the first item.This will cause an issue.



## Assessed type

en/de-code