fix: resolve 17 P2 defects and 5 P3 defects from pre-launch audit
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Batch fix covering multiple modules:
- P2-01: HandRegistry Semaphore-based max_concurrent enforcement
- P2-03: Populate toolCount/metricCount from Hand trait methods
- P2-06: heartbeat_update_config minimum interval validation
- P2-07: ReflectionResult used_fallback marker for rule-based fallback
- P2-08/09: identity_propose_change parameter naming consistency
- P2-10: ClassroomMetadata is_placeholder flag for LLM failure
- P2-11: classroomStore userDidCloseDuringGeneration intent tracking
- P2-12: workflowStore pipeline_create sends actionType
- P2-13/14: PipelineInfo step_count + PipelineStepInfo for proper step mapping
- P2-15: Pipe transform support in context.resolve (8 transforms)
- P2-16: Mustache {{...}} → \${...} auto-normalization
- P2-17: SaaSLogin password placeholder 6→8
- P2-19: serialize_skill_md + update_skill preserve tools field
- P2-22: ToolOutputGuard sensitive patterns from warn→block
- P2-23: Mutex::unwrap() → unwrap_or_else in relay/service.rs
- P3-01/03/07/08/09: Various P3 fixes
- DEFECT_LIST.md: comprehensive status sync (43/51 fixed, 8 remaining)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -449,7 +449,7 @@ impl AgentLoop {
|
||||
}
|
||||
} else {
|
||||
// Legacy inline path
|
||||
let guard_result = self.loop_guard.lock().unwrap().check(&name, &input);
|
||||
let guard_result = self.loop_guard.lock().unwrap_or_else(|e| e.into_inner()).check(&name, &input);
|
||||
match guard_result {
|
||||
LoopGuardResult::CircuitBreaker => {
|
||||
tracing::warn!("[AgentLoop] Circuit breaker triggered by tool '{}'", name);
|
||||
@@ -621,7 +621,7 @@ impl AgentLoop {
|
||||
let memory = self.memory.clone();
|
||||
let driver = self.driver.clone();
|
||||
let tools = self.tools.clone();
|
||||
let loop_guard_clone = self.loop_guard.lock().unwrap().clone();
|
||||
let loop_guard_clone = self.loop_guard.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
||||
let middleware_chain = self.middleware_chain.clone();
|
||||
let skill_executor = self.skill_executor.clone();
|
||||
let path_validator = self.path_validator.clone();
|
||||
@@ -911,7 +911,7 @@ impl AgentLoop {
|
||||
}
|
||||
} else {
|
||||
// Legacy inline loop guard path
|
||||
let guard_result = loop_guard_clone.lock().unwrap().check(&name, &input);
|
||||
let guard_result = loop_guard_clone.lock().unwrap_or_else(|e| e.into_inner()).check(&name, &input);
|
||||
match guard_result {
|
||||
LoopGuardResult::CircuitBreaker => {
|
||||
let _ = tx.send(LoopEvent::Error("检测到工具调用循环,已自动终止".to_string())).await;
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
//!
|
||||
//! Rules:
|
||||
//! - Output length cap: warns when tool output exceeds threshold
|
||||
//! - Sensitive pattern detection: flags API keys, tokens, passwords
|
||||
//! - Injection marker detection: flags common prompt-injection patterns
|
||||
//! - Sensitive pattern detection: logs error-level for API keys, tokens, passwords
|
||||
//! - Injection marker detection: **blocks** output containing prompt-injection patterns
|
||||
//!
|
||||
//! This middleware does NOT modify content. It only logs warnings at appropriate levels.
|
||||
//! P2-22 fix: Injection patterns now return Err to prevent malicious output reaching the LLM.
|
||||
//! Sensitive patterns log at error level (was warn) for visibility.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use serde_json::Value;
|
||||
@@ -104,26 +105,32 @@ impl AgentMiddleware for ToolOutputGuardMiddleware {
|
||||
);
|
||||
}
|
||||
|
||||
// Rule 2: Sensitive information detection
|
||||
// Rule 2: Sensitive information detection — block output containing secrets (P2-22)
|
||||
let output_lower = output_str.to_lowercase();
|
||||
for pattern in SENSITIVE_PATTERNS {
|
||||
if output_lower.contains(pattern) {
|
||||
tracing::warn!(
|
||||
"[ToolOutputGuard] Tool '{}' output contains sensitive pattern: '{}'",
|
||||
tracing::error!(
|
||||
"[ToolOutputGuard] BLOCKED tool '{}' output: sensitive pattern '{}'",
|
||||
tool_name, pattern
|
||||
);
|
||||
break; // Only warn once per tool call
|
||||
return Err(zclaw_types::ZclawError::Internal(format!(
|
||||
"[ToolOutputGuard] Tool '{}' output blocked: sensitive information detected ('{}')",
|
||||
tool_name, pattern
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Rule 3: Injection marker detection
|
||||
// Rule 3: Injection marker detection — BLOCK the output (P2-22 fix)
|
||||
for pattern in INJECTION_PATTERNS {
|
||||
if output_lower.contains(pattern) {
|
||||
tracing::warn!(
|
||||
"[ToolOutputGuard] Tool '{}' output contains potential injection marker: '{}'",
|
||||
tracing::error!(
|
||||
"[ToolOutputGuard] BLOCKED tool '{}' output: injection marker '{}'",
|
||||
tool_name, pattern
|
||||
);
|
||||
break; // Only warn once per tool call
|
||||
return Err(zclaw_types::ZclawError::Internal(format!(
|
||||
"[ToolOutputGuard] Tool '{}' output blocked: potential prompt injection detected",
|
||||
tool_name
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user