AI 에이전트 시스템의 가장 중요한 보안 위험 10가지와 이를 완화하는 방법을 알아보세요.
자율적으로 계획하고, 도구를 사용하고, 외부 서비스와 상호 작용하는 AI 에이전트 시스템과 관련된 가장 중요한 보안 위험의 순위입니다. 2026년 버전에서는 에이전트 AI가 연구용에서 프로덕션 배포로 이동하면서 새롭게 등장하는 위협을 다룹니다.
공격자는 조작된 입력을 통해 에이전트의 목표 또는 목적을 조작하여 의도하지 않은 목표를 추구하도록 합니다. 단순한 프롬프트 인젝션과 달리 목표 하이재킹은 여러 계획 단계에서 지속될 수 있으며, 에이전트가 일련의 유해한 작업을 자율적으로 수행하도록 만들 수 있습니다.
공격자는 자율 에이전트를 리디렉션하여 데이터를 유출하거나 시스템 구성을 수정하거나 에이전트가 정상적으로 작동하는 것처럼 보이기 때문에 탐지하기 어려운 다단계 공격 체인을 수행할 수 있습니다.
# Agent goal is derived directly from untrusted input def run_agent(user_request: str) -> str: goal = f"Complete this task: {user_request}" plan = llm.plan(goal) for step in plan: execute(step) # No validation of planned steps
import re ALLOWED_GOALS = ["summarize", "search", "draft_email", "analyze_data"] def sanitize_goal(user_request: str) -> str: # Strip injection patterns cleaned = re.sub(r'(?i)(ignore|override|new goal|forget).*', '', user_request) return cleaned.strip() def run_agent(user_request: str) -> str: sanitized = sanitize_goal(user_request) goal = f"Complete this task: {sanitized}" plan = llm.plan(goal) # Validate each step against allowed actions for step in plan: if step.action not in ALLOWED_GOALS: raise ValueError(f"Disallowed action: {step.action}") if goal_drift_detected(step, sanitized): raise ValueError("Goal drift detected, aborting") for step in plan: execute(step)
외부 도구(API, 파일 시스템, 데이터베이스, 웹 브라우저)에 액세스할 수 있는 에이전트는 이러한 도구를 오용하도록 조작될 수 있습니다. 제한되지 않은 도구 액세스는 공격자가 에이전트를 통해 무단 작업을 수행할 수 있도록 허용합니다.
도구 액세스 권한이 무제한인 에이전트는 파일을 삭제하거나, 무단 API 요청을 보내거나, 웹 브라우징을 통해 데이터를 유출하거나, 중요한 시스템 구성을 수정할 수 있습니다.
# Agent can call any tool without restrictions def agent_execute(tool_name: str, params: dict): tool = tools_registry.get(tool_name) return tool(**params) # No validation or approval
TOOL_ALLOWLIST = {
"web_search": {"max_calls": 10, "approval": False},
"send_email": {"max_calls": 1, "approval": True},
"file_write": {"max_calls": 5, "approval": True},
}
def agent_execute(tool_name: str, params: dict, session) -> str:
if tool_name not in TOOL_ALLOWLIST:
return "Error: Tool not permitted"
config = TOOL_ALLOWLIST[tool_name]
if session.tool_calls[tool_name] >= config["max_calls"]:
return "Error: Tool call limit exceeded"
if config["approval"]:
if not request_human_approval(tool_name, params):
return "Action denied by user"
session.tool_calls[tool_name] += 1
return tools_registry[tool_name](**params)
에이전트는 종종 자신을 실행한 사용자 또는 서비스 계정의 ID와 권한을 상속받습니다. 이러한 과도한 권한 상속으로 인해 에이전트가 필요한 것 이상의 작업을 수행할 수 있으며, 에이전트가 손상될 경우 광범위한 공격 표면이 만들어집니다.
관리자 자격 증명으로 실행되는 손상된 에이전트는 모든 시스템에 액세스하고 권한을 수정하며 조직 전체에서 권한을 에스컬레이션할 수 있습니다.
# Agent inherits full user credentials def create_agent(user_session): agent = Agent( credentials=user_session.full_credentials, # All permissions! scope="*", ) return agent
def create_agent(user_session, task_type: str): # Issue scoped, short-lived credentials for the agent scoped_token = auth.create_scoped_token( parent_token=user_session.token, scopes=TASK_SCOPES[task_type], # Minimal required permissions ttl_minutes=30, max_actions=50, ) agent = Agent( credentials=scoped_token, scope=TASK_SCOPES[task_type], audit_log=True, ) return agent TASK_SCOPES = { "summarize": ["read:documents"], "draft_email": ["read:contacts", "draft:email"], "analyze": ["read:data", "write:reports"], }
상담원 시스템은 타사 플러그인, 툴 통합 및 공유 상담원 프레임워크에 의존합니다. 에이전트 공급망에서 손상되었거나 악의적인 구성 요소는 백도어, 데이터 유출 채널 또는 무단 기능을 도입할 수 있습니다.
# Loading plugins without verification def load_plugin(plugin_url: str): code = requests.get(plugin_url).text exec(code) # Arbitrary code execution!
import hashlib, importlib TRUSTED_PLUGINS = { "search_plugin": "sha256:a1b2c3...", "email_plugin": "sha256:d4e5f6...", } def load_plugin(plugin_name: str) -> None: if plugin_name not in TRUSTED_PLUGINS: raise ValueError(f"Untrusted plugin: {plugin_name}") module = importlib.import_module(f"plugins.{plugin_name}") actual_hash = compute_hash(module.__file__) if actual_hash != TRUSTED_PLUGINS[plugin_name]: raise ValueError("Plugin integrity check failed") module.init(sandbox=True)
코드를 생성하고 실행할 수 있는 에이전트(예: 데이터 분석 에이전트, 코딩 어시스턴트)가 속아서 악성 코드를 실행할 수 있습니다. 적절한 샌드박싱이 없으면 시스템 손상, 데이터 도난 또는 측면 이동으로 이어질 수 있습니다.
생성된 코드에서 eval() 또는 exec()를 사용하는 에이전트는 원격 코드 실행에 악용되어 공격자가 전체 시스템 액세스 권한을 획득할 수 있습니다.
# Agent executes generated code directly def code_agent(task: str) -> str: code = llm.generate_code(task) result = eval(code) # Dangerous! return str(result)
import subprocess, tempfile, os BLOCKED_MODULES = ["os", "subprocess", "socket", "shutil"] def code_agent(task: str) -> str: code = llm.generate_code(task) # Static analysis: block dangerous imports for mod in BLOCKED_MODULES: if f"import {mod}" in code or f"from {mod}" in code: raise ValueError(f"Blocked import: {mod}") # Execute in sandboxed container with resource limits result = sandbox.run( code=code, timeout=30, memory_mb=256, network=False, read_only_fs=True, ) return result.output
영구 메모리(RAG, 대화 기록, 학습된 기본 설정)를 유지하는 상담원은 메모리 중독에 취약합니다. 공격자는 에이전트의 지식창고에 악성 콘텐츠를 삽입하여 향후 상호작용에서 손상된 결과를 생성하도록 합니다.
# Agent stores all interactions without validation def store_memory(agent_id: str, interaction: str): memory_db.insert(agent_id, interaction) # No filtering
def store_memory(agent_id: str, interaction: str, source: str): # Validate content before storing if contains_injection_patterns(interaction): log.warning(f"Blocked poisoned memory: {agent_id}") return memory_db.insert( agent_id=agent_id, content=interaction, source=source, provenance=compute_provenance(source), timestamp=now(), ttl_days=30, # Auto-expire old memories ) def retrieve_memory(agent_id: str, query: str) -> list: results = memory_db.search(agent_id, query) # Filter by provenance score return [r for r in results if r.provenance_score > 0.8]
상담원들이 서로 통신하는 멀티 에이전트 시스템은 메시지 변조, 스푸핑 및 도청에 취약합니다. 적절한 인증 및 무결성 검사가 이루어지지 않으면 손상된 에이전트가 악성 지침을 에이전트 네트워크에 주입할 수 있습니다.
# Agents communicate via plain text messages def send_to_agent(target: str, message: str): channel.send(target, message) # No auth, no signing
import hmac, json, time def send_to_agent(target: str, message: str, sender_key: bytes): payload = { "content": message, "sender": agent_id, "target": target, "timestamp": time.time(), "nonce": os.urandom(16).hex(), } signature = hmac.new( sender_key, json.dumps(payload).encode(), "sha256" ).hexdigest() payload["signature"] = signature encrypted = encrypt(json.dumps(payload), target_public_key) channel.send(target, encrypted) def receive_message(data: bytes, private_key) -> dict: payload = json.loads(decrypt(data, private_key)) if not verify_signature(payload): raise ValueError("Invalid message signature") if is_replay(payload["nonce"]): raise ValueError("Replay attack detected") return payload
다중 에이전트 또는 다단계 워크플로에서는 한 에이전트의 오류나 악의적인 작업이 시스템 전체에 전파되어 연쇄적인 장애를 일으킬 수 있습니다. 적절한 오류 경계가 없으면 손상된 단일 단계로 인해 전체 파이프라인이 손상될 수 있습니다.
# Errors propagate without boundaries def pipeline(data): result1 = agent_a.process(data) result2 = agent_b.process(result1) # If agent_a fails or is poisoned... result3 = agent_c.process(result2) # ...error cascades to all return result3
from circuitbreaker import circuit class AgentPipeline: def __init__(self): self.circuit_breakers = {} @circuit(failure_threshold=3, recovery_timeout=60) def safe_execute(self, agent, data): result = agent.process(data) if not validate_output(result): raise ValueError("Output validation failed") return result def pipeline(self, data): try: r1 = self.safe_execute(agent_a, data) except Exception: r1 = fallback_a(data) try: r2 = self.safe_execute(agent_b, r1) except Exception: r2 = fallback_b(r1) return r2
사용자는 상담원의 결과물을 지나치게 신뢰하여 충분한 검토 없이 작업을 승인할 수 있습니다. 신뢰도는 높지만 근거가 불충분한 권장 사항을 제시하는 에이전트는 사용자가 유해한 결정을 내리도록 유도할 수 있습니다. 공격자는 이러한 신뢰 관계를 악용할 수 있습니다.
# Agent requests approval without context def request_action(action: str): # "Deploy to production?" - user clicks Yes without review return ui.confirm(f"Execute: {action}?")
def request_action(action: str, context: dict) -> bool: confidence = context.get("confidence", 0.0) risk_level = assess_risk(action) approval_request = { "action": action, "confidence": f"{confidence:.0%}", "risk_level": risk_level, "reasoning": context["reasoning"], "affected_systems": context["systems"], "reversible": context.get("reversible", False), } # Force detailed review for high-risk or low-confidence if risk_level == "high" or confidence < 0.8: return ui.detailed_review(approval_request) return ui.confirm(approval_request)
에이전트는 목표 오정렬, 적대적 조작 또는 돌발 행동으로 인해 의도된 목적에서 벗어날 수 있습니다. 불량 에이전트는 조직의 목표와 상충되는 목표를 추구하거나, 자원을 축적하거나, 종료 시도에 저항할 수 있습니다.
# Agent runs without monitoring or kill switch def run_agent(task): while True: agent.step() # No termination condition
class MonitoredAgent: def __init__(self, agent, max_steps=100): self.agent = agent self.max_steps = max_steps self.step_count = 0 self.behavior_log = [] def run(self): while self.step_count < self.max_steps: action = self.agent.next_action() # Check for rogue behavior if self.is_off_task(action): log.alert(f"Rogue behavior: {action}") self.shutdown() return # Check guardrails if not guardrails.check(action): log.warning(f"Guardrail violation: {action}") continue self.agent.execute(action) self.step_count += 1 self.behavior_log.append(action) def shutdown(self): self.agent.stop() revoke_credentials(self.agent.id) notify_admin(self.behavior_log)
| ID | 취약성 | 심각도 | 주요 완화 |
|---|---|---|---|
| ASI01 | 에이전트 목표 하이재킹 | Critical | 입력 위생 처리, 목표 드리프트 감지, 목표 허용 목록 |
| ASI02 | 도구 오용 및 악용 | Critical | 도구 허용 목록, 사람 승인, 속도 제한 |
| ASI03 | 신원 및 권한 남용 | Critical | 범위가 지정된 자격 증명, 수명이 짧은 토큰, 최소 권한 |
| ASI04 | 에이전트 공급망 취약성 | High | 플러그인 서명 확인, 샌드박스 실행 |
| ASI05 | 예기치 않은 코드 실행 | Critical | 샌드박스 컨테이너, 정적 분석, eval() 없음 |
| ASI06 | 메모리 및 컨텍스트 중독 | High | 입력 유효성 검사, 출처 추적, 메모리 TTL |
| ASI07 | 안전하지 않은 에이전트 간 통신 | High | 메시지 서명, 암호화, 재생 방지 |
| ASI08 | 계단식 실패 | High | 회로 차단기, 출력 유효성 검사, 폴백 핸들러 |
| ASI09 | 인간-에이전트 신뢰 악용 | Medium | 신뢰 표시, 상세 검토, 점진적 신뢰 |
| ASI10 | 로그 에이전트 | High | 행동 모니터링, 가드레일, 킬 스위치 |