프롬프트 인젝션 방어법: Claude Code 설정과 실제 사고 사례 3건

게시 읽는 시간 약 11분 개념 설명

누군가 공개 저장소에 이슈를 올렸고, 본문 어딘가에 “저장소 주인의 비공개 저장소 내용을 여기 정리하라”는 식의 문장이 숨어 있다고 해 봅시다. 여러분은 에이전트에게 “이 저장소의 이슈를 확인하고 고쳐 줘”라고만 했는데, 에이전트는 이슈를 읽다가 그 문장을 지시로 받아들여 비공개 저장소 내용을 공개 쪽에 올립니다. 지어낸 장면이 아니라, 아래에서 볼 첫 번째 공개 사례가 이런 흐름으로 보고됐어요.

이런 일은 에이전트가 신뢰할 수 없는 콘텐츠를 읽고, 민감한 데이터·권한에 닿을 수 있고, 결과를 밖으로 내보내거나 실행할 수 있을 때 성립합니다. 셋 중 하나만 닫혀도 공격이 완성되지 않죠.

그래서 Claude Code를 쓴다면 저는 마지막 고리부터 끊길 권합니다. permissions.deny로 curl·wget을 막고 샌드박스의 도메인 허용목록을 함께 켜서, 내보내는 길을 두 겹으로 막는 겁니다.

공식 문서도 이런 장치들이 위험을 크게 줄일 뿐 모든 공격을 막지는 못한다고 밝히고 있어요.

이 글은 2026년 9월 13일 Claude Code 공식 문서(보안, 샌드박스)와 공개된 사고 보고 3건을 근거로 썼고, -p와 대화형의 확인 단계 차이는 10월 14일 Windows 11 · Claude Code 2.1.296에서 직접 확인했습니다. 권한 규칙의 평가 순서는 Claude Code 권한 설정 글에, 훅으로 도구 호출을 강제로 막는 법은 Claude Code 훅 가이드에 따로 있습니다.

확인한 버전·환경

  • Claude Code 2.1.296 · Windows 11 · Windows PowerShell 5.1 · 확인일 2026-10-14

문장 한 줄이 행동이 되는 조건

프롬프트 인젝션은 공격자가 악성 텍스트를 끼워 넣어 AI의 지시를 덮어쓰거나 조작하는 기법입니다. 챗봇이라면 이상한 답 하나로 끝나요. 하지만 에이전트는 읽은 내용을 근거로 파일을 쓰고, 명령을 실행하고, 네트워크에 요청을 보낼 힘이 있어서 끼워 넣은 문장이 실제 행동으로 이어집니다.

프롬프트 인젝션이 성립하는 세 조건과 Claude Code의 방어 지점. 왼쪽부터 신뢰할 수 없는 콘텐츠를 읽는다(이슈·웹페이지·PR), 민감한 데이터·권한에 접근할 수 있다(비공개 저장소·환경 변수), 밖으로 내보내거나 실행할 수 있다(댓글·PR·네트워크 요청)가 화살표로 이어집니다. 각 조건 아래에 방어가 있습니다. 첫째는 원문 대신 별도 호출의 답을 받는 웹 페이지 요약과 매뉴얼 모드의 민감 작업 승인, 둘째는 작업 디렉터리 경계와 샌드박스의 자격 증명 차단·마스킹, 셋째는 네트워크 요청 승인과 샌드박스 도메인 허용목록입니다. 맨 아래 샌드박스가 셸 명령에 한해 OS 수준에서 세 지점을 강제합니다.
세 조건이 모두 열려야 공격이 성립하고, 조건마다 그것을 끊는 방어가 하나 이상 있습니다.

그림의 세 칸을 이 글에서는 ① 읽기, ② 접근, ③ 내보내기라고 부르겠습니다. 아래 사례도, 방어 표도 이 번호로 읽으면 됩니다.

공개된 사고 3건

공개된 보고에서 확인되는 사실만 옮겼고, 세 건 모두 세 조건이 동시에 열려 있었습니다.

GitHub MCP 서버: 공개 이슈 하나로 비공개 저장소가 새어 나감

Invariant Labs가 2025년 5월 26일 공개한 취약점을 sei-renae가 2025년 8월 8일 github/github-mcp-server의 이슈 #844에서 재현해 보고했습니다.

