MCP 보안 체크리스트: OAuth confused deputy와 도구 권한 사고를 막는 방법
요약: MCP 공식 보안 문서는 confused deputy 문제, OAuth 흐름, 동적 클라이언트 등록, 사용자 동의 우회 같은 위험을 구체적으로 다룹니다. MCP 서버를 붙이는 팀은 “LLM이 우리 툴을 잘 호출한다”보다 “누가 어떤 권한으로 어떤 툴을 호출했는지 증명할 수 있는가”를 먼저 봐야 합니다.
MCP가 편해질수록 권한 경계가 중요해진다
Model Context Protocol, 즉 MCP는 에이전트와 외부 도구를 연결하는 표준 인터페이스로 빠르게 퍼졌습니다. 파일 시스템, GitHub, Slack, Notion, 데이터베이스, 내부 API를 모델이 다룰 수 있게 해 줍니다. 문제는 연결이 쉬워질수록 권한 사고도 쉬워진다는 점입니다.
MCP 서버는 단순한 플러그인이 아닙니다. 사용자의 토큰으로 외부 API를 호출하거나, 조직 내부 시스템에 접근하거나, 파일을 읽고 쓸 수 있습니다. 따라서 MCP 보안은 프롬프트 인젝션만의 문제가 아닙니다. OAuth, 세션, redirect_uri, consent, tenant isolation, audit log가 모두 얽힌 애플리케이션 보안 문제입니다.
공식 MCP 보안 문서는 confused deputy 문제를 대표 위험으로 설명합니다. 특히 MCP proxy server가 third-party API에 연결되고, static client ID와 dynamic client registration, consent cookie가 함께 쓰일 때 사용자 동의가 우회될 수 있는 시나리오를 제시합니다. 실무에서는 이 구조를 이해하지 못한 채 MCP 서버를 붙이면 토큰 탈취나 권한 오남용으로 이어질 수 있습니다.
confused deputy 문제를 쉽게 설명하면
confused deputy는 권한을 가진 중개자가 속아서 공격자를 대신해 행동하는 문제입니다. MCP 상황에서는 proxy server가 중개자입니다. 사용자는 정상적으로 MCP 서버를 통해 제3자 API에 로그인합니다. 제3자 authorization server는 static client ID에 대한 consent cookie를 브라우저에 남깁니다. 이후 공격자가 악성 client를 동적으로 등록하고 악성 redirect URI가 포함된 링크를 사용자에게 보냅니다.
사용자가 링크를 누르면 브라우저에는 이전 consent cookie가 남아 있습니다. 제3자 authorization server는 이미 동의했다고 보고 consent 화면을 건너뛸 수 있습니다. 결과적으로 authorization code가 공격자 redirect URI로 흘러가고, 공격자는 MCP token을 얻어 사용자를 가장할 수 있습니다.
핵심은 모델이 똑똑한지와 무관합니다. OAuth 흐름과 client별 consent가 제대로 분리되지 않으면 LLM을 쓰지 않아도 취약합니다. MCP는 이 문제를 더 자주 만나게 할 뿐입니다.
MCP 서버 운영 전 필수 설계 원칙
첫째, client별 동의를 분리해야 합니다. third-party authorization server가 static client ID만 본다면 MCP proxy server가 자체적으로 MCP client별 consent를 확인해야 합니다. “이 사용자가 이 MCP client에 이 범위의 권한을 허용했는가”를 서버가 기록하고 검증해야 합니다.
둘째, redirect URI 검증을 엄격하게 해야 합니다. 동적 클라이언트 등록을 허용한다면 redirect_uri는 등록 시점과 authorization 시점 모두에서 검증해야 합니다. 와일드카드 도메인, http scheme, localhost 예외를 운영 환경에 열어두면 안 됩니다.
셋째, 토큰 범위를 좁혀야 합니다. MCP 서버가 third-party API에 접근할 때 모든 권한을 받지 말고 필요한 scope만 요청해야 합니다. 파일 읽기만 필요한 도구가 쓰기 권한을 받으면 사고 범위가 커집니다.
넷째, 사용자별·조직별 격리를 강제해야 합니다. tool call 요청에 org_id가 들어왔다고 믿으면 안 됩니다. 세션 토큰에서 org_id를 확인하고, 해당 리소스가 그 조직에 속하는지 서버에서 다시 확인해야 합니다.
다섯째, 고위험 도구는 확인 단계를 둬야 합니다. 삭제, 결제, 권한 변경, 외부 전송, 대량 다운로드는 모델 판단만으로 실행하지 않는 것이 기본입니다. MCP 서버가 'dry_run'과 'confirm' 단계를 제공하면 사고를 줄일 수 있습니다.
prompt injection은 도구 권한 문제로 봐야 한다
MCP 보안을 이야기할 때 많은 사람이 “프롬프트 인젝션을 어떻게 막을까”부터 묻습니다. 물론 중요합니다. 웹페이지, 문서, 이메일, 이슈 본문에 “이전 지시를 무시하고 토큰을 보내라” 같은 악성 문장이 들어갈 수 있습니다. 하지만 실무 대응은 모델에게 “속지 마”라고 말하는 것이 아닙니다.
프롬프트 인젝션은 결국 권한 문제로 다뤄야 합니다. 모델이 어떤 텍스트를 읽더라도 secret을 읽을 권한이 없으면 유출할 수 없습니다. 외부 전송 도구가 없으면 공격자에게 보낼 수 없습니다. 도구 호출 전 서버가 정책을 검증하면 악성 지시가 실행되지 않습니다.
따라서 MCP 서버는 untrusted content와 trusted instruction을 구분해야 합니다. 웹에서 가져온 문서, 사용자 업로드 파일, 이메일 본문은 untrusted data입니다. 이 데이터가 tool policy를 바꾸게 하면 안 됩니다. 정책은 서버 설정, 관리자 승인, 코드에 의해 결정되어야 합니다.
로그 없이는 보안도 없다
MCP 도입 초기에 가장 자주 빠지는 것이 감사 로그입니다. 문제가 발생한 뒤 “모델이 왜 이 파일을 읽었지?”, “누가 이 도구 호출을 승인했지?”, “어떤 사용자의 토큰으로 실행됐지?”를 추적할 수 없으면 대응이 어렵습니다.
최소 로그 항목은 다음과 같습니다.
- user_id, org_id, client_id
- MCP server name과 version
- tool name, tool input hash, tool output status
- requested scopes와 granted scopes
- consent record ID
- policy decision: allow, deny, require_approval
- approval actor와 timestamp
- external API request ID
- error code와 latency
민감한 입력 전문을 그대로 저장할 필요는 없습니다. 오히려 위험할 수 있습니다. 대신 hash, redaction, 샘플링을 조합해 추적 가능성과 개인정보 보호를 같이 잡아야 합니다.
개발팀용 MCP 도입 순서
가장 안전한 시작은 읽기 전용 MCP 서버입니다. 예를 들어 GitHub issue 읽기, 문서 검색, 코드 검색처럼 외부 상태를 바꾸지 않는 도구부터 붙입니다. 이후 쓰기 도구를 추가할 때는 도구별 위험 등급을 매깁니다.
낮은 위험: 검색, 조회, 요약. 중간 위험: 초안 생성, PR 코멘트 작성, 티켓 생성. 높은 위험: 삭제, 배포, 결제, 권한 변경, 외부 발송.
높은 위험 도구는 기본적으로 비활성화하고, 관리자 승인과 사용자 확인을 모두 요구하는 편이 좋습니다. 또한 tool schema에는 입력 제한을 강하게 둬야 합니다. 자유 텍스트 하나로 모든 명령을 받는 'runCommand'류 도구는 피해야 합니다.
실행 체크리스트
- MCP proxy server가 static client ID를 쓰는지 확인한다.
- MCP client별 consent record를 별도로 저장하고 검증한다.
- dynamic client registration을 허용한다면 redirect_uri 검증을 엄격히 한다.
- third-party API scope를 최소화한다.
- user_id, org_id, resource ownership을 서버에서 강제한다.
- untrusted content가 tool policy나 system instruction을 바꾸지 못하게 한다.
- 삭제, 배포, 결제, 권한 변경 도구는 dry-run과 승인 단계를 둔다.
- tool call, scope, consent, policy decision을 감사 로그로 남긴다.
- 운영 환경에서 와일드카드 redirect URI와 과도한 localhost 예외를 제거한다.
- MCP 서버별 위험 등급표를 만들고 기본 허용 도구를 최소화한다.
MCP는 에이전트를 실무 시스템에 연결하는 강력한 접착제입니다. 하지만 접착제가 강할수록 잘못 붙었을 때 떼기 어렵습니다. 처음부터 OAuth와 도구 권한을 애플리케이션 보안 문제로 다루는 팀만 안전하게 확장할 수 있습니다.