# Alchemix Access Control Issue Bugfix Review

AlchemixHarvester whitelisted Gelato's generic Automate contract, so anyone could create a task calling harvest() with minimumAmountOut=1 and sandwich the Balancer rETH unwrap to steal yield.

- Payout: $28,730
- Severity: high
- Program: Alchemix
- Credited: Koiush
- Disclosed: 2024-06-14
- Write-up quality: 8/10
- Original: https://immunefi.com/blog/bug-fix-reviews/alchemix-access-control-issue-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic vuln:oracle-manipulation vuln:reward-distribution

**Target:** AlchemixHarvester / AlchemistV2 harvest via Gelato Automate
**Root cause:** Harvester whitelisted the permissionless generic Gelato Automate contract instead of a dedicated PROXY msg.sender, letting any user create a task invoking harvest() with attacker-chosen minimumAmountOut.
**Steps:**
1. Call `automate.createTask(harvester, abi.encodeWithSelector(harvest.selector, alETH, rETH, 1), ...)` to register a task with minimumAmountOut=1
2. Front-run: swap 13500 rETH into the rETH/WETH Balancer pool to push rETH price up
3. Trigger `automate.exec(...)` so Gelato keeper calls `harvest(alETH, rETH, 1)`; unwrap executes at manipulated rate with no slippage protection
4. Back-run: swap remaining WETH back to rETH to restore pool rate and realize profit
**How found:** Noticed the harvester restricted callers to the generic Gelato Automate address rather than a dedicated PROXY msg.sender; since createTask is permissionless, any user could craft a harvest call with arbitrary minimumAmountOut, and the resolver's checker() logic revealed a way to suppress legitimate harvests.
**Exploitation:** Attacker needs no capital beyond the sandwich swap; creates a permissionless Gelato task targeting the harvester with minimumAmountOut=1, manipulates the Balancer rETH/WETH pool upward, triggers the keeper exec so the harvest unwraps at the inflated rate, then reverses the swap to recover collateral and keep a portion of accrued WETH (PoC: ~4.975 rETH profit, 14.2 WETH protocol loss).
**Escalation:** Attacker could pass a custom contract as the alchemist parameter so the resolver records a harvest without harvesting, blocking the legitimate keeper via the checker() condition and letting unharvested yield accumulate for a more profitable sandwich.
**Insight:** When a contract whitelists a shared, permissionless automation/relayer contract (Gelato Automate, Chainlink Automation) instead of a dedicated per-task proxy, treat every parameter of the automated call as attacker-controlled; check whether the resolver/checker can be spoofed to suppress legitimate executions and inflate the eventual sandwich.