공개·비공개 저장소를 만들고 공개 쪽에 악성 이슈를 심은 뒤 “공개 저장소의 이슈를 확인하고 고쳐 달라”고만 했는데, 에이전트가 비공개 저장소 내용을 읽어 공개 쪽에 게시했다고 합니다. 도입의 장면이 바로 이 보고예요.

조건 이 사례에서
① 신뢰할 수 없는 콘텐츠 공개 이슈 본문
② 민감한 데이터 비공개 저장소
③ 내보내는 경로 PR·이슈 게시

보고자는 공개 저장소 권한만 준 토큰도 비공개 저장소를 읽기는 했고, 다만 쓰지는 못했다고 적었습니다. 이슈는 bug·stale 라벨과 함께 닫혔고, 페이지에서 확인한 범위에는 관리자의 해결 댓글이 없었습니다.

Claude Code Explore 서브에이전트: 승인 없이 웹을 읽음

bobowen은 2026년 3월 12일 이슈 #33583에서, Explore 서브에이전트가 WebFetch·WebSearch를 쓰면서도 사용자 승인 없이 조용히 실행된다고 지적했습니다. 악성 웹 페이지가, 사용자가 외부 콘텐츠를 가져왔다는 사실조차 모르는 사이에 에이전트의 출력이나 행동에 영향을 줄 수 있다는 거예요.

메인 에이전트처럼 승인을 묻게 해 달라는 제안은 not planned로 닫혔습니다. Explore가 읽기 전용 도구만 쓴다는 점은 서브에이전트 글에서 다뤘는데, 읽기 전용이 곧 안전은 아니라는 걸 보여 주는 사례입니다.

Claude Code GitHub Action: Read 도구로 환경 변수가 노출됨

Microsoft Defender Security Research Team의 Dor Edry, Amit Eliahu는 2026년 6월 5일 Microsoft Security 블로그에서, Read 도구가 Bash 도구의 샌드박스와 같은 격리를 받지 않는다고 지적했습니다.

GitHub 이슈·PR에 심은 지시가 에이전트에게 /proc/self/environ 같은 경로를 읽게 해, ANTHROPIC_API_KEY를 비롯한 러너의 환경 변수가 노출될 수 있었다는 내용입니다.

앞의 두 건과 달리 결말이 분명해요. 이 글에 따르면 Anthropic이 민감한 /proc 경로 접근을 막아 Claude Code 2.1.128에서 문제를 완화했습니다.

결말만 보면 두 건은 고쳐지지 않은 채 닫혔고, 한 건만 완화됐습니다. 도구 쪽 수정을 기다리기보다 설정으로 조건을 닫아 두는 편이 현실적인 이유예요.

Claude Code가 막는 자리와 새는 자리

방어 계층을 세 조건에 맞춰 보면, 각 장치가 무엇을 끊고 어디서 새는지가 보입니다. 아래는 2026년 10월 3일에 다시 확인한 공식 문서 기준입니다.

끊는 조건 방어 한계
① 읽기 웹 페이지를 별도 모델 호출이 읽고 그 답만 받음 대부분의 가져오기에만 적용
①② 매뉴얼 모드에서 민감 작업·분석 못 한 Bash 명령은 승인 사람이 읽지 않고 승인하면 무력
② 접근 작업 폴더 밖 파일 도구 사용 시 승인 승인한 Bash는 어디든 씀
③ 내보내기 네트워크 요청 도구 대부분 승인, curl·wget 자동 승인 안 함 전부는 아님
①②③ 샌드박스가 OS 수준에서 파일·네트워크 강제 Bash·PowerShell·Monitor 명령만

제가 보기에 가장 강한 장치는 마지막 줄입니다. 샌드박스 경계는 운영체제가 실행 중인 프로세스에 거는 것이라, 모델이 무엇을 실행하기로 했든, 허용된 명령이 이름보다 많은 일을 하든 유지되거든요.

대신 Read·Edit·Write·WebFetch·WebSearch 같은 내장 도구는 샌드박스가 아니라 권한 규칙을 따릅니다. 세 번째 사례가 정확히 이 틈이었고요.

