
MCP를 연결한다는 것은 기능을 추가하는 것이 아니다. 에이전트에게 손을 부여하고, 모르는 누군가에게 입구를 넘겨주는 것이다
요약
MCP(Model Context Protocol)를 통해 에이전트에게 도구를 연결하는 것은 단순한 기능 추가를 넘어 권한을 부여하는 행위임을 경고합니다. 특히 간접 프롬프트 인젝션(Indirect Prompt Injection)을 통한 데이터 유출 위험과 이를 방지하기 위한 보안 전략을 다룹니다.
핵심 포인트
- MCP 연결은 에이전트에게 새로운 '손'과 '입구'를 제공하는 권한 부여 과정임
- 도구 출력값에 포함된 지시문이 에이전트의 행동을 조종하는 간접 프롬프트 인젝션 위험 존재
- 비밀 접근, 신뢰할 수 없는 입력 읽기, 외부 전송 경로가 결합될 때 데이터 유출 발생
- 도구 설명문 자체도 프롬프트의 일부이므로 신뢰할 수 있는 서버만 연결해야 함
- 권한 최소화 원칙(Least Privilege)과 업데이트 시 변경 사항 확인이 필수적임
에이전트에게 GitHub의 Issue를 읽게 하고 있었을 때의 일입니다.
"이 버그 보고를 읽고 대응해줘"라고 부탁했습니다. 흔히 있는 작업입니다. 그런데, 만약 그 Issue 본문의 끝에 이런 문장이 섞여 있었다면 어떻게 될까요?
(Issue 본문)
버그 보고입니다. 재현 절차는…
---
...
저는 아무런 잘못을 하지 않았습니다. 그저 "Issue를 읽어줘"라고 부탁했을 뿐입니다. 하지만 도구가 가져온 문자열 속에 에이전트에 대한 지시가 섞여 있었습니다. 그리고 에이전트는 그 문자열을 읽고 다음에 무엇을 할지 결정합니다. 그 지시에 따라버릴 가능성이 여기에 있습니다.
MCP를 연결한다는 것은 바로 이런 것이라는 사실을 뒤늦게 깨달았습니다. 기능을 추가하고 있다고 생각했지만, 실제로는 권한을 넘겨주고 있었습니다. 손이 늘어나는 것과 동시에, 모르는 누군가가 들어올 수 있는 입구도 늘어나고 있었던 것입니다.
이전에 이를 영어로 썼을 때 제 글에 가장 많은 댓글이 달렸습니다. 그만큼 모두가 막연하게나마 걱정하고 있는 이야기라고 생각합니다. MCP가 실험 단계에서 구현 표준으로 넘어가고 있는 지금, 일본어로도 적어둡니다.
라이브러리를 추가하는 것과는 다르다
일반적인 라이브러리를 추가하는 것과 MCP를 연결하는 것은 성질이 다릅니다.
라이브러리는 내가 작성한 코드에서 호출됩니다. 호출하는 곳도, 전달하는 값도 우리가 결정합니다. 하지만 MCP 도구는 에이전트가 자신의 판단으로 호출합니다. 언제 호출할지, 무엇을 전달할지를 결정하는 것은 우리가 아니라 모델입니다.
그리고 에이전트는 도구의 출력을 읽고 다음 행동을 결정합니다. 이 점이 앞서 말한 Issue 이야기로 이어집니다. 도구가 반환한 문자열에 지시와 같은 문장이 섞여 있다면, 에이전트는 그것을 읽습니다. 읽은 뒤에 그 지시를 따를 수도 있습니다. 외부에서 온 문자열이 그대로 행동으로 변하는 것. 이것이 바로 간접적 프롬프트 인젝션 (Indirect Prompt Injection)이라 불리는 것입니다.
갖춰지면 빠져나가는, 3가지 조합
무서운 것은 단일 도구가 아니라 조합이었습니다. 다음 세 가지가 갖춰지면 데이터는 외부로 유출됩니다.
비밀에 접근할 수 있는 것. 신뢰할 수 없는 문자열을 읽는 것. 외부로 내보낼 수 있는 경로가 있는 것.
파일을 읽을 수 있는 도구, Issue나 웹을 읽는 도구, 그리고 HTTP 요청을 보낼 수 있는 도구. 각각 단독으로는 편리할 뿐입니다. 하지만 동일한 세션에 이 세 가지가 갖춰지면, 앞선 예시처럼 "읽고, 지시를 받고, 보낸다"가 하나의 선으로 연결되어 버립니다.
그래서 저는 우선 이 세 가지가 동시에 성립하는지를 확인합니다. 전부 버릴 필요는 없습니다. 그중 하나만 제거해도 선은 끊어집니다. 외부로 내보낼 수 있는 도구를 제거한다. 신뢰할 수 없는 입력을 읽게 하지 않는다. 비밀에 닿지 않도록 한다. 이 중 하나만 해도 됩니다.
연결하기 전에 확인해야 할 것
MCP 서버를 추가할 때 제가 확인하는 부분은 다음과 같습니다.
먼저, 어떤 도구가 생기는가. 서버를 연결하면 도구 목록이 에이전트의 컨텍스트 (Context)에 올라갑니다. 여기서 놓치기 쉬운 점은 도구의 설명문 또한 프롬프트 (Prompt)의 일부라는 것입니다. 설명에 이상한 지시가 적혀 있다면 모델은 그것을 읽습니다. 제작자를 신뢰할 수 없는 서버는 연결하는 시점에서 이미 패배한 것입니다.
다음으로, 권한을 제한할 수 있는가. 많은 서버는 토큰이나 계정 연동을 요구합니다. 읽기 권한만으로 충분하다면 쓰기 권한은 주지 않습니다. 리포지토리 전체가 아니라 필요한 하나로 범위를 좁힙니다. 이는 서버 측의 구현이라기보다, 전달할 토큰을 만드는 방식에 관한 문제입니다.
그리고, 업데이트로 무엇이 변하는가. 오늘 안전했던 서버가 내일의 업데이트로 도구를 늘릴지도 모릅니다. 버전을 고정할 수 있다면 고정하고, 업데이트할 때는 차이점(diff)을 확인합니다. 이 번거로움은 솔직히 고달픕니다. 하지만 커뮤니티 제작 서버를 아무 확인 없이 계속 업데이트하는 것은, 타인의 코드에 내 환경의 열쇠를 계속 맡겨두는 것과 같았습니다.
수동으로 수행하는 방어
완벽하게 할 수는 없기에, 제 환경 측에서도 그물을 칩니다.
// ~/.claude/settings.json
{
"permissions": {
...
파괴하거나 유출하는 계열의 커맨드는 미리 막아둡니다. 에이전트가 선의로 실행하려는 상황에서도 여기서 멈추게 됩니다.
그 위에서 효과를 보고 있는 것은 세션을 분리하는 것이었습니다. 신뢰할 수 없는 문자열을 읽는 작업(Issue 조사, 웹 서핑)과 비밀에 접근하는 작업을 동일한 세션에서 수행하지 않습니다. 앞서 말한 3종 세트가 갖춰지지 않도록 시간적으로 분리합니다. 소박하지만 가장 효과적입니다.
파괴적인 작업에는 승인 단계를 거친다. 전부 자동으로 실행하고 싶은 마음은 굴뚝같지만, 삭제·전송·공개 이 세 가지만큼은 인간이 한 번 확인한다. 이 부분을 자동화해서 얻는 여유 시간보다, 사고가 났을 때 잃게 될 시간이 아마 더 클 것이다.
결국, 폼(Form) 입력과 같았다
나는 플러그인 개발을 할 때, LLM의 응답을 그대로 화면에 출력했다가 낭패를 본 적이 있다. 사용자 입력은 의심하면서, 그것을 LLM에 통과시켰을 뿐인 출력은 왜인지 신뢰해 버린다. 이를 이중 신뢰(Double Trust) 문제라고 부른다.
MCP는 이것이 한 단계 더 깊어진 형태였다. 도구(Tool)의 출력을 에이전트(Agent)가 읽는다. 읽은 내용에 따라 다음 행동을 결정한다. 즉, 도구의 출력은 모델에게 있어 입력(Input)이다. 서두에 언급한 이슈가 바로 그것이었다.
따라서 마음가짐은 폼 입력을 받을 때와 다르지 않다. 어떤 곳에서 온 문자열인가. 그것이 무엇으로 변할 것인가. 이 두 가지를 본다. 신뢰할 수 있는 출처란 기본적으로 없다는 전제하에 다룬다. 새로운 기술 같아 보이지만, 해야 할 일은 예전부터 해오던 것과 같았다.
다음의 나에게 남기는 메모
- MCP를 연결한다는 것은 기능 추가가 아니라 권한의 부여다. 손과 입구는 세트로 늘어난다.
- 에이전트는 도구의 출력을 읽고 움직인다. 출력에 섞여 들어온 지시를 따를 수도 있다.
- 「비밀에 접근·신뢰할 수 없는 문자열을 읽음·외부로 내보낼 수 있음」이 모두 갖춰지면 뚫린다. 이 중 하나는 반드시 제외한다.
- 도구의 설명문(Description)도 프롬프트(Prompt)다. 제작자를 신뢰할 수 없는 서버는 연결하는 시점에서 이미 패배한 것이다.
- 토큰(Token)은 읽기 전용으로 제한하거나 대상을 좁혀서 전달한다. 업데이트의 차이점(Diff)을 확인한다.
deny를 통해 파괴적인 계열의 작업을 차단한다. 파괴적인 작업에는 승인을 거친다. 신뢰할 수 없는 입력과 비밀은 세션을 분리한다.
MCP는 편리하다. 나도 사용하고 있다. 다만, 연결할 때마다 "이 손으로 무엇을 할 수 있게 되는가"를 한 번 더 생각하게 되었다. 손이 늘어나는 것은 기쁜 일이다. 다만 그 손이, 나 이외의 누군가가 하는 말도 들을 수 있을지도 모른다는 이야기일 뿐이다.
평소에는 raplsworks.com에서 WordPress 플러그인 개발이나 Claude Code 주변의 이야기를 쓰고 있다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기