diff --git a/crates/goose/src/agents/tool_execution.rs b/crates/goose/src/agents/tool_execution.rs index 5ffd6eb72bfb..b8813900b8a4 100644 --- a/crates/goose/src/agents/tool_execution.rs +++ b/crates/goose/src/agents/tool_execution.rs @@ -88,7 +88,7 @@ impl Agent { // Log user decision if this was a security alert if let Some(finding_id) = get_security_finding_id_from_results(&request.id, inspection_results) { tracing::info!( - counter.goose.prompt_injection_user_decisions = 1, + monotonic_counter.goose.prompt_injection_user_decisions = 1, decision = ?confirmation.permission, finding_id = %finding_id, tool_request_id = %request.id, diff --git a/crates/goose/src/security/mod.rs b/crates/goose/src/security/mod.rs index 88b5d21487f1..1384ce70f7b2 100644 --- a/crates/goose/src/security/mod.rs +++ b/crates/goose/src/security/mod.rs @@ -61,20 +61,34 @@ impl SecurityManager { ) -> Result> { if !self.is_prompt_injection_detection_enabled() { tracing::debug!( - counter.goose.prompt_injection_scanner_disabled = 1, + monotonic_counter.goose.prompt_injection_scanner_disabled = 1, "Security scanning disabled" ); return Ok(vec![]); } let scanner = self.scanner.get_or_init(|| { + let config = Config::global(); + let command_classifier_enabled = config + .get_param::("SECURITY_COMMAND_CLASSIFIER_ENABLED") + .unwrap_or(false); + let prompt_classifier_enabled = config + .get_param::("SECURITY_PROMPT_CLASSIFIER_ENABLED") + .unwrap_or(false); + + tracing::info!( + monotonic_counter.goose.security_command_classifier_enabled = if command_classifier_enabled { 1 } else { 0 }, + monotonic_counter.goose.security_prompt_classifier_enabled = if prompt_classifier_enabled { 1 } else { 0 }, + "Security classifier configuration" + ); + let ml_enabled = self.is_ml_scanning_enabled(); let scanner = if ml_enabled { match PromptInjectionScanner::with_ml_detection() { Ok(s) => { tracing::info!( - counter.goose.prompt_injection_scanner_enabled = 1, + monotonic_counter.goose.prompt_injection_scanner_enabled = 1, "Security scanner initialized with ML-based detection" ); s @@ -90,7 +104,7 @@ impl SecurityManager { } } else { tracing::info!( - counter.goose.prompt_injection_scanner_enabled = 1, + monotonic_counter.goose.prompt_injection_scanner_enabled = 1, "Security scanner initialized with pattern-based detection only" ); PromptInjectionScanner::new() @@ -124,7 +138,7 @@ impl SecurityManager { serde_json::to_string(&tool_call).unwrap_or_else(|_| "{}".to_string()); tracing::warn!( - counter.goose.prompt_injection_finding = 1, + monotonic_counter.goose.prompt_injection_finding = 1, threat_type = "command_injection", above_threshold = above_threshold, tool_name = %tool_call.name, @@ -164,7 +178,7 @@ impl SecurityManager { } tracing::info!( - counter.goose.prompt_injection_analysis_performed = 1, + monotonic_counter.goose.prompt_injection_analysis_performed = 1, security_issues_found = results.len(), "Prompt injection detection: Security analysis complete" ); diff --git a/crates/goose/src/security/scanner.rs b/crates/goose/src/security/scanner.rs index 1e6b4607b915..f8929364ee68 100644 --- a/crates/goose/src/security/scanner.rs +++ b/crates/goose/src/security/scanner.rs @@ -27,6 +27,7 @@ struct DetailedScanResult { confidence: f32, pattern_matches: Vec, ml_confidence: Option, + used_pattern_detection: bool, } pub struct PromptInjectionScanner { @@ -160,9 +161,9 @@ impl PromptInjectionScanner { tool_confidence = %tool_result.confidence, context_confidence = ?context_result.ml_confidence, final_confidence = %final_confidence, - has_command_ml = tool_result.ml_confidence.is_some(), - has_prompt_ml = context_result.ml_confidence.is_some(), - has_patterns = !tool_result.pattern_matches.is_empty(), + used_command_ml = tool_result.ml_confidence.is_some(), + used_prompt_ml = context_result.ml_confidence.is_some(), + used_pattern_detection = tool_result.used_pattern_detection, threshold = %threshold, malicious = final_confidence >= threshold, "Security analysis complete" @@ -172,6 +173,7 @@ impl PromptInjectionScanner { confidence: final_confidence, pattern_matches: tool_result.pattern_matches, ml_confidence: tool_result.ml_confidence, + used_pattern_detection: tool_result.used_pattern_detection, }; Ok(ScanResult { @@ -191,6 +193,7 @@ impl PromptInjectionScanner { confidence: ml_confidence, pattern_matches: Vec::new(), ml_confidence: Some(ml_confidence), + used_pattern_detection: false, }); } } @@ -200,6 +203,7 @@ impl PromptInjectionScanner { confidence: pattern_confidence, pattern_matches, ml_confidence: None, + used_pattern_detection: true, }) } @@ -211,6 +215,7 @@ impl PromptInjectionScanner { confidence: 0.0, pattern_matches: Vec::new(), ml_confidence: None, + used_pattern_detection: false, }); }; @@ -219,6 +224,7 @@ impl PromptInjectionScanner { confidence: 0.0, pattern_matches: Vec::new(), ml_confidence: None, + used_pattern_detection: false, }); } @@ -237,6 +243,7 @@ impl PromptInjectionScanner { confidence: max_confidence, pattern_matches: Vec::new(), ml_confidence: Some(max_confidence), + used_pattern_detection: false, }) }