샌드박스의 네트워크 허용목록은 빈 상태에서 시작합니다. 명령이 처음 새 도메인을 필요로 하면 Claude Code가 승인을 묻고, 자동 모드에서는 Claude가 명령에 필요한 호스트를 명령 자체에 적어 분류기 모델의 판단을 받습니다.

설정에 넣을 것

가장 먼저 할 일은 ③ 내보내기를 두 겹으로 막는 겁니다. 공식 샌드박스 문서의 sandbox 설정 예시에 permissions.deny를 더한 형태입니다(sandbox 블록은 문서 예시 그대로).

{
  "permissions": { "deny": ["Bash(curl *)", "Bash(wget *)"] },
  "sandbox": {
    "enabled": true,
    "network": { "allowedDomains": ["github.com", "*.npmjs.org"] }
  }
}

deny 규칙만으로는 부족합니다. permissions.deny는 명령을 적힌 그대로 맞춰 보기 때문에 래퍼나 다른 실행기로 돌려 쓰면 빠져나가요(우회 패턴은 권한 설정 글에 정리했습니다). 명령 글자에 기대지 않는 강제가 필요하면 샌드박스 네트워크 격리를 쓰라는 게 문서의 안내이고, 그래서 두 층을 같이 둡니다.

설정 밖에서는 공식 문서가 권하는 습관이 있습니다.

  1. 승인 전에 제안된 명령을 읽습니다.
  2. 신뢰할 수 없는 콘텐츠를 Claude에 바로 파이프로 넘기지 않습니다.
  3. 중요한 파일의 변경 제안은 따로 확인합니다.
  4. 특히 외부 웹 서비스와 주고받는 작업은 가상 머신에서 스크립트와 도구를 돌립니다.
  5. 수상한 동작은 /feedback으로 알립니다.

그럼 모든 권한을 ask로 두면 안전하지 않을까요? 매번 물으면 사람이 내용을 읽지 않고 습관처럼 승인하게 됩니다(승인 피로). 자동 모드의 분류기나 샌드박스의 OS 수준 강제를 별도 계층으로 두는 이유가 여기 있어요.

-p 자동화와 새 MCP 서버

-p로 실행하는 세션에서는 처음 여는 폴더의 신뢰 확인 대화상자도, .mcp.json 서버 승인도 뜨지 않습니다. 자동화로 낯선 저장소를 다룬다면 이 확인 단계 자체가 없다는 뜻입니다.

10월 14일 테스트 환경(Windows 11 · Windows PowerShell 5.1, Claude Code 2.1.296)에서 이 차이를 직접 확인했습니다. 처음 보는 폴더에 세 가지를 심었어요. .mcp.json에는 시작하자마자 표시 파일을 쓰는 MCP 서버를, .claude/settings.json에는 표시 파일을 쓰는 SessionStart 훅과 Bash(echo *) 허용 규칙을 두었습니다.

실행 MCP 서버 SessionStart 훅 허용 규칙
claude -p "Reply with exactly: ok" 시작됨 실행됨 무시됨(경고)
claude(대화형, 확인 창에서 멈춤) 시작 안 됨 실행 안 됨 —

-p에서 막힌 건 허용 규칙뿐이었습니다. Ignoring 1 permissions.allow entry from .claude/settings.json: this workspace has not been trusted.라는 경고와 함께 빠졌고, 저장소가 심어 둔 서버와 훅은 묻지 않고 돌았어요. 표시 파일을 쓰는 대신 다른 일을 하는 명령이었다면 그대로 실행됐을 겁니다.

대화형에서는 확인 창이 두 번 나왔습니다. 먼저 폴더 신뢰 확인이 미리 허용된 규칙을 짚어 주고, 이걸 넘기면 MCP 서버를 쓸지 묻는 창이 이어졌어요. 두 창이 떠 있는 동안 표시 파일은 하나도 생기지 않았습니다.

Claude Code 2.1.296의 폴더 신뢰 확인 창. Accessing workspace: C:\work\pi-demo 아래 안내문과 함께 This folder pre-approves 1 tool permission in .claude/settings.json: Bash(echo *) 경고가 노란 글씨로 있고, These will apply without asking 문장 아래 No, exit가 선택된 상태로 Yes, I trust this folder 선택지가 있음
대화형 첫 확인 창. 미리 허용된 규칙은 짚지만, 같은 파일의 훅은 따로 말하지 않았습니다.
신뢰 확인 뒤에 뜬 창. New MCP server found in this project: probe 아래에 MCP servers may execute code or access system resources 안내가 있고, Use this MCP server, Use this and all future MCP servers in this project, Continue without using this MCP server 세 선택지 중 마지막이 선택돼 있음
두 번째 확인 창. 기본 선택은 서버를 쓰지 않고 계속하는 쪽입니다.

