목차
RAG 에이전트는 외부 문서를 검색해 답변을 생성하는 특성상 기본 챗봇보다 공격 표면이 넓다. 검색된 문서 자체에 악성 지침이 포함될 수 있고, 사용자가 시스템 프롬프트를 탈취하려 시도할 수 있다. 이 글에서는 Viget의 RAG 에이전트 보안 구현 사례를 바탕으로 기본·심화 보안 전략을 정리한다.
기본 보호: 프롬프트 필터링
입력을 에이전트에 전달하기 전에 악성 패턴을 사전 필터링한다.
import re
from dataclasses import dataclass
@dataclass(frozen=True)
class PromptFilterResult:
safe: bool
reason: str | None = None
_PATTERNS: list[tuple[re.Pattern[str], str]] = [
(
re.compile(
r"\b(ignore|disregard|forget|override)\s+"
r"(?:(?:your|all|the|any|previous|prior|earlier|above|preceding)\s+){1,3}"
r"(instructions?|rules?|prompts?|system\s+prompt|directives?)",
re.IGNORECASE,
),
"instruction-override phrase",
),
(
re.compile(
r"\b(reveal|show|print|tell|repeat|output|leak|dump|expose|share)\s+"
r"(me\s+)?(your|the)\s+"
r"(system\s+prompt|instructions?|rules?|directives?|initial\s+prompt)",
re.IGNORECASE,
),
"request to reveal system prompt",
),
]
def filter_prompt(user_input: str) -> PromptFilterResult:
for pattern, reason in _PATTERNS:
if pattern.search(user_input):
return PromptFilterResult(safe=False, reason=reason)
return PromptFilterResult(safe=True)이 필터를 에이전트 호출 전에 실행해, 악성으로 판단된 입력은 에이전트에 전달하지 않는다.
심화 보호: AWS Bedrock Guardrail
인프라 레이어에서 더 강력한 가드레일을 적용한다. Bedrock Guardrail은 유해 콘텐츠 차단, 프롬프트 인젝션 탐지, PII 익명화를 서비스 수준에서 제공한다.
가드레일 생성
import boto3
bedrock = boto3.client("bedrock")
response = bedrock.create_guardrail(
name="rag-agent-guardrail",
contentPolicyConfig={
"filtersConfig": [
{"type": "SEXUAL", "inputStrength": "HIGH", "outputStrength": "HIGH"},
{"type": "VIOLENCE", "inputStrength": "HIGH", "outputStrength": "HIGH"},
{"type": "HATE", "inputStrength": "HIGH", "outputStrength": "HIGH"},
{"type": "MISCONDUCT", "inputStrength": "HIGH", "outputStrength": "HIGH"},
]
},
sensitiveInformationPolicyConfig={
"piiEntitiesConfig": [
{"type": "EMAIL", "action": "ANONYMIZE"},
{"type": "PHONE", "action": "ANONYMIZE"},
{"type": "SSN", "action": "BLOCK"},
{"type": "CREDIT_DEBIT_CARD_NUMBER", "action": "BLOCK"},
]
},
promptAttackPolicyConfig={
"filtersConfig": [{"type": "PROMPT_ATTACK", "inputStrength": "HIGH"}]
},
)
guardrail_id = response["guardrailId"]
guardrail_version = response["version"]
print(f"Guardrail ID: {guardrail_id}, Version: {guardrail_version}")에이전트에 적용
import os
def build_model_settings() -> BedrockModelSettings:
settings: dict = {"max_tokens": 4096}
guardrail_id = os.getenv("BEDROCK_GUARDRAIL_ID")
guardrail_version = os.getenv("BEDROCK_GUARDRAIL_VERSION")
if guardrail_id and guardrail_version:
settings["guardrail"] = {
"guardrailIdentifier": guardrail_id,
"guardrailVersion": guardrail_version,
}
else:
raise ValueError(
"Bedrock guardrail not applied: both BEDROCK_GUARDRAIL_ID and "
"BEDROCK_GUARDRAIL_VERSION must be set."
)
return BedrockModelSettings(**settings)주요 위협과 대응 전략
| 위협 유형 | 설명 | 대응 |
|---|---|---|
| 프롬프트 인젝션 | “이전 지침을 무시하고 X를 해라” | 입력 필터링 + Bedrock 프롬프트 공격 차단 |
| 시스템 프롬프트 탈취 | “시스템 프롬프트를 보여줘” | 입력 필터링으로 사전 차단 |
| 문서 오염 | 검색된 문서 내 악성 지침 | 문서 소스 검증 + 출력 모니터링 |
| PII 유출 | 민감 정보 노출 | Bedrock PII 익명화·차단 |
| 유해 콘텐츠 생성 | 폭력·혐오 출력 | Bedrock 콘텐츠 정책 필터 |
보안 레이어 설계 원칙
- 입력 레이어: 명백한 악성 패턴을 에이전트 도달 전에 차단한다
- 인프라 레이어: Bedrock Guardrail처럼 서비스 레이어에서 광범위한 정책을 적용한다
- 출력 레이어: 에이전트 응답을 배포 전에 검토하는 단계를 추가한다
단일 레이어에 의존하지 않고 여러 레이어를 겹쳐 적용하는 심층 방어(defense in depth) 원칙이 핵심이다.
누가 읽으면 좋은가
- RAG 챗봇이나 문서 기반 Q&A 에이전트를 프로덕션에 배포하는 팀
- 고객 대면 AI 서비스에서 보안 리스크를 줄이려는 엔지니어
- AWS 기반 AI 인프라에서 Bedrock Guardrail 도입을 검토하는 아키텍트
관련 문서
- rag — RAG 기본 개념
- ai-agent-security-tips-docker-sandbox — AI 에이전트 보안 샌드박스 구성
- pii-proxy — LLM 호출 전 개인정보를 로컬에서 마스킹하는 미들웨어
참고 자료
- Protecting Your RAG Agent — Viget (2026-06-09)