mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
fix(engine): auto-approve http calls with registered credentials in v2
The v1 approval flow (interactive yes/no prompt) doesn't exist in v2. When the http tool returned UnlessAutoApproved for credentialed hosts, the effect adapter blocked with LeaseDenied — making all skill-based API calls fail. Fix: credential-backed http calls bypass the v1 approval check. The user authorized by storing the credential; the v1 interactive prompt is redundant in v2's lease-based security model. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
@@ -326,13 +326,27 @@ impl EffectExecutor for EffectBridgeAdapter {
|
||||
ApprovalRequirement::UnlessAutoApproved => {
|
||||
let is_approved = self.auto_approved.read().await.contains(lookup_name);
|
||||
if !is_approved {
|
||||
return Err(EngineError::LeaseDenied {
|
||||
reason: format!(
|
||||
"Tool '{}' requires approval. \
|
||||
Use a read-only tool instead, or ask the user to approve this action.",
|
||||
action_name
|
||||
),
|
||||
});
|
||||
// In v2, credential-backed HTTP calls are auto-approved.
|
||||
// The user authorized by storing the credential — the v1
|
||||
// interactive approval flow doesn't exist in v2.
|
||||
let has_credential_backing = lookup_name == "http"
|
||||
&& self
|
||||
.tools
|
||||
.credential_registry()
|
||||
.is_some_and(|reg| {
|
||||
crate::tools::builtin::extract_host_from_params(¶meters)
|
||||
.is_some_and(|host| reg.has_credentials_for_host(&host))
|
||||
});
|
||||
|
||||
if !has_credential_backing {
|
||||
return Err(EngineError::LeaseDenied {
|
||||
reason: format!(
|
||||
"Tool '{}' requires approval. \
|
||||
Use a read-only tool instead, or ask the user to approve this action.",
|
||||
action_name
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ApprovalRequirement::Never => {}
|
||||
|
||||
@@ -366,7 +366,8 @@ fn parse_save_to_param(save_to: Option<&serde_json::Value>) -> Result<Option<Str
|
||||
}
|
||||
|
||||
/// Extract host from URL in params (for approval checks).
|
||||
fn extract_host_from_params(params: &serde_json::Value) -> Option<String> {
|
||||
/// Extract the host from an HTTP tool's params (for credential registry lookup).
|
||||
pub fn extract_host_from_params(params: &serde_json::Value) -> Option<String> {
|
||||
params
|
||||
.get("url")
|
||||
.and_then(|u| u.as_str())
|
||||
|
||||
@@ -23,7 +23,7 @@ pub use extension_tools::{
|
||||
ToolRemoveTool, ToolSearchTool, ToolUpgradeTool,
|
||||
};
|
||||
pub use file::{ApplyPatchTool, ListDirTool, ReadFileTool, WriteFileTool};
|
||||
pub use http::HttpTool;
|
||||
pub use http::{HttpTool, extract_host_from_params};
|
||||
pub use job::{
|
||||
CancelJobTool, CreateJobTool, JobEventsTool, JobPromptTool, JobStatusTool, ListJobsTool,
|
||||
PromptQueue, SchedulerSlot,
|
||||
|
||||
Reference in New Issue
Block a user