Platform: Code4rena
Start Date: 09/09/2022
Pot Size: $42,000 USDC
Total HM: 2
Participants: 101
Period: 3 days
Judge: hickuphh3
Total Solo HM: 2
Id: 161
League: ETH
Rank: 6/101
Findings: 1
Award: $81.81
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: GalloDaSballo
Also found by: 0x040, 0x1f8b, 0x4non, 0x52, 0x85102, 0xNazgul, 0xSky, 0xSmartContract, Aymen0909, Bnke0x0, CertoraInc, Chandr, Chom, CodingNameKiki, Deivitto, Diana, Funen, JC, Jeiwan, Junnon, KIntern_NA, Lambda, Mohandes, Noah3o6, Ocean_Sky, Picodes, R2, Randyyy, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Samatak, Sm4rty, SnowMan, SooYa, StevenL, Tagir2003, Tointer, TomJ, Tomo, V_B, Waze, _Adam, __141345__, a12jmx, ajtra, ak1, asutorufos, bharg4v, bobirichman, brgltd, c3phas, cccz, cryptonue, cryptostellar5, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, dipp, djxploit, durianSausage, erictee, fatherOfBlocks, gogo, got_targ, hansfriese, horsefacts, hyh, ignacio, innertia, izhuer, karanctf, ladboy233, leosathya, lucacez, lukris02, mics, oyc_109, pashov, pauliax, prasantgupta52, rbserver, ret2basic, rfa, robee, rokinot, rotcivegaf, rvierdiiev, sach1r0, scaraven, sikorico, simon135, smiling_heretic, sorrynotsorry, unforgiven, wagmi, yixxas
81.8103 USDC - $81.81
The project contains packages that urgently need to be updated because they contain important vulnerabilities.
Proof of concept:
To get the complete list of issues you have to run:
> npm audit
Summary:
83 vulnerabilities (2 low, 26 moderate, 52 high, 3 critical)
npm audit report:
@openzeppelin/contracts-upgradeable <=4.7.2 Severity: high OpenZeppelin Contracts's SignatureChecker may revert on invalid EIP-1271 signers - https://github.com/advisories/GHSA-4g63-c64m-25w9 OpenZeppelin Contracts's ERC165Checker may revert instead of returning false - https://github.com/advisories/GHSA-qh9x-gcfh-pcrw OpenZeppelin Contracts ERC165Checker unbounded gas consumption - https://github.com/advisories/GHSA-7grf-83vw-6f5x OpenZeppelin Contracts's GovernorVotesQuorumFraction updates to quorum may affect past defeated proposals - https://github.com/advisories/GHSA-xrc4-737v-9q75 OpenZeppelin Contracts vulnerable to ECDSA signature malleability - https://github.com/advisories/GHSA-4h98-2769-gh6h fix available via `npm audit fix`
ajv <6.12.3 Severity: moderate Prototype Pollution in Ajv - https://github.com/advisories/GHSA-v88g-cgmw-v5xw fix available via `npm audit fix --force`
async 2.0.0 - 2.6.3 Severity: high Prototype Pollution in async - https://github.com/advisories/GHSA-fwr7-v2mv-hh25 No fix available
braces <=2.3.0 Regular Expression Denial of Service in braces - https://github.com/advisories/GHSA-g95f-p29q-9xw4 Regular Expression Denial of Service (ReDoS) in braces - https://github.com/advisories/GHSA-cwfw-4gq5-mrqx fix available via `npm audit fix --force`
cross-fetch <=2.2.5 || 3.0.0 - 3.1.4 || >=3.2.0-alpha.0 Severity: high Incorrect Authorization in cross-fetch - https://github.com/advisories/GHSA-7gc6-qh9x-w6h8 Depends on vulnerable versions of node-fetch fix available via `npm audit fix`
diff <3.5.0 Severity: high Regular Expression Denial of Service (ReDoS) - https://github.com/advisories/GHSA-h6ch-v84p-w6p9 fix available via `npm audit fix --force`
elliptic <6.5.4 Severity: moderate Use of a Broken or Risky Cryptographic Algorithm - https://github.com/advisories/GHSA-r9p9-mrjm-926w fix available via `npm audit fix`
glob-parent <5.1.2 Severity: high glob-parent before 5.1.2 vulnerable to Regular Expression Denial of Service in enclosure regex - https://github.com/advisories/GHSA-ww39-953v-wcq6 fix available via `npm audit fix --force`
got <11.8.5 Severity: moderate Got allows a redirect to a UNIX socket - https://github.com/advisories/GHSA-pfrx-2q88-qq97 fix available via `npm audit fix --force`
highlight.js 9.0.0 - 10.4.0 Severity: moderate ReDOS vulnerabities: multiple grammars - https://github.com/advisories/GHSA-7wwv-vh3v-89cq fix available via `npm audit fix`
json-schema <0.4.0 Severity: critical json-schema is vulnerable to Prototype Pollution - https://github.com/advisories/GHSA-896r-f27r-55mw fix available via `npm audit fix`
lodash <=4.17.20 Severity: high Command Injection in lodash - https://github.com/advisories/GHSA-35jh-r3h4-6jhm Regular Expression Denial of Service (ReDoS) in lodash - https://github.com/advisories/GHSA-29mw-wpgm-hmr9 fix available via `npm audit fix`
mem <4.0.0 Severity: moderate Denial of Service in mem - https://github.com/advisories/GHSA-4xcv-9jjx-gfj3 No fix available
minimist <=1.2.5 Severity: critical Prototype Pollution in minimist - https://github.com/advisories/GHSA-xvch-5gv4-984h Prototype Pollution in minimist - https://github.com/advisories/GHSA-vh95-rmgr-6w4m fix available via `npm audit fix --force`
node-fetch <=2.6.6 Severity: high node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor - https://github.com/advisories/GHSA-r683-j2x4-v87g The `size` option isn't honored after following a redirect in node-fetch - https://github.com/advisories/GHSA-w7rc-rwvf-8q5r No fix available
normalize-url 4.3.0 - 4.5.0 Severity: high ReDoS in normalize-url - https://github.com/advisories/GHSA-px4h-xg32-q955 fix available via `npm audit fix`
path-parse <1.0.7 Severity: moderate Regular Expression Denial of Service in path-parse - https://github.com/advisories/GHSA-hj48-42vr-x3v9 fix available via `npm audit fix`
simple-get <2.8.2 Severity: high Exposure of Sensitive Information in simple-get - https://github.com/advisories/GHSA-wpg7-2c88-r8xv fix available via `npm audit fix`
tar <=4.4.17 Severity: high Arbitrary File Creation/Overwrite on Windows via insufficient relative path sanitization - https://github.com/advisories/GHSA-5955-9wpr-37jh Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning using symbolic links - https://github.com/advisories/GHSA-qq89-hq3f-393p Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning using symbolic links - https://github.com/advisories/GHSA-9r2w-394v-53qc Arbitrary File Creation/Overwrite due to insufficient absolute path sanitization - https://github.com/advisories/GHSA-3jfq-g458-7qm9 Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning - https://github.com/advisories/GHSA-r628-mhmh-qjhw fix available via `npm audit fix`
underscore 1.3.2 - 1.12.0 Severity: high Arbitrary Code Execution in underscore - https://github.com/advisories/GHSA-cf4h-3jhx-xvhq fix available via `npm audit fix --force`
undici <=5.8.1 Severity: high undici before v5.8.0 vulnerable to CRLF injection in request headers - https://github.com/advisories/GHSA-3cvr-822r-rqcc ProxyAgent vulnerable to MITM - https://github.com/advisories/GHSA-pgw7-wx7w-2w33 `undici.request` vulnerable to SSRF using absolute URL on `pathname` - https://github.com/advisories/GHSA-8qr4-xgw6-wmr3 Nodejs โundiciโ Vulnerable to CRLF Injection via Content-Type - https://github.com/advisories/GHSA-f772-66g8-q5h3 undici before v5.8.0 vulnerable to uncleared cookies on cross-host / cross-origin redirect - https://github.com/advisories/GHSA-q768-x9m6-m9qp fix available via `npm audit fix`
ws 5.0.0 - 5.2.2 Severity: moderate ReDoS in Sec-Websocket-Protocol header - https://github.com/advisories/GHSA-6fc8-4gx4-v693 fix available via `npm audit fix`
yargs-parser <=5.0.0 || 6.0.0 - 13.1.1 Severity: moderate yargs-parser Vulnerable to Prototype Pollution - https://github.com/advisories/GHSA-p9pc-299p-vxgp yargs-parser Vulnerable to Prototype Pollution - https://github.com/advisories/GHSA-p9pc-299p-vxgp No fix available
Recommended changes:
To address issues that do not require attention, run: npm audit fix To address all issues possible (including breaking changes), run: npm audit fix --force Some issues need review, and may require choosing a different dependency.
The pragma version used are:
pragma solidity =0.8.10; pragma solidity ^0.8.4;
Note that mixing pragma is not recommended. Because different compiler versions have different meanings and behaviors, it also significantly raises maintenance costs. As a result, depending on the compiler version selected for any given file, deployed contracts may have security issues.
The minimum required version must be 0.8.16; otherwise, contracts will be affected by the following important bug fixes:
abi.encodeCall
in place of fixed bytes arguments.calldatasize()
in all cases.bytes
arrays.Apart from these, there are several minor bug fixes and improvements.
redeem
The TribeRedeemer
constructor does not check that the same token appears repeated in the _tokensReceived
array.
If the tokensReceivedOnRedeem
method returns the same token twice, the amount that can be redeemed will be returned twice, since the balance of the contract is used and in both iterations it will be the same, this will cause that when the method is called redeem
, this fails due to not having enough balance.
function previewRedeem(uint256 amountIn) public view returns (address[] memory tokens, uint256[] memory amountsOut) { tokens = tokensReceivedOnRedeem(); amountsOut = new uint256[](tokens.length); uint256 base = redeemBase; for (uint256 i = 0; i < tokensReceived.length; i++) { uint256 balance = IERC20(tokensReceived[i]).balanceOf(address(this)); require(balance != 0, "ZERO_BALANCE"); // @dev, this assumes all of `tokensReceived` and `redeemedToken` // have the same number of decimals uint256 redeemedAmount = (amountIn * balance) / base; amountsOut[i] = redeemedAmount; } } function redeem(address to, uint256 amountIn) external nonReentrant { IERC20(redeemedToken).safeTransferFrom(msg.sender, address(this), amountIn); (address[] memory tokens, uint256[] memory amountsOut) = previewRedeem(amountIn); uint256 base = redeemBase; redeemBase = base - amountIn; // decrement the base for future redemptions for (uint256 i = 0; i < tokens.length; i++) { IERC20(tokens[i]).safeTransfer(to, amountsOut[i]); } emit Redeemed(msg.sender, to, amountIn, base); }
Recommended change:
Affected source code:
A user supplied argument can be passed as zero to multiplication operation.
Reference:
Affected source code:
The previewRedeem
method calls the tokensReceivedOnRedeem
method to get the list of tokens, however to iterate them it calls the state variable directly, if this method becomes virtual
and is overridden in the future, a denial of service could occur when using different variables.
function tokensReceivedOnRedeem() public view returns (address[] memory) { return tokensReceived; } function previewRedeem(uint256 amountIn) public view returns (address[] memory tokens, uint256[] memory amountsOut) { tokens = tokensReceivedOnRedeem(); amountsOut = new uint256[](tokens.length); uint256 base = redeemBase; - for (uint256 i = 0; i < tokensReceived.length; i++) { + for (uint256 i = 0; i < tokens.length; i++) { - uint256 balance = IERC20(tokensReceived[i]).balanceOf(address(this)); + uint256 balance = IERC20(tokens[i]).balanceOf(address(this)); require(balance != 0, "ZERO_BALANCE"); // @dev, this assumes all of `tokensReceived` and `redeemedToken` // have the same number of decimals uint256 redeemedAmount = (amountIn * balance) / base; amountsOut[i] = redeemedAmount; } }
Affected source code:
previewRedeem
logicThe previewRedeem
method of the TribeRedeemer
contract performs a check that the balance of the token is different from 0, otherwise this execution will fail, I think that this check should not be done in this method since it is a view
method, its result should be 0 instead of failing, and if you want to check this value, you should do it in the redeem
method.
Affected source code:
It is not good practice to hardcode values, but if you are dealing with addresses much less, these can change between implementations, networks or projects, so it is convenient to remove these addresses from the source code.
Affected source code:
Although the change is 1 to 1 and does not affect the logic, it is better to use the in and out variables instead of the same one, since if the conversion factor changes, the rest of the logic will not be affected and will be changed, reducing the change of human errors.
Recommended change:
/// @notice mint `amountFeiOut` FEI to address `to` for `amountIn` underlying tokens /// @dev see getMintAmountOut() to pre-calculate amount out function mint( address to, uint256 amountIn, uint256 minAmountOut ) external returns (uint256 amountFeiOut) { amountFeiOut = amountIn; require(amountFeiOut >= minAmountOut, "SimpleFeiDaiPSM: Mint not enough out"); DAI.safeTransferFrom(msg.sender, address(this), amountIn); FEI.mint(to, amountFeiOut); - emit Mint(to, amountIn, amountIn); + emit Mint(to, amountIn, amountFeiOut); } /// @notice redeem `amountFeiIn` FEI for `amountOut` underlying tokens and send to address `to` /// @dev see getRedeemAmountOut() to pre-calculate amount out /// @dev FEI received is not burned, see `burnFeiHeld()` below to batch-burn the FEI redeemed function redeem( address to, uint256 amountFeiIn, uint256 minAmountOut ) external returns (uint256 amountOut) { amountOut = amountFeiIn; require(amountOut >= minAmountOut, "SimpleFeiDaiPSM: Redeem not enough out"); FEI.safeTransferFrom(msg.sender, address(this), amountFeiIn); DAI.safeTransfer(to, amountOut); - emit Redeem(to, amountFeiIn, amountFeiIn); + emit Redeem(to, amountFeiIn, amountOut); }
Affected source code:
The _multiClaim
method calls the _claim
method multiple times, however the _multiRedeem
method replicates the logic and allows different implementations to perform the same action.
Such is the case of line 231, where it is checked that the token is different from address(0)
, a condition that is not done in the _redeem
method.
require(cTokens[i] != address(0), "Invalid cToken address");
Affected source code: