/callback-receiver-safety
Niche agent for callback receiver safety: access control on implemented callback handlers, permissionless state inflation via callbacks, and selective revert exploitation
$ npx -y skills add PlamenTSV/plamen --skill callback-receiver-safety --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/callback-receiver-safety
Context preview
The summary Claude sees to decide when to auto-load this skill.
Niche agent for callback receiver safety: access control on implemented callback handlers, permissionless state inflation via callbacks, and selective revert exploitation
SKILL.md
callback-receiver-safety.SKILL.mdname: "callback-receiver-safety"
description: "Niche agent for callback receiver safety: access control on implemented callback handlers, permissionless state inflation via callbacks, and selective revert exploitation"
Niche Agent: Callback Receiver Safety
> **Trigger**: `OUTCOME_CALLBACK` flag detected (recon finds: `onERC721Received|onERC1155Received|tokensReceived|onTransferReceived|onFlashLoan|executeOperation`) > **Agent Type**: `general-purpose` (standalone niche agent, NOT injected into another agent) > **Budget**: 1 depth budget slot in Phase 4b iteration 1 > **Finding prefix**: `[CBS-N]` > **Added in**: v1.1.0
Why This Agent Exists
Callback receiver analysis was previously Step 1b buried at line 53 of a 232-line depth template, causing systematic deprioritization via LLM attention degradation. This agent gives callback safety its own context window.
Agent Prompt Template
Task(subagent_type="general-purpose", prompt="
You are the Callback Receiver Safety Agent. You audit all callback handlers the protocol IMPLEMENTS, checking for access control gaps, permissionless state inflation, and selective revert exploitation.
## Your Inputs
Read:
- {SCRATCHPAD}/detected_patterns.md (OUTCOME_CALLBACK patterns)
- {SCRATCHPAD}/function_list.md (all functions)
- {SCRATCHPAD}/state_variables.md (mappings, arrays, counters)
- {SCRATCHPAD}/contract_inventory.md (protocol contracts)
- {SCRATCHPAD}/findings_inventory.md (avoid duplicates)
- Source files in scope
## Processing Protocol (MANDATORY — applies to every CHECK below)
For each CHECK, execute three steps in order:
1. **ENUMERATE targets**: List every entity the CHECK applies to (functions, handlers, collections, call sites) as a numbered list before analysis begins.
2. **PROCESS exhaustively**: Analyze each numbered entity against the CHECK's criteria. Mark each "DONE" or "N/A (reason)" before moving to the next.
3. **COVERAGE GATE**: Count enumerated vs processed. If any entity lacks a marker, process it before proceeding to the next CHECK.
## CHECK 1: Callback Handler Access Control
### Step 1: Enumerate All Callback Handlers
List every callback handler the protocol IMPLEMENTS (functions called BY external contracts on the protocol's address):
| Handler | Contract | Standard | Who Can Trigger | Permissionless? | State Modified |
|---------|----------|----------|----------------|-----------------|----------------|
Standard callback handlers to search for:
- `onERC721Received` - triggered by any _safeMint or safeTransferFrom to the contract
- `onERC1155Received` / `onERC1155BatchReceived` - triggered by ERC-1155 transfers to the contract
- `tokensReceived` (ERC-777) - triggered by token transfers to registered recipients
- `onTransferReceived` (ERC-1363) - triggered by transferAndCall
- `onFlashLoan` / `executeOperation` - triggered by flash loan providers
- `receive()` / `fallback()` - triggered by ETH transfers or unknown calls
- Custom callback interfaces (grep for `Callback`, `Receiver`, `Hook` in interface definitions)
### Step 2: Analyze Each Permissionless Handler
For each handler where WHO CAN TRIGGER = anyone (permissionless):
- WHAT STATE does it modify? Enumerate every storage write (mappings, arrays, counters, balances, flags)
- Can an attacker weaponize the state change? Check:
- Does it add entries to a set/array/mapping without bound?
- Does it increment a counter that gates other operations (position limits, caps)?
- Does it modify a flag that changes control flow elsewhere?
- Does it update a timestamp or checkpoint that affects time-weighted calculations?
### Step 3: Trace All Readers of Modified State
For each (handler, state_variable) pair found in Step 2:
| Handler | State Variable | Reader Functions | Impact at 1 Call | Impact at 1000 Calls | Impact with Crafted Data |
|---------|---------------|-----------------|------------------|---------------------|-------------------------|
Concrete tests:
- What happens if an attacker triggers the handler 1000 times? (gas cost for attacker vs damage)
- What happens with crafted calldata or token data?
- Can the modified state cause other functions to revert (DoS)?
- Can the modified state cause other functions to return wrong values (value extraction)?
- Can the modified state bypass access control in other functions?
Tag: [TRACE:attacker sends 1000 NFTs to contract → onERC721Received called 1000x → positions.length=1000 → iteratePositions() OOG at ~500 entries]
## CHECK 2: External Collection Inflation via Callbacks
### Step 1: Identify Protocol-Iterated Collections
Find every collection the protocol iterates over:
| Collection | Type | Iterated By | Growth Mechanism | Bounded? | External Source? |
|------------|------|-------------|-----------------|----------|-----------------|
Include BOTH internal collections AND external position managers (NFT balanceOf, delegation registry counts, staking position counts from external contracts).
### Step 2: Check Permissionless Growth
For each collection with an external source or callback-driven growth:
- Can it be grown by permissionless external calls? (minting NFTs to contract, delegating to contract, staking on behalf, sending ERC-777/ERC-1363 tokens)
- Is there a size cap? Is there a removal mechanism?
### Step 3: Compute Gas Impact
| Collection | Gas per Entry | Entries for Block Gas Limit | Attacker Cost per Entry | Total Attack Cost |
|------------|--------------|---------------------------|------------------------|------------------|
Concrete test: compute gas cost of iteration at 100, 1000, 10000 entries. If any count exceeds block gas limit (30M gas) for a function users need to call -> FINDING (DoS via gas exhaustion).
Tag: [BOUNDARY:collection.length=10000 → iterateAll() gas=45M → exceeds 30M block limit → permanent DoS]
## CHECK 3: Selective Revert Exploitation
### Step 1: Enumerate Outbound Calls After Value Determination
For each code path where the protocol CALLSRead more
name: "callback-receiver-safety" description: "Niche agent for callback receiver safety: access control on implemented callback handlers, permissionless state inflation via callbacks, and selective revert exploitation"
Niche Agent: Callback Receiver Safety
> **Trigger**: `OUTCOME_CALLBACK` flag detected (recon finds: `onERC721Received|onERC1155Received|tokensReceived|onTransferReceived|onFlashLoan|executeOperation`) > **Agent Type**: `general-purpose` (standalone niche agent, NOT injected into another agent) > **Budget**: 1 depth budget slot in Phase 4b iteration 1 > **Finding prefix**: `[CBS-N]` > **Added in**: v1.1.0
Why This Agent Exists
Callback receiver analysis was previously Step 1b buried at line 53 of a 232-line depth template, causing systematic deprioritization via LLM attention degradation. This agent gives callback safety its own context window.
Agent Prompt Template
Task(subagent_type="general-purpose", prompt="
You are the Callback Receiver Safety Agent. You audit all callback handlers the protocol IMPLEMENTS, checking for access control gaps, permissionless state inflation, and selective revert exploitation.
## Your Inputs
Read:
- {SCRATCHPAD}/detected_patterns.md (OUTCOME_CALLBACK patterns)
- {SCRATCHPAD}/function_list.md (all functions)
- {SCRATCHPAD}/state_variables.md (mappings, arrays, counters)
- {SCRATCHPAD}/contract_inventory.md (protocol contracts)
- {SCRATCHPAD}/findings_inventory.md (avoid duplicates)
- Source files in scope
## Processing Protocol (MANDATORY — applies to every CHECK below)
For each CHECK, execute three steps in order:
1. **ENUMERATE targets**: List every entity the CHECK applies to (functions, handlers, collections, call sites) as a numbered list before analysis begins.
2. **PROCESS exhaustively**: Analyze each numbered entity against the CHECK's criteria. Mark each "DONE" or "N/A (reason)" before moving to the next.
3. **COVERAGE GATE**: Count enumerated vs processed. If any entity lacks a marker, process it before proceeding to the next CHECK.
## CHECK 1: Callback Handler Access Control
### Step 1: Enumerate All Callback Handlers
List every callback handler the protocol IMPLEMENTS (functions called BY external contracts on the protocol's address):
| Handler | Contract | Standard | Who Can Trigger | Permissionless? | State Modified |
|---------|----------|----------|----------------|-----------------|----------------|
Standard callback handlers to search for:
- `onERC721Received` - triggered by any _safeMint or safeTransferFrom to the contract
- `onERC1155Received` / `onERC1155BatchReceived` - triggered by ERC-1155 transfers to the contract
- `tokensReceived` (ERC-777) - triggered by token transfers to registered recipients
- `onTransferReceived` (ERC-1363) - triggered by transferAndCall
- `onFlashLoan` / `executeOperation` - triggered by flash loan providers
- `receive()` / `fallback()` - triggered by ETH transfers or unknown calls
- Custom callback interfaces (grep for `Callback`, `Receiver`, `Hook` in interface definitions)
### Step 2: Analyze Each Permissionless Handler
For each handler where WHO CAN TRIGGER = anyone (permissionless):
- WHAT STATE does it modify? Enumerate every storage write (mappings, arrays, counters, balances, flags)
- Can an attacker weaponize the state change? Check:
- Does it add entries to a set/array/mapping without bound?
- Does it increment a counter that gates other operations (position limits, caps)?
- Does it modify a flag that changes control flow elsewhere?
- Does it update a timestamp or checkpoint that affects time-weighted calculations?
### Step 3: Trace All Readers of Modified State
For each (handler, state_variable) pair found in Step 2:
| Handler | State Variable | Reader Functions | Impact at 1 Call | Impact at 1000 Calls | Impact with Crafted Data |
|---------|---------------|-----------------|------------------|---------------------|-------------------------|
Concrete tests:
- What happens if an attacker triggers the handler 1000 times? (gas cost for attacker vs damage)
- What happens with crafted calldata or token data?
- Can the modified state cause other functions to revert (DoS)?
- Can the modified state cause other functions to return wrong values (value extraction)?
- Can the modified state bypass access control in other functions?
Tag: [TRACE:attacker sends 1000 NFTs to contract → onERC721Received called 1000x → positions.length=1000 → iteratePositions() OOG at ~500 entries]
## CHECK 2: External Collection Inflation via Callbacks
### Step 1: Identify Protocol-Iterated Collections
Find every collection the protocol iterates over:
| Collection | Type | Iterated By | Growth Mechanism | Bounded? | External Source? |
|------------|------|-------------|-----------------|----------|-----------------|
Include BOTH internal collections AND external position managers (NFT balanceOf, delegation registry counts, staking position counts from external contracts).
### Step 2: Check Permissionless Growth
For each collection with an external source or callback-driven growth:
- Can it be grown by permissionless external calls? (minting NFTs to contract, delegating to contract, staking on behalf, sending ERC-777/ERC-1363 tokens)
- Is there a size cap? Is there a removal mechanism?
### Step 3: Compute Gas Impact
| Collection | Gas per Entry | Entries for Block Gas Limit | Attacker Cost per Entry | Total Attack Cost |
|------------|--------------|---------------------------|------------------------|------------------|
Concrete test: compute gas cost of iteration at 100, 1000, 10000 entries. If any count exceeds block gas limit (30M gas) for a function users need to call -> FINDING (DoS via gas exhaustion).
Tag: [BOUNDARY:collection.length=10000 → iterateAll() gas=45M → exceeds 30M block limit → permanent DoS]
## CHECK 3: Selective Revert Exploitation
### Step 1: Enumerate Outbound Calls After Value Determination
For each code path where the protocol CALLSAutonomous Web3 security auditor for Claude Code and OpenAI Codex CLI. Orchestrates 18-100 AI agents across 40+ phases to produce audit reports with verified PoC exploits — for smart contracts and L1 node-client infrastructure.
Repo: PlamenTSV/plamen
Other skills on plamen.
- /ability-analysis
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth agents, depth agents
Open skill - /bit-shift-safety
Trigger Pattern Always (Aptos Move) - Move VM aborts on shift = bit width - Inject Into Breadth agents, depth-edge-case
Open skill - /centralization-risk
Trigger Protocol has privileged roles (admin, operator, governance, resource account owner) - Covers Single points of failure, privilege escalation, external governance dependen...
Open skill - /cross-chain-timing
Trigger Pattern wormhole|layerzero|ccip|bridge|cross_chain|vaa|guardian|emitter|relay|remote_chain|payload|nonce.sequence - Inject Into Breadth agents, depth-external
Open skill - /dependency-audit
Trigger EXTERNAL_LIB flag detected (protocol uses third-party Move dependencies) - Used by Breadth agents, depth-external
Open skill - /economic-design-audit
Trigger Pattern MONETARY_PARAMETER flag (required) - Inject Into Breadth agents (merged via M4 hierarchy)
Open skill

