# Incorrectly implemented modifiers in LybraConfigurator.sol allow any address to call functions that are supposed to be restricted

LybraConfigurator's onlyRole/checkRole modifiers call checkOnlyRole without require, so any address can invoke restricted setters like initToken and setProtocolRewardsPool.

- Payout: Contest reward
- Severity: high
- Program: Lybra Finance
- Credited: alexweb3
- Disclosed: 2023-08-21
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-06-lybra-findings/issues/704
- Library page: https://bugbountylibrary.com/r/c4%3A2023-06-lybra%3AH-03
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** LybraConfigurator.sol access-control modifiers (Solidity contract)
**Root cause:** The onlyRole and checkRole modifiers invoke GovernanceTimelock.checkOnlyRole(role, msg.sender) as a bare statement, discarding the boolean return value, so the modifier never reverts for unauthorized callers.
**Steps:**
1. Deploy GovernanceTimelock and Configurator as in setUp
2. Call `lybraConfigurator.initToken(eusd, pEusd)` from an arbitrary address (vm.prank(randomUser))
3. Observe EUSD address changes despite caller lacking role
4. Call `lybraConfigurator.setProtocolRewardsPool(rewardsPool)` from randomUser and observe rewards pool overwritten
**How found:** Manual code review of the modifier implementations, noticing checkOnlyRole's return value was not wrapped in require.
**Exploitation:** Any unprivileged address calls privileged configurator functions such as initToken (repointing EUSD/pEUSD tokens) and setProtocolRewardsPool (redirecting protocol rewards), taking over protocol configuration without a role.
**Insight:** When auditing role modifiers, verify the access-check call's boolean return is actually consumed (require/if-revert); a bare external call to a check function silently no-ops.