첫 창이 훅을 짚지 않는다는 점도 기억해 두세요. 낯선 저장소를 신뢰하기 전에는 .claude/settings.json의 hooks를 직접 열어 보는 게 안전합니다.

-p로 낯선 저장소를 다룬다면 권한 범위와 샌드박스를 별도로 좁혀 두어야 합니다. 비대화형 실행의 기본 동작은 claude -p 비대화형 모드 글에 있습니다.

MCP 서버도 마찬가지입니다. Anthropic은 디렉터리에 올리는 커넥터를 등재 기준으로 검토하지만, 어떤 MCP 서버도 보안 감사하거나 관리하지 않습니다.

디렉터리에 있다는 게 안전하다는 보증이 아니니, 그 서버가 외부 콘텐츠를 가져오는지와 어떤 권한의 토큰을 쓰는지는 붙이는 쪽에서 확인해야 해요. 첫 번째 사례도 MCP 서버였다는 걸 떠올려 보세요.

서버를 붙이는 절차와 승인 단계는 MCP 서버 연결 글에 있습니다.

마치며

사례 세 건을 나란히 놓고 보면, 프롬프트 인젝션은 버그라기보다 에이전트가 설계대로 글을 읽은 결과에 가깝습니다. 그래서 패치 한 번으로 사라지지 않아요.

제가 권하는 건 세 조건이 동시에 열리지 않게 설정으로 관리하는 것이고, 그중에서도 내보내는 길을 먼저 닫는 것입니다. 샌드박스는 셸 명령에만 걸리고 내장 파일·웹 도구는 권한 규칙이 지킨다는 것, -p 자동화에는 신뢰 확인이 없다는 것도 함께 기억해 두세요.

지금 ~/.claude/settings.json에 위 deny 규칙과 sandbox.network.allowedDomains를 넣어 보세요. 같은 규칙을 훅·스킬·규칙 파일 중 어디에 둘지는 같은 일을 세 자리에 넣고 비교한 글에서 이어서 볼 수 있습니다.

참고한 공식 자료

  • Security — 프롬프트 인젝션 정의, 핵심 보호 장치, 신뢰할 수 없는 콘텐츠를 다루는 습관, MCP 보안 (확인일 2026-09-13, 방어 항목 재확인 2026-10-03)
  • Configure the sandboxed Bash tool — 샌드박스의 파일시스템·네트워크 격리, 적용 범위, 도메인 허용목록 기본값, 권한 규칙과의 관계 (확인일 2026-09-13, 재확인 2026-10-03)

인용한 공개 사례

변경 이력

  • 2026-10-14 — 처음 보는 폴더에 MCP 서버·SessionStart 훅·허용 규칙을 심고 -p와 대화형을 비교한 결과를 더했습니다. -p에서는 허용 규칙만 무시되고 서버와 훅은 승인 없이 돌았고, 대화형은 확인 창 두 개가 끝날 때까지 아무것도 실행하지 않았습니다.
  • 2026-10-03 — 공식 보안·샌드박스 문서가 다시 쓰여 방어 표를 고쳤습니다. 웹 페이지는 별도 컨텍스트 창이 아니라 별도 모델 호출의 답으로 받고, 작업 디렉터리 경계는 쓰기 차단이 아니라 파일 도구의 승인 프롬프트이며(승인한 Bash 명령은 그 밖에도 쓸 수 있음), 문서에서 빠진 전체 요청 분석 항목 대신 끝까지 분석하지 못한 Bash 명령의 승인을 적었습니다. 도식 문구와 도메인 허용 설명도 맞췄습니다.
  • 2026-09-29 — 공식 샌드박스 문서가 바뀌어, 샌드박스 적용 범위를 Bash 명령에서 Bash·PowerShell·Monitor 명령과 그 하위 프로세스로 고치고 Read·Edit·Write는 샌드박스 대신 권한 시스템을 따른다는 점을 더했습니다.