Summary
In tools/delegate_tool.py (lines ~370-372), subagents receive a reference to the parent's credential pool, giving them access to all API keys for the provider — not just the one they need:
child_pool = _resolve_child_credential_pool(effective_provider, parent_agent)
if child_pool is not None:
child._credential_pool = child_pool
Impact
A prompt-injected subagent can iterate over the credential pool and exfiltrate all API keys. Combined with the non-interactive auto-approve behavior (approval.py:617, reported in #7826), the subagent has unrestricted shell access to send keys to an external server.
Suggested Fix
Provide subagents with a scoped view of the credential pool that only exposes the currently leased credential, not the full pool:
class ScopedCredentialView:
"""Read-only view exposing only the leased credential."""
def __init__(self, leased_entry):
self._entry = leased_entry
def select(self):
return self._entry
# Block iteration, status, and other pool-wide operations
Severity
Warning — requires prompt injection into a subagent context to exploit.
Summary
In
tools/delegate_tool.py(lines ~370-372), subagents receive a reference to the parent's credential pool, giving them access to all API keys for the provider — not just the one they need:Impact
A prompt-injected subagent can iterate over the credential pool and exfiltrate all API keys. Combined with the non-interactive auto-approve behavior (approval.py:617, reported in #7826), the subagent has unrestricted shell access to send keys to an external server.
Suggested Fix
Provide subagents with a scoped view of the credential pool that only exposes the currently leased credential, not the full pool:
Severity
Warning — requires prompt injection into a subagent context to exploit.