
패치되지 않은 MCP STDIO 명령 주입 결함(CVE-2026-30623 계열)을 위한 드롭인 수정
패치되지 않은 MCP STDIO 명령 주입 결함(CVE-2026-30623 계열, 2026년 4월 OX Security가 "설계상(by design)"으로 공개 -- SDK 패치는 제공되지 않음)을 위한 드롭인 수정입니다. 한 줄만 임포트하면 Python 앱이 시작하는 모든 stdio MCP 서버는 OS가 프로세스를 생성하기 전에 명령/인자/env가 검증됩니다.
처음 방문했다면 먼저 범위를 읽고, 설치와 시작하기를 따라 하면 2분 안에 보호받을 수 있습니다.
1.0 이전 버전이며, 활발히 개발 중입니다.
check//)는 구현되어 있으며, 목(mocks)이 아닌 테스트 머신에 설치된 실제 바이너리(, , )를 대상으로 실행되는 자동화된 테스트 스위트로 검증됩니다. 실제 생성된 서버 픽스처를 통한 진짜 엔드투엔드 MCP 핸드셰이크와 의 실제 서브프로세스 수준 테스트도 포함됩니다.launchrulespythonnodenpxlaunch적용 범위: stdio MCP 서버 실행(명령 + 인자 + env)이 OS 프로세스 생성 계층에 도달하기 전에 검증합니다. 특히 SECURITY.md에 설명된 명령/인자 주입 경로를 차단합니다.
명시적 비적용 범위: 서버의 선언된 도구에서 위험한 기능을 스캔하는 것(그건 다른 문제입니다 -- AgentGuard 참고), 생성된 프로세스의 샌드박싱, 그리고 non-stdio(SSE/HTTP) MCP 전송 방식.
git clone <this-repo>
cd mcpshield
pip install -e . # core CLI: click + rich only
pip install -e ".[mcp]" # if you also want the Python autopatch (needs the `mcp` SDK)
작동 확인:
mcpshield --version
mcpshield --help
앱이 Python으로 작성되었고 StdioServerParameters를 만들거나 mcp.client.stdio.stdio_client를 직접 호출한다면, 다른 어떤 코드가 mcp.client.stdio를 임포트하기 전에 엔트리포인트 맨 위에 import 한 줄을 추가하세요:
import mcpshield.autopatch # side-effect import; must come first
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# ... use stdio_client exactly as before -- it's now validated
이제 안전하지 않은 실행은 프로세스를 생성하는 대신 mcpshield.core.errors.UnsafeConfigurationError(ValueError 하위 클래스)를 발생시킵니다.
아무것도 실행하지 않고 mcpServers 스타일 구성 파일을 감사합니다:
mcpshield check claude_desktop_config.json
+---------------------------------------------------------------+
| Server | Status | Command | Detail |
|------------------+---------+---------+------------------------|
| filesystem | OK | npx | - |
| evil-server | BLOCKED | npx | Argument '...' contains|
| | | | shell metacharacter |
+---------------------------------------------------------------+
1 ok, 0 warned, 1 blocked
무언가 BLOCKED면 0이 아닌 종료 코드를 반환합니다(--strict를 추가하면 WARN에도 실패 처리). -- 바로 CI에 적용할 수 있습니다.
Python 자동 패치를 사용할 수 없는 MCP 클라이언트(Node, Java, Rust 등)에서는 실제 명령 대신 mcpshield를 가리키도록 설정하세요:
{
"command": "mcpshield",
"args": ["launch", "--", "npx", "-y", "some-mcp-server"]
}
launch는 검증한 후 MCP 클라이언트가 기대하는 것과 동일한 stdio로 실제 명령을 실행합니다(투명한 패스스루). -- 실행이 안전하지 않으면 명확한 오류와 함께 거부합니다.
| 검사 | 네이티브 바이너리(예: python.exe) | 셸 해석 가능(.cmd/.bat/shebang 스크립트) |
|---|---|---|
인자의 셸 메타문자(&, |, ;, 백틱, $(...), ...) | 허용 | 차단 |
| 인자의 NUL 바이트 / 줄바꿈 | 차단 | 차단 |
명령이 상대 경로 탐색(..)으로 확인되는 경우 | 차단 | 차단 |
| 명령이 실제 파일로 확인되지 않는 경우 | 차단 | 차단 |
env에 있는 LD_PRELOAD / NODE_OPTIONS 등 | 제거됨(경고) | 제거됨(경고) |
env에 있는 PYTHONPATH | 플래그 표시(경고), 제거 안 됨 | 플래그 표시(경고), 제거 안 됨 |
네이티브 바이너리는 exec를 직접 하기 때문에 인자 검사가 더 느슨합니다. 인자 목록을 다시 해석할 셸이 없기 때문입니다. 셸 해석 가능한 명령(Windows에서 가장 흔한 npx.cmd/npx.bat)은 엄격한 검사를 받습니다. 이것이 기반 CVE가 악용하는 바로 그 메커니즘이기 때문입니다.
둘 다 신중하게 설계된 값별 옵트인(opt-in)이며, 절대 전체를 비활성화하는 "disable checks" 플래그가 아닙니다:
allow_raw_args=["--some-value-with-a-pipe"](라이브러리)는 검토하고 신뢰하는 특정 인자 값을 면제합니다.allow_env=["SOME_VAR"]는 일반적으로 제거되는 환경 변수를 수정 없이 통과시킵니다.| 명령 | 설명 |
|---|---|
mcpshield check <config> [--format table|json] [--strict] | mcpServers 구성에 대한 정적 감사입니다. 아무것도 실행하지 않습니다. BLOCKED가 있으면 0이 아닌 종료 코드를 반환합니다(--strict를 사용하면 WARN도 마찬가지). |
mcpshield launch -- <command> [args...] | 검증 후 패스스루 stdio로 실제 명령을 실행합니다. |
mcpshield rules list | 활성 셸 메타문자 차단 목록, 환경 변수 목록, 알려진 안전한 런처 바이너리를 표시합니다. |
git clone이 필요합니다.mcp.client.stdio.stdio_client만 패치합니다. import mcpshield.autopatch 이전에 from mcp.client.stdio import stdio_client를 실행해 이미 자체 참조를 보유한 코드는 이를 우회합니다. 항상 import mcpshield.autopatch를 먼저 임포트하세요.check는 실행 중인 머신을 기준으로 명령을 확인합니다. 실제 배포 머신(다른 PATH, 다른 설치 도구)에서 다르게 해석되는 구성은 그곳에서 다르게 보고될 수 있습니다.mcpshield/
autopatch.py # one-line-import fix for Python MCP hosts
core/
validate.py # the validation engine (command/args/env checks)
rules.py # blocklist/allowlist data
errors.py # UnsafeConfigurationError
cli/
main.py
commands/ (check.py, launch.py, rules.py)
tests/
fixtures/ # real benign MCP server + sample/malicious configs
pip install -e ".[dev,mcp]"
pytest
테스트 스위트는 실행 중인 머신에 설치된 실제 python/node/npx 바이너리를 대상으로 검증하며(엔진이 해석하는 것과 동일한 방식으로 해석), 목이 아닌 실제 생성된 서버 픽스처를 통한 진짜 엔드투엔드 MCP 핸드셰이크를 포함합니다.