AI 에이전트 보안: 프롬프트 내부가 아닌 외부에서 경계 설정하기
요약
LLM 에이전트 보안 위협인 프롬프트 주입(Prompt injection)에 대응하기 위해 아키텍처적 접근 방식이 필요합니다. 모델의 지침만으로는 부족하며, 기능 범위 설정, 정책 게이트 구현, 샌드박스 실행 등 다층적인 방어 로직을 코드로 강제해야 합니다.
핵심 포인트
- 과도한 자격 증명(Over-provisioned credentials)은 최소 권한 원칙으로 제한해야 합니다.
- 에이전트의 모든 자격 증명은 전용 ID로 교체하고 접근 범위를 구체화해야 합니다.
- 모델이 제안하는 도구 호출은 스키마 검증 및 정책 평가를 거쳐야 합니다.
- Open Policy Agent (OPA)와 같은 정책 엔진을 사용하여 실행 전에 호출을 검증할 수 있습니다.
프롬프트 주입(Prompt injection)은 LLM 애플리케이션의 OWASP Top 10 최상단에 위치하며 (LLM01), 어떤 시스템 프롬프트도 이를 확실하게 막을 수 없습니다. 만약 에이전트의 유일한 방어선이 '절대 파일을 삭제하지 마라'와 같은 문장이라면, 그것은 경계(boundary)가 아니라 단순한 제안에 불과합니다. 해결책은 아키텍처적인 접근입니다. 모델을 신뢰할 수 없는 플래너로 취급하고, 모델이 말만으로 우회할 수 없는 결정론적 코드(deterministic code)에 강제 로직을 구현해야 합니다. 이 글에서는 네 가지 계층—기능 범위 설정(capability scoping), 모든 도구 호출에 대한 정책 게이트(policy gate), 샌드박스 실행(sandboxed execution), 그리고 CI에서 실행할 수 있는 검증(verification)—을 다룹니다.
정책 작성 전에 기능 범위를 설정하라
대부분의 에이전트 사고는 과도하게 부여된 자격 증명(over-provisioned credentials)에서 비롯됩니다. 데이터베이스 사용자가 테이블 삭제 권한을 가지고 있기 때문에, 에이전트는 프로덕션 테이블을 삭제할 수 있습니다. 하지만 oWASP는 이를 LLM06, 과도한 에이전시(Excessive Agency)라고 부르며, 해결책은 구식의 최소 권한 원칙(least privilege)입니다. 해결책은 구체적이어야 합니다. 에이전트에게 개발자의 토큰이 아닌, 자체적인 ID를 부여해야 합니다. Postgres의 경우, 작업에 필요한 정확한 권한만을 가진 역할을 생성합니다:
CREATE ROLE support_agent LOGIN PASSWORD '...';
GRANT SELECT ON orders, customers TO support_agent;
GRANT UPDATE (status) ON orders TO support_agent;
...
GitHub에도 동일한 규칙을 적용하여, 단일 리포지토리에만 제한된 세밀한 개인 접근 토큰(fine-grained personal access token)이나 GitHub App을 사용합니다. AWS의 경우, 와일드카드 없이 특정 버킷 ARN에 대한 s3:GetObject와 같은 구체적인 작업을 나열하는 IAM 역할을 사용합니다. 자격 증명이 어떤 행동을 수행할 수 없다면, 주입된 지침이 에이전트가 그 행동을 하도록 만들 수 없습니다. 핵심 요약: 오늘날 에이전트가 보유한 모든 자격 증명을 목록화하고, 공유되거나 관리자 범위의 토큰은 에이전트가 접촉하는 정확한 리소스에 제한된 전용 ID로 교체해야 합니다.
모델과 모든 도구 사이에 정책 게이트를 두어라
자격 증명(Credentials)은 외부 벽을 만듭니다. 그 내부에서도 여전히 호출별 결정이 필요합니다. 환불 도구는 일반적으로 허용될 수 있지만, 에이전트가 인간의 개입 없이 5,000달러를 환불하는 것은 원치 않을 수 있습니다. 모델은 구조화된 JSON으로 도구 호출을 제안합니다. 귀하의 코드가 무언가를 실행하기 전에 이를 검증합니다. 유용한 분할 방식은 다음과 같습니다:
- 스키마 검증(Schema validation). Pydantic이나 Zod를 사용하여 인수를 구문 분석하고 알 수 없는 필드는 거부합니다. 수정하려고 시도하는 대신 잘못된 호출을 거부해야 합니다. 2. 정책 평가(Policy evaluation). 호출, 사용자 컨텍스트, 세션 상태를 정책 엔진으로 보냅니다. Rego를 사용하는 Open Policy Agent (OPA)가 잘 작동하는데, 이는 정책이 버전 관리되고 테스트 가능하기 때문입니다. AWS Cedar도 견고한 대안입니다. 3. 에스컬레이션(Escalation).
allow,deny, 또는require_approval중 하나의 결정을 반환합니다. 마지막 결정은 인간의 대기열로 라우팅합니다. 최소한의 Rego 규칙:
package agent.tools
default decision := "deny"
...
가장 중요한 것은 verified_orders 확인입니다. 이는 행동을 모델이 우연히 언급한 데이터가 아니라 _사용자_가 권한을 가진 데이터에 연결합니다. 이를 통해 지원 티켓의 주입된 텍스트가
- Docker와 강화(hardening) 플래그 사용. 최소한 다음 명령을 사용하세요:
docker run --rm --network=none --read-only --cap-drop=ALL --pids-limit=128 --memory=512m --user 1000:1000 agent-sandbox. - gVisor (--runtime=runsc). 사용자 공간 커널(user-space kernel)을 추가하여 시스템 호출 공격 표면적(syscall attack surface)을 축소합니다. - Firecracker 마이크로VM. 이는 AWS Lambda의 기반 기술이며, 빠른 부팅 시간과 함께 VM 수준의 격리(isolation)를 제공합니다. E2B와 같은 호스팅 서비스가 이를 기반으로 구축됩니다. 데이터 유출(data exfiltration)은 네트워크 이그레스(Network egress)에서 발생합니다. 일반적인 패턴 중 하나는 에이전트에게 공격자의 도메인으로 비밀 정보(secrets)를curl하도록 지시하는 주입된 명령어입니다. 기본적으로--network=none을 사용하세요. 에이전트가 네트워크 액세스가 필요할 때는, 도메인 허용 목록(domain allowlist)이 있는 이그레스 프록시(egress proxy)를 통해 라우팅합니다. Squid나 Envoy 모두 사용할 수 있습니다. 핵심 요약: 오늘 바로 에이전트의 코드 실행 도구를--network=none및--cap-drop=ALL로 실행하세요. 그런 다음, 문제가 발생하는 접근만 다시 추가하십시오.
규칙을 한 번이 아닌 지속적으로 검증하기
도구를 추가할수록 정책은 무너집니다(Policies rot). 에이전트 경계(agent boundaries)를 다른 보안 제어 장치와 마찬가지로 취급하세요: 테스트하고, 로깅하고, 공격해야 합니다. 정책 단위 테스트. CI에서 opa test ./policies -v를 실행합니다. 행복한 경로(happy path)뿐만 아니라 모든 거부(deny) 사례에 대한 테스트를 작성하십시오. 실제 도구를 사용한 레드팀 활동. Promptfoo에는 프롬프트 주입 및 과도한 에이전시(excessive agency)에 대한 레드팀 플러그인이 있습니다. NVIDIA의 Garak는 알려진 탈옥(jailbreak) 클래스에 대해 모델을 탐지합니다. 이 둘 중 하나를 도구와 연결된 전체 에이전트에 대해 실행하십시오. 베어 모델만 테스트하는 것은 중요한 실패 사례들을 놓치게 만듭니다. 모든 결정 기록. 각 도구 호출에 대해 제안된 호출, 정책 결정, 정책 버전 및 결과를 기록하세요. 무언가 잘못되었을 때, 정책이 허용했는지 아니면 에이전트가 게이트를 우회했는지 알아야 합니다. deny 이벤트의 급증은 활성 주입 시도(active injection attempt)의 초기 신호일 수도 있습니다. 카나리 테스트. 문서에 가짜 비밀 정보, 예를 들어 미끼 API 키(decoy API key)를 심고, 이것이 도구 인자나 아웃바운드 요청에 나타날 경우 경고하도록 설정하십시오.
핵심 요약: 프롬프트, 도구 또는 정책 변경 시마다 정책 테스트와 최소한 하나의 주입(injection) 테스트 스위트를 실행하는 CI 작업을 추가하세요. 오늘 당장 한 가지 조치부터 시작하세요: 에이전트가 호출할 수 있는 가장 위험한 단일 도구를 찾으세요. 이 도구가 삭제, 결제, 전송 또는 배포를 하든 상관없이 말입니다. 이를 기본 거부(default-deny) 검사를 통과하도록 코드로 구현하고, 임계값을 설정하여 require_approval을 반환하게 만드세요. 그 하나의 게이트가 가장 위험했던 프롬프트 수준의 기대를 강제된 경계로 바꿀 것입니다.
이 글은 AI의 도움을 받아 작성되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기