# OpenZeppelin Reentrancy Bugfix Review

TimelockController.executeBatch checked isOperationReady after executing calls, letting an EXECUTOR reenter and self-govern the timelock to seize PROPOSER/ADMIN roles.

- Payout: $25,000
- Severity: critical
- Program: OpenZeppelin
- Credited: Zb3
- Disclosed: 2021-09-03
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/openzeppelin-reentrancy-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-openzeppelin-reentrancy-bugfix-review
- Tags: domain:web3 impact:integrity impact:privesc kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:reentrancy

**Target:** TimelockController smart contract (executeBatch)
**Root cause:** executeBatch performs the external _call loop before require(isOperationReady(id)), so a reentrant call during execution bypasses the readiness/approval check; the timelock self-governs ADMIN, so it can call itself.
**Steps:**
1. Attacker with EXECUTOR_ROLE calls executeBatch targeting the TimelockController itself
2. During _call, reenter executeBatch before isOperationReady(id) is checked
3. Reentrant call grants attacker PROPOSER role
4. Set minDelay to 0
5. Schedule and approve an arbitrary call, then execute it to hijack roles/contracts
**Exploitation:** EXECUTOR reenters executeBatch to make the timelock call itself: grant PROPOSER, zero the delay, approve arbitrary operations, then execute them to remove existing PROPOSERs, set attacker as PROPOSER, and make arbitrary external calls taking over dependent contracts.
**Escalation:** Self-governance of ADMIN by the timelock lets the EXECUTOR escalate to full control of the timelock and any contract it governs.
**Insight:** In self-governing timelocks, audit whether authorization/readiness checks run before external self-calls; an EXECUTOR that can make the contract call itself can reenter past post-call checks.
