MCP 설정 파일이 실제 보안 경계입니다. 아무도 감사하지 않습니다.
요약
본 글은 MCP(Model Context Protocol) 서버의 설정 파일 자체가 실제 보안 경계이며, 기존 스캐너들이 놓치는 핵심적인 취약점을 지적합니다. 저자는 로컬 런타임 보안 스캐너 `mcp-audit`을 개발하여, 사용자의 구성 파일을 분석하고 알려진 CVE 버전 및 위험한 명령어 주입 패턴 등을 검사하는 방법을 제시했습니다.
핵심 포인트
- MCP 서버 설정 파일 자체가 가장 중요한 보안 경계입니다.
- 기존 도구는 설계나 '위험해 보이는' 것만 보고할 뿐, 실제 취약점은 놓칩니다.
- `mcp-audit`는 CVE 테이블과 원클릭 수정 기능을 제공하는 로컬 스캐너입니다.
- 주요 위험으로는 명령어 주입(command injection), 인증되지 않은 엔드포인트, `0.0.0.0` 바인딩 등이 있습니다.
MCP 설정 파일이 실제 보안 경계입니다. 아무도 감사하지 않습니다.
저는 MCP 보안 도구에 대해 많이 읽었는데 이상한 점을 발견했습니다. 제가 찾은 모든 스캐너는 서버의 _설계_를 검사하거나, 설정이 '위험해 보인다'고 보고할 뿐이었습니다. 그 어떤 것도 제가 제 ~/.claude.json 파일을 볼 때 실제로 궁금했던 두 가지 질문에 답하지 못합니다.
- 현재 알려진 CVE가 있는 서버 버전을 사용하고 있나요?
- 그냥 고칠 수 있나요?
그래서 저는 MCP 서버를 위한 로컬 런타임 보안 스캐너인 mcp-audit을 만들었습니다. 이 도구는 번들된 CVE 테이블과 원클릭 수정 기능을 제공합니다. stdlib만 사용하며, 의존성은 없습니다.
pip install mcp-runtime-audit
mcp-audit scan
자체 설정 파일 스캔의 필요성
여기서의 위협 모델은 일반적인 소프트웨어와 비교했을 때 이상합니다. MCP 서버는 사용자의 권한으로 실행되며, 사용자를 대신하여 AI 에이전트에 의해 구동됩니다. 이를 시작하는 구성 파일은 아무도 검토하지 않은 수작업 편집 JSON입니다.
그리고 기록도 좋지 않습니다:
- 공식 도구에서 RCE가 포함되었습니다. CVE-2025-49596이 Anthropic의 자체 MCP Inspector(CVSS 9.4)를 공격했습니다: 이 로컬 프록시는
transportType=stdio&command=<cmd>를 가진 인증되지 않은/sse요청을 수락하고 이를 서브프로세스로 실행했습니다. 악성 페이지에 접속하는 것만으로도 개발자의 컴퓨터에서 코드를 실행할 수 있었습니다. Inspector 0.14.1에서 수정되었습니다. - 엔터프라이즈 MCP 앱도 마찬가지입니다. CVE-2026-76404 (Splunk MCP Server < 1.2.1, CVSS 9.1): 자격 증명 관리의 안전하지 않은 역직렬화(unsafe deserialization)로 인해 관리자 역할이 임의 OS 명령을 실행할 수 있게 되었습니다.
- Langflow의 stdio transport가 사용자의 명령어를
bash -c로 감쌌습니다. CVE-2026-105697 (CVSS 9.9): 사용자가 MCP 서버 설정에 입력한 어떤 명령어든 허용 목록 없이 실행되었습니다. - Anthropic의 공식 입장은 stdio 위험이
mcp-audit scan은 MCP 클라이언트 설정을 읽어옵니다 (Claude Code의 ~/.claude.json, Codex 설정, 그리고 일반적으로 사용되는 다른 위치 — 또는 --config로 전달하는 경로). 그리고 네 가지 검사를 수행합니다:
1. 위험한 stdio 명령어. 만약 귀하의 stdio 항목이 실행을 bash -c / sh -c / cmd /c 안에 감싸고 있다면, 이는 설계상 명령 주입(command injection)입니다. 이것은 바로 위의 Langflow 패턴과 같으며, 실제 설정에서 생각보다 더 자주 나타납니다.
2. 인증되지 않은 엔드포인트. Authorization/X-API-Key 헤더가 없는 SSE/HTTP 서버입니다. --probe를 사용하면 해당 엔드포인트가 실제로 응답하는지 확인하기 위해 인증되지 않은 GET 요청을 하나 보냅니다 — CVE-2025-49596 형태의 취약점입니다.
3. 바인딩 주소. URL, --host 플래그 또는 환경 변수에서 0.0.0.0은 서버가 localhost를 넘어 도달 가능하다는 것을 의미합니다.
4. 알려진 CVE 버전 검사. 이 부분은 제가 다른 곳에서는 찾을 수 없었던 것입니다: 이는 귀하의 npx/uvx 호출에서 package@version을 추출하여 번들된 CVE 테이블과 일치시킵니다. @modelcontextprotocol/[email protected] 실행 시, CVE-2025-49596이라는 심각한 취약점 명칭과 이를 수정하는 버전을 알려줍니다.
모든 발견 사항은 규칙 ID(rule id), CVE ID, 심각도(severity), 증거(evidence), 그리고 해결책(fix)을 포함하며 — 텍스트 및 JSON 출력으로 제공되고 CI에 준비된 종료 코드(0: 깨끗함, 1: 발견됨, 2: 오류)를 가집니다.
원클릭 수정 (The one-click fix)
스캔은 절반의 작업일 뿐입니다. mcp-audit fix는 건식 실행 계획(dry-run plan)을 출력합니다. 여기에 --apply를 추가하면 다음 작업을 수행합니다:
- URL, 플래그 및 환경 값에서
0.0.0.0을127.0.0.1로 재작성하고, - 인증되지 않은 엔드포인트에
Authorization: Bearer ${MCP_TOKEN}플레이스홀더를 추가합니다 (사용자가 실제 토큰으로 채워야 함), - 어떤 것도 쓰기 전에 설정을
<file>.bak-<timestamp>로 백업합니다.
만약 agent-guard가 설치된 것을 감지하면, mcp-audit scan --link-agent-guard는 중요한 서버들을 agent-guard의 블랙리스트에 작성하여 에이전트 런타임이 해당 서버를 실행하는 것을 거부하게 합니다.
다른 스캐너와의 차이점 (How it differs from the other scanners)
- mcpscan과 graygnatconsole의 mcp-audit-tool은 설정을 스캔하지만, 알려진 CVE 버전 매칭을 수행하지도 않고 수정 사항을 되돌려 쓰지도 않습니다.
- mcp-lint는 MCP 서버를 위한 설계 품질 린터(linter)이며, 다른 계층에 속합니다. 이 도구는 실행 중인 서버의 런타임 보안을 감사합니다.
의도적으로 빠진 기능들
- 버전 감지는
package@version-스타일 호출(npx/uvx/node)에서만 작동합니다. 다른 방식으로 설치된 서버는 CVE 테이블과 일치하지 않습니다. - CVE 테이블은 라이브 피드가 아니라 번들링된 스냅샷이므로, 새로운 CVE가 발견되면 새 릴리스가 필요합니다.
--probe는 네트워크에 접근하므로(GET 요청 한 번, 페이로드 없음, 변형 없음), 소유하지 않은 호스트를 가리키지 마십시오.- 서버가 시작한 후 무엇을 하는지는 볼 수 없습니다. 이것은 설정 및 런타임 표면 스캐너이며, 동작 모니터(behavior monitor)가 아닙니다.
Repo: https://github.com/hahahahahahahahah6/mcp-audit
PyPI: https://pypi.org/project/mcp-runtime-audit/ (pip install mcp-runtime-audit)
MCP 서버를 로컬에서 실행하는 경우, 스캔을 실행해 보세요. 야생(실제 환경)에서 무엇을 발견하는지 정말 알고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기