From e4126b86773f4083ac0da7ced53edcb4898541bf Mon Sep 17 00:00:00 2001 From: MoMannn Date: Thu, 11 Jun 2026 10:08:10 +0200 Subject: [PATCH] document some edge case scenarios --- documents/CaveatEnforcers.md | 12 ++++++++++++ documents/Security.md | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/documents/CaveatEnforcers.md b/documents/CaveatEnforcers.md index f7a57fb9..372913ad 100644 --- a/documents/CaveatEnforcers.md +++ b/documents/CaveatEnforcers.md @@ -307,6 +307,18 @@ Neither case is an authority escalation (the structural constraints above still If a redelegator needs a root-scoped guarantee (e.g. "Carol may only revoke one of Alice's specific approvals"), they should rely on structural caveats that compose cleanly across links, such as `AllowedTargetsEnforcer`, `AllowedCalldataEnforcer`, or `ExactCalldataEnforcer`. Placing `ApprovalRevocationEnforcer` on an intermediate link in the hope of validating the root's approval state does not achieve that. +### AllowedTargetsEnforcer and AllowedMethodsEnforcer + +`AllowedTargetsEnforcer` restricts a delegation to call only a specified set of target addresses. `AllowedMethodsEnforcer` restricts a delegation to call only a specified set of function selectors. Both are simple, composable guards that inspect the outer execution — they do **not** inspect nested calldata inside the execution payload. + +> ⚠️ **Security Notice**: These enforcers are safe in all typical combinations. The one exception: if `AllowedMethodsEnforcer` permits `redeemDelegations` **and** the delegation targets the delegator's own account (e.g. via `AllowedTargetsEnforcer`), the delegate gains unrestricted execution authority despite the seemingly narrow permission. Never permit `redeemDelegations` as an allowed method in that context. See [Security.md](./Security.md#allowedmethodsenforcer-with-redeemdelegations-on-a-self-targeted-delegation-arbitrary-execution-escalation) for details. + +### ERC20PeriodTransferEnforcer + +`ERC20PeriodTransferEnforcer` enforces a rolling per-period ERC-20 transfer cap on a delegation, initializing its state on first use and resetting it each time a new period begins. + +> ⚠️ **Security Notice**: Attaching more than one `ERC20PeriodTransferEnforcer` caveat to the **same delegation** (e.g. a daily cap and a monthly cap) causes state collision — only the first instance in the caveats array initializes the shared storage slot, and subsequent instances silently reuse it, making their own terms ineffective. Do not attach multiple instances to a single delegation. See [Security.md — ERC20PeriodTransferEnforcer: multiple instances on the same delegation](./Security.md#erc20periodtransferenforcer-multiple-instances-on-the-same-delegation) for details. + ## LogicalOrWrapperEnforcer Context Switching The `LogicalOrWrapperEnforcer` enables logical OR functionality between groups of enforcers, allowing flexibility in delegation constraints. This enforcer is designed for a narrow set of use cases, and careful attention must be given when constructing caveats. The enforcer introduces an important architectural consideration: **context switching**. diff --git a/documents/Security.md b/documents/Security.md index aef11fc0..125a83ce 100644 --- a/documents/Security.md +++ b/documents/Security.md @@ -77,3 +77,25 @@ Improperly constructed calldata can lead to: - **Separate sensitive operations** into individual transactions when possible --- + +## Caveat Enforcer Combination Risks + +### AllowedMethodsEnforcer with `redeemDelegations` on a Self-Targeted Delegation: Arbitrary Execution Escalation + +> ⚠️ **Security Notice** +> +> Using `AllowedMethodsEnforcer` with `redeemDelegations` as a permitted method — when the delegation also targets the delegator's own account (e.g. via `AllowedTargetsEnforcer`) — grants the delegate **unrestricted execution authority** over the delegator's account, despite appearing narrow. The enforcer only inspects the outer execution selector and does not look inside the nested calldata. A delegate can exploit the account's self-call path (`onlyEntryPointOrSelf` on the DeleGator's `redeemDelegations`) and the `DelegationManager`'s empty-context shortcut to execute arbitrary calldata with root authority. +> +> `AllowedMethodsEnforcer` and `AllowedTargetsEnforcer` are safe in all other combinations. The risk is specific to `redeemDelegations` being an allowed method on a delegation that targets the delegator's own account. **Never** permit `redeemDelegations` as an allowed method in that context. + +--- + +### ERC20PeriodTransferEnforcer: Multiple Instances on the Same Delegation + +> ⚠️ **Security Notice** +> +> `ERC20PeriodTransferEnforcer` keys its state by `(delegationManager, delegationHash)`. When two or more instances are attached to the same delegation (e.g. a daily and a monthly cap), only the first caveat in array order initializes the storage slot — subsequent instances silently reuse it, rendering their own `terms` ineffective. The effective ceiling becomes whichever caveat ran first, not the most restrictive one. +> +> Do **not** attach more than one `ERC20PeriodTransferEnforcer` to a single delegation. + +---