Description
DynExecutor implements ToolExecutor but does not override requires_confirmation, so it always returns the default false from ToolExecutor. Every other delegation method (is_tool_retryable, is_tool_speculatable, set_skill_env, set_effective_trust) correctly calls the corresponding _erased variant on the inner Arc<dyn ErasedToolExecutor> — but requires_confirmation is missing.
This inconsistency is currently unexploitable because the speculation engine holds Arc<dyn ErasedToolExecutor> directly and calls requires_confirmation_erased without going through DynExecutor. However, DynExecutor is a public composition primitive, and as usage grows the missing delegation will silently produce incorrect behavior.
Reproduction Steps
- Wrap an
ErasedToolExecutor implementation that overrides requires_confirmation_erased to return true inside a DynExecutor
- Call
dyn_executor.requires_confirmation(call) via the ToolExecutor trait
- Observe: returns
false instead of delegating to the inner requires_confirmation_erased
Expected Behavior
DynExecutor::requires_confirmation should delegate to self.0.requires_confirmation_erased(call), consistent with all other delegation methods.
Recommended Fix
Add to DynExecutor's ToolExecutor impl:
fn requires_confirmation(&self, call: &ToolCall) -> bool {
self.0.requires_confirmation_erased(call)
}
Files
crates/zeph-tools/src/executor.rs — DynExecutor impl of ToolExecutor
Depends on
#3644 (merged) — introduced ToolExecutor::requires_confirmation
Description
DynExecutorimplementsToolExecutorbut does not overriderequires_confirmation, so it always returns the defaultfalsefromToolExecutor. Every other delegation method (is_tool_retryable,is_tool_speculatable,set_skill_env,set_effective_trust) correctly calls the corresponding_erasedvariant on the innerArc<dyn ErasedToolExecutor>— butrequires_confirmationis missing.This inconsistency is currently unexploitable because the speculation engine holds
Arc<dyn ErasedToolExecutor>directly and callsrequires_confirmation_erasedwithout going throughDynExecutor. However,DynExecutoris a public composition primitive, and as usage grows the missing delegation will silently produce incorrect behavior.Reproduction Steps
ErasedToolExecutorimplementation that overridesrequires_confirmation_erasedto returntrueinside aDynExecutordyn_executor.requires_confirmation(call)via theToolExecutortraitfalseinstead of delegating to the innerrequires_confirmation_erasedExpected Behavior
DynExecutor::requires_confirmationshould delegate toself.0.requires_confirmation_erased(call), consistent with all other delegation methods.Recommended Fix
Add to
DynExecutor'sToolExecutorimpl:Files
crates/zeph-tools/src/executor.rs—DynExecutorimpl ofToolExecutorDepends on
#3644 (merged) — introduced
ToolExecutor::requires_confirmation