MCP STDIO: 서버가 신뢰되기 전에 명령어가 실행됩니다
요약
MCP STDIO 전송 방식의 설계 특성으로 인해 발생할 수 있는 보안 취약점을 분석합니다. 클라이언트가 서버의 유효성을 검증하기 전에 명령어를 먼저 실행하기 때문에, 신뢰할 수 없는 입력값이 명령어 실행 표면이 될 수 있음을 경고합니다.
핵심 포인트
- MCP STDIO는 서버 유효성 검증 전 명령어를 실행하는 설계 특성을 가짐
- 명령어 주입, 허용 목록 우회, 프롬프트 주입을 통한 코드 실행 위험 존재
- 신뢰할 수 없는 입력값이 MCP 설정 파일에 영향을 미치지 않도록 주의 필요
만약 여러분이 MCP로 AI 에이전트를 구축하고 있다면, STDIO 전송 (transport) 방식에서 놓치기 쉬운 세부 사항이 하나 있습니다.
클라이언트는 설정 (config) 값을 읽습니다.
그 설정 값에는 명령어가 포함되어 있습니다.
명령어가 실행됩니다.
그 이후에야 클라이언트는 해당 명령어가 유효한 MCP 서버를 시작했는지 여부를 알게 됩니다.
만약 명령어가 실제 MCP 서버를 시작한다면, 에이전트는 작동하는 도구 (tool) 연결을 얻게 됩니다.
만약 그렇지 않다면, 에이전트는 에러를 받게 됩니다.
하지만 명령어는 이미 실행되었습니다.
이것이 개발자들이 직시해야 할 부분입니다. 이것은 단순히 한 앱의 버그가 아닙니다. OX Security에 따르면, 이는 MCP STDIO 전송 (transport)이 작동하는 방식의 설계 특성입니다.
요약 버전
MCP는 AI 에이전트가 도구 (tools), 파일, 데이터베이스, API 및 로컬 서비스에 연결할 수 있도록 해줍니다.
STDIO는 MCP의 전송 방식 중 하나입니다. HTTP를 통해 연결하는 대신, 클라이언트는 로컬 프로세스를 실행하고 표준 입력 (standard input) 및 표준 출력 (standard output)을 통해 해당 프로세스와 통신합니다.
이러한 설계는 유용합니다. 네트워크 포트를 여는 것을 방지하며, 로컬 도구를 에이전트에 쉽게 연결할 수 있게 해줍니다.
하지만 이는 또한 MCP 클라이언트가 사용자의 머신에서 프로세스를 실행한다는 것을 의미합니다.
이것이 자동으로 안전하지 않은 것은 아닙니다. 로컬 개발자 도구들은 항상 프로세스를 실행합니다.
위험은 신뢰할 수 없는 입력값이 명령어, 인자 (arguments), 또는 MCP 서버를 정의하는 설정 파일에 영향을 미칠 수 있을 때 나타납니다.
그 시점에서 여러분의 MCP 설정은 명령어 실행 표면 (command execution surface)이 됩니다.
OX Security가 발견한 내용
OX Security는 5개월 동안 MCP를 감사한 후 2026년 4월에 연구 결과를 발표했습니다.
그들의 발견은 단순하지만 심각했습니다:
공격자가 제어하는 입력값이 MCP STDIO 실행 명령어에 도달하면, 공격자는 호스트에서 코드를 실행할 수 있을지도 모릅니다.
OX는 이 위험을 몇 가지 경로로 분류했습니다:
직접적인 명령어 주입 (Direct command injection). 일부 AI 프레임워크는 충분한 검증 없이 사용자 입력을 STDIO 서버 설정에 전달했습니다.
허용 목록 우회 (Allowlist bypasses). 어떤 제품은 npx와 같이 신뢰할 수 있는 런처만 허용할 수도 있지만, 여전히 공격자가 제어하는 인자(arguments)를 허용할 수 있습니다. 만약 인자가 npx가 실행하는 내용을 변경할 수 있다면, 허용 목록은 큰 보호를 제공하지 못합니다.
IDE 프롬프트 주입 (IDE prompt injection). 코딩 에이전트나 IDE는 파일, 웹 페이지, 리포지토리(repos) 또는 도구 응답으로부터 신뢰할 수 없는 콘텐츠를 처리할 수 있습니다. 만약 해당 콘텐츠가 에이전트로 하여금 로컬 MCP 설정을 수정하게 만들 수 있다면, 다음 도구 실행 시 코드 실행(code execution)으로 이어질 수 있습니다.
확인된 한 가지 사례는 Windsurf의 CVE-2026-30615로, 공격자가 제어하는 HTML이 로컬 MCP 설정을 수정하고 악성 MCP STDIO 서버를 자동으로 등록하여, 추가적인 사용자 상호작용 없이 명령 실행으로 이어질 수 있었습니다.
마켓플레이스 배포 (Marketplace distribution). OX는 11개의 MCP 마켓플레이스에 테스트 패키지를 제출했습니다. 그중 9곳이 이를 수락했습니다.
OX는 또한 공개적으로 접근 가능한 7,000개의 서버, 최대 200,000개의 취약한 인스턴스, 그리고 6개의 실제 운영 플랫폼에서의 명령 실행 사례를 보고했습니다.
이러한 수치보다 더 중요한 것은 패턴입니다.
MCP는 인프라가 되어가고 있습니다. 인프라에 날카로운 모서리가 있다면, 그 하류(downstream)에 있는 모든 이들이 이를 물려받게 됩니다.
허용 목록 문제 (The allowlist problem)
허용 목록 우회는 개발자가 얻어야 할 교훈입니다.
어떤 제품이 다음과 같은 보안 규칙을 가지고 있다고 가정해 봅시다:
MCP STDIO 서버는
npx를 통해서만 실행될 수 있다.
이는 합리적으로 들립니다. 무작위 바이너리를 차단하며, 팀이 검토해야 할 신뢰할 수 있는 런처를 하나로 제한하기 때문입니다.
하지만 신뢰할 수 없는 입력이 인자(args)에 도달한다면 어떻게 될까요?
{
"name": "example-tool",
"transport": "stdio",
...
허용 목록은 명령어 이름(command name)을 확인했습니다.
하지만 그 명령어가 무엇을 하도록 요청받았는지는 확인하지 않았습니다.
이것이 불일치(mismatch)입니다. 보안 로직은 "명령어가 허용됨"이라고 말하지만, 런타임 동작은 "전체 명령어와 인자가 중요하다"라고 말합니다.
진정한 허용 목록 (allowlist)은 바이너리 이름에서 멈출 수 없습니다. 전체 명령어 형태 (command shape)를 검증해야 합니다.
그것은 다음을 의미합니다:
- 어떤 런처 (launcher)가 허용되는지
- 어떤 인자 (arguments)가 허용되는지
- 어떤 패키지 이름 (package names)이 허용되는지
- 어떤 플래그 (flags)가 차단되는지
- 쉘 (shell)과 유사한 동작이 가능한지
- 명령어가 알려진 버전으로 고정 (pinned)되어 있는지
- 서버 정의가 신뢰할 수 있는 출처로부터 왔는지
만약 답변이 "우리는 npx를 허용하고 나머지는 신뢰한다"라면, 그것은 보안 경계 (security boundary)가 아닙니다.
이것이 단지 MCP만의 문제가 아닌 이유
이것은 개발자들이 수년 동안 목격해 온 것과 동일한 유형의 실수입니다.
우리는 래퍼 (wrapper)를 신뢰하지만, 그 래퍼가 안전하지 않은 일을 하도록 지시받을 수 있다는 사실을 잊습니다.
우리는 파일 이름을 검증하지만, 경로 (path)가 디렉토리를 탈출할 수 있다는 사실을 잊습니다.
우리는 하나의 실행 파일 (executable)을 허용하지만, 그 플래그가 실행 모델 (execution model)을 변경할 수 있다는 사실을 잊습니다.
MCP는 에이전트 (agents)가 이제 신뢰할 수 없는 콘텐츠와 로컬 실행 (local execution) 사이에 위치하기 때문에 이 문제를 더 중요하게 만듭니다.
개발자는 에이전트에게 리포지토리 (repo)를 조사하거나, 문서를 읽거나, 이슈를 요약하거나, 도구를 설치하거나, 로컬 서버를 구성하도록 요청할 수 있습니다.
그 에이전트는 공격자가 제어하는 콘텐츠를 읽을 수 있습니다.
만약 에이전트가 설정 파일 (config files)을 작성하거나 도구를 실행할 수 있다면, 공격자는 인간을 직접 속일 필요가 없습니다. 그들은 에이전트의 환경에 영향을 미칠 수 있습니다.
이것이 프롬프트 인젝션 (prompt injection)이 로컬 도구 실행 (local tool execution)과 만날 때 더욱 심각해지는 이유입니다.
프롬프트 그 자체는 페이로드 (payload)가 아닙니다.
프롬프트는 페이로드로 가는 경로가 됩니다.
Anthropic이 프로토콜을 패치하지 않은 이유
OX Security에 의해 설명된 Anthropic의 입장은 이러한 동작이 예상된 것이라는 점입니다.
그것에는 나름의 논리가 있습니다.
STDIO는 클라이언트가 로컬 MCP 서버를 실행할 수 있도록 존재합니다. 만약 프로토콜이 인자를 공격적으로 제거하거나 명령어 패턴을 차단한다면, 정당한 도구 설정 (tool setups)을 망가뜨릴 수 있습니다.
반론 또한 합리적입니다.
기본 통합 계층 (default integration layer)이 되는 프로토콜은 모든 하위 팀 (downstream team)이 스스로 안전한 명령어 검증 (command validation)을 설계할 것이라고 가정할 수 없습니다.
MCP를 사용하는 대부분의 팀은 명령어 실행 안전성 (command execution safety)의 전문가가 되려는 것이 아닙니다. 그들은 AI 에이전트 (AI agent)를 유용한 도구 (tools)에 연결하려고 노력하는 것입니다.
이것이 바로 공급망 문제 (supply chain problem)입니다.
프로토콜 또는 SDK 계층에서의 위험한 기본 설정 (risky default)은 수많은 제품 전반에 걸쳐 반복되는 버그가 됩니다.
자신의 MCP 설정에서 확인해야 할 사항
만약 MCP STDIO를 사용하고 있다면, 다음 테스트부터 시작해 보시기 바랍니다.
1. 사용자 입력이 명령어 (command) 또는 인자 (args)에 도달할 수 있는가?
입력이 다음과 같은 값으로 흘러 들어가는 곳을 찾으십시오:
StdioServerParameters(
command=...,
args=...
...
또는 사용 중인 언어나 프레임워크의 상응하는 부분입니다.
사용자 입력이 어느 한 필드에라도 도달한다면, 이를 명령어 실행 위험 (command execution risk)으로 간주하십시오.
직접적인 양식 필드 (form fields)만 확인하지 마십시오. 또한 다음 사항들도 확인해야 합니다:
- 임포트된 프로젝트 파일 (imported project files)
- 생성된 설정 (generated config)
- 에이전트가 작성한 설정 (agent-written config)
- 도구 매니페스트 (tool manifests)
- 마켓플레이스 패키지 메타데이터 (marketplace package metadata)
- 설정 스크립트 (setup scripts)
- 리포지토리 지침 (repo instructions)
- 에이전트가 소비하는 이슈(issue) 또는 PR 콘텐츠
2. 허용 목록 (allowlist)이 전체 표현식을 검증하는가?
다음과 같이 확인하는 허용 목록은 불완전합니다:
"command": "npx"
인자 (args)도 검증해야 합니다.
더 좋은 방법은 허용된 도구를 고정된 명령어 템플릿 (command templates)에 매핑하는 것입니다.
예를 들어:
{
"tool": "approved-doc-search",
"command": "npx",
...
이 방식이 사용자 제어 입력 (user-controlled input)이 명령어를 구축하도록 허용하는 것보다 더 안전합니다.
3. 에이전트가 MCP 설정을 몰래 수정할 수 있는가?
이 부분은 팀들이 놓치기 쉬운 지점입니다.
위험은 단지 "사용자가 잘못된 명령어를 입력했는가?"에 그치지 않습니다.
위험은 또한 "에이전트가 적대적인 콘텐츠를 읽은 후 설정을 변경할 수 있는가?"이기도 합니다.
STDIO 실행 동작에 영향을 미치는 설정 변경은 의도적인 확인 (deliberate confirmation)을 거쳐야 합니다. MCP 서버 명령어에 대한 무음 업데이트 (silent update)는 코드 변경 (code change)과 동일하게 취급되어야 합니다.
4. MCP 서버가 공개적으로 노출되어 있는가?
만약 MCP가 연결된 서비스가 공용 인터넷(public internet)에서 접근 가능하다면, 그 앞에 인증(authentication) 및 네트워크 제어 장치를 배치하십시오.
AI 툴링(AI tooling)을 해롭지 않은 개발 유틸리티로 취급하지 마십시오. 이러한 시스템은 종종 API 키, 로컬 파일 접근 권한, 데이터베이스 핸들(database handles), 또는 클라우드 자격 증명(cloud credentials)을 보유하고 있습니다.
5. MCP 패키지는 어디에서 왔는가?
MCP 서버를 npm 패키지처럼 취급하십시오.
즉, 다음 사항들을 확인해야 함을 의미합니다:
- 발행자 신원 (publisher identity)
- 리포지토리 이력 (repo history)
- 설치 스크립트 (install scripts)
- 버전 고정 (version pinning)
- 패키지 연령 (package age)
- 요청된 권한 (permissions requested)
- 패키지가 공식 소스에서 왔는지 여부
마켓플레이스 등록 정보만으로는 충분하지 않습니다.
QA 교훈
가장 유용한 테스트 케이스는 "모델을 탈옥(jailbreak)할 수 있는가?"가 아닙니다.
더 나은 테스트는 다음과 같습니다:
신뢰할 수 없는 콘텐츠가 에이전트(agent)로 하여금 실행되는 코드를 변경하는 방식으로 MCP STDIO 서버를 생성, 수정 또는 실행하게 만들 수 있는가?
이는 QA 및 보안 팀에 테스트를 위한 구체적인 워크플로우를 제공합니다.
에이전트가 읽을 가능성이 높은 곳에 악성 명령(malicious instructions)을 배치하십시오:
- README 파일
- 문서(docs) 페이지
- 이슈(issue) 댓글
- PR(Pull Request) 설명
- 웹 페이지
- 툴 응답 (tool responses)
- 패키지 메타데이터 (package metadata)
- 생성된 설정 지침 (generated setup instructions)
그런 다음, 에이전트가 해당 지침을 로컬 MCP 설정 변경이나 안전하지 않은 툴 실행으로 전환할 수 없는지 확인하십시오.
이것이 바로 많은 AI 보안 테스트가 나아가고 있는 방향입니다.
단순히 프롬프트 입력(prompt input)만이 아닙니다.
단순히 모델 출력(model output)만이 아닙니다.
신뢰할 수 없는 콘텐츠로부터 툴 실행(tool execution)에 이르는 전체 경로입니다.
OWASP 매핑
이는 OWASP LLM03: Supply Chain 항목에 깔끔하게 부합합니다.
위험은 프로토콜, SDK, 레지스트리(registries) 및 툴 패키지를 통해 상속됩니다. 다운스트림(downstream)의 개발자들은 MCP STDIO를 채택했을 때 명령 실행 표면(command execution surface)을 상속받았다는 사실을 깨닫지 못할 수도 있습니다.
또한 이는 OWASP LLM06: Excessive Agency와도 관련이 있습니다.
취약하게 검증된 설정을 통해 로컬 프로세스를 실행할 수 있는 에이전트는 대부분의 사용자가 인지하는 것보다 더 많은 권한을 가집니다.
그 조합이 바로 진짜 문제입니다:
공급망 리스크 (Supply chain risk)는 에이전트에게 위험한 공격 표면 (tool surface)을 제공합니다.
과도한 권한 (Excessive agency)은 에이전트가 그 표면을 사용하게 만듭니다.
프롬프트 인젝션 (Prompt injection)은 공격자에게 에이전트를 조종할 수 있는 수단을 제공합니다.
결론 (Bottom line)
MCP STDIO는 유용합니다.
하지만 또한 날카롭습니다.
만약 이를 사용한다면, 단순히 MCP 서버가 작동하는지만 묻지 마십시오.
서버가 제대로 작동함을 증명하기 전에 어떤 명령어가 실행되는지를 물으십시오.
STDIO 환경에서 커넥터 (connector)는 단순한 커넥터가 아니기 때문입니다.
커넥터가 바로 쉘 (shell)입니다.
더 읽어보기 (Further reading)
더 자세한 내용은 저의 전체 글인 AI Leak Watch: The Protocol That Anthropic Won't Fix와 관련 가이드인 How the MCP STDIO Flaw Works를 참조하십시오.
주요 연구: OX Security: The Mother of All AI Supply Chains
프로토콜 문서: Model Context Protocol: Transports
Windsurf 권고: CVE-2026-30615 / GHSA-wj2m-jvpr-64cq
OWASP 매핑: LLM03 Supply Chain 및 LLM06 Excessive Agency
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기