diff --git a/apps/api/src/services/decision_manager.py b/apps/api/src/services/decision_manager.py index 291d47ec..c5187065 100644 --- a/apps/api/src/services/decision_manager.py +++ b/apps/api/src/services/decision_manager.py @@ -678,6 +678,25 @@ class DecisionManager: action = _re.sub(r"", _target, action) action = _re.sub(r"<[^>]+>", _target, action) + # 安全守衛: 替換後仍含 "unknown" 或未替換的 <...>/{...} → 拒絕執行 + # 主機層告警(HostHighCpuLoad 等)沒有 deployment 名稱,不應盲目執行 + if "unknown" in action or _re.search(r"[<{][^>}]+[>}]", action): + logger.warning( + "auto_execute_blocked_unresolved_placeholder", + incident_id=incident.incident_id, + action=action, + target=_target, + reason="action 含未解析的 placeholder 或 unknown,拒絕執行", + ) + token.state = DecisionState.ERROR + token.error = f"Auto-execute blocked: unresolved placeholder in action: {action[:80]}" + await self._save_token(token) + asyncio.create_task( + _push_auto_repair_result(incident, action, success=False, + error="無法確認 deployment 名稱,請人工確認後手動執行") + ) + return + try: # 延遲導入避免循環依賴 from src.models.approval import ApprovalRequest, ApprovalStatus