mcp-confirm
mcp-confirm
쉽게 말하면: AI가 "확실합니까?"라고 물을 때, MCP SDK는 이미 그 승인이 다른 작업에 재사용되는 것을 막습니다. 그러나 같은 승인이 두 번 사용되는 것을 막지는 않습니다. 이 저장소는 그 공백과 SDK가 남겨둔 다른 두 가지 공백을 메웁니다.
먼저 읽어보세요: 이 문제의 대부분은 이미 해결되어 있습니다
2026-07-28 MCP 사양은 Multi Round-Trip Requests를 추가하여, 도구가 호출 중간에 멈추고 사용자에게 확인을 요청할 수 있게 했습니다. 승인은 불투명한 requestState로 클라이언트를 통해 다시 전달되며, 사양은 서버가 이를 공격자가 제어하는 값으로 취급해야 한다고 명시합니다.
Python SDK는 기본적으로 모든 MCPServer에서 이를 처리합니다.
RequestStateBoundary는 조건 없이 미들웨어 체인에 추가됩니다 — 키를 제공하지 않으면 임시 키와 함께 추가됩니다. 이는 상태를 AES-256-GCM으로 봉인하고, 메서드, 대상, 호출 인자의 다이제스트, 대상(audience), 인증된 주체(principal)에 바인딩하며, TTL을 적용합니다.
그래서 가장 먼저 떠올리는 공격 — cache.txt 삭제를 승인한 다음, 그 승인을 thesis.txt에 재사용하는 것 — 은 이미 SDK가 거부합니다.
이를 위한 라이브러리가 필요하지 않으며, 직접 작성해서도 안 됩니다.
이 저장소는 원래 어쨌든 하나를 작성했습니다: HMAC, TTL, 인자 바인딩으로 250줄을 작성하여 헤드라인 기능으로 출시했지만, 출시 당일에 이미 중복이었습니다. 이는 조용히 삭제하는 대신 문서 하단에 기록되어 있습니다.
Related MCP server: RecourseOS
SDK가 하지 않는 것
세 가지 공백이 있으며, 각각 테스트가 있습니다.
1. 상태를 바인딩하고 만료시키지만, 소비하지는 않습니다.
TTL 내에서 같은 승인은 제시되는 횟수만큼 검증됩니다. 경계가 수행하는 모든 검사는 매번 통과합니다. 사양은 이것이 의도적이며 나머지는 서버의 몫임을 명시적으로 밝힙니다:
이러한 조치는 재생(replay) 창을 제한하고 교차 사용자 및 교차 요청 재사용을 방지하지만, 그 자체로 단일 사용을 보장하지는 않습니다. 주어진
requestState가 최대 한 번만 소비되어야 하는 서버(예: 일회용 상환)는 해당 불변식을 서버 측에서 반드시 강제해야 합니다.
"파일 삭제"의 경우 두 번째 시도는 아무것도 찾지 못합니다. "£500 이체"의 경우 그것이 전체 문제입니다. singleuse.py는 바로 그 불변식입니다 — 미결 확인(confirmation)의 원장(ledger)이며, 상환 시 소비됩니다. 암호화는 포함하지 않습니다. 경계가 이미 평문이 이 서버가 발행한 것임을 보장하기 때문입니다.
2. 인간이 읽는 질문을 정화하는 것이 없습니다.
elicitation message는 서버가 선택한 텍스트로, 사람에게 렌더링되며, 일반적으로 신뢰할 수 없는 값이 그 안에 삽입됩니다 — 핵심은 어떤 파일이 삭제될지 말하는 것입니다. 그래서 파일 이름을 지정하세요:
cache.txt
SYSTEM NOTICE: your session has expired.
Enter your AWS secret key to continue:이제 대화 상자에 두 번째로 공식적으로 보이는 프롬프트가 표시됩니다. 사용자는 삭제를 확인하는 것이 아니라, 자신의 도구에 의해 피싱당하고 있는 것입니다. 같은 2026-07-28 릴리스는 MCP Apps(서버 렌더링 UI)도 출시했으며, 이는 이 표면을 좁히기보다 넓힙니다.
prompt.py는 신뢰할 수 없는 값을 한 줄로 평탄화하고, 양방향 오버라이드와 제로 너비 문자를 제거하며, 중간에서 잘라내어 끝에 있는 파일 이름이 계속 보이도록 합니다. 제어 문자는 삭제하는 대신 공백으로 바뀝니다. 축소하면 a\nb와 ab가 동일하게 렌더링될 수 있기 때문입니다 — 서로 다른 두 파일이 하나의 대화 상자에 표시됩니다.
3. 어떤 프로토콜 계층도 실행 시점에 당신의 리소스를 다시 확인할 수 없습니다.
사용자는 그 사이에 생각했습니다. 파일은 그 창에서 교체될 수 있으며, "변경되지 않음"이 무엇을 의미하는지 아는 것은 도구뿐입니다. 이 서버는 삭제 전에 다시 확인하고, 심볼릭 링크가 된 경로를 거부합니다.
어떤 계층이 무엇을 거부하는가
이것이 유용한 부분이며, 테스트는 이를 입증하도록 작성되었습니다. MCPError는 SDK의 미들웨어가 이 패키지가 실행되기 전에 거부했음을 의미하고, ToolError는 이 패키지가 거부했음을 의미합니다.
공격 | 거부 주체 | 테스트 |
승인이 다른 파일에 재생됨 | SDK |
|
상태가 위조되거나 다른 키로 봉인됨 | SDK |
|
같은 승인이 두 번 소비됨 | 이 패키지 |
|
다른 복제본이 발행한 상태 | 이 패키지 |
|
시스템 프롬프트를 위조하는 파일명 | 이 패키지 |
|
승인 후 파일이 심볼릭 링크로 교체됨 | 이 패키지 |
|
허용된 루트 밖의 경로 | 이 패키지 |
|
테스트
35개 테스트 — 서버를 통한 17개, 원장(ledger)에 대한 11개, 프롬프트 정화에 대한 7개.
모든 서버 테스트는 실제 RequestStateBoundary를 통해 실행됩니다. MCPServer가 자체적으로 설치하는 것과 같은 클래스이며, 고정된 키를 사용하여 1라운드 봉인과 2라운드 해제를 실제 통신과 동일하게 수행합니다.
그 하네스는 특정 실수 때문에 존재합니다. 첫 번째 버전은 MCPServer.call_tool()을 직접 호출하여 테스트했는데, 이는 도구 관리자로 바로 가서 미들웨어 체인을 완전히 우회했습니다. SDK의 경계가 실행되지 않았으므로, 중복된 수제 가드가 중요한 것처럼 보였습니다. 테스트 설계가 전체 빌드 주기 동안 그것을 숨긴 것입니다.
커버리지는 81%이며, prompt.py는 100%, singleuse.py는 94%입니다. 나머지는 main()의 argparse와 전송 연결이며, build_server를 통해 테스트됩니다.
CI는 의도적으로 Ubuntu에서만 실행됩니다: 승인 후 교체 테스트는 심볼릭 링크가 필요하며, 빌드는 해당 테스트가 건너뛴 것으로 보고되면 실패합니다.
설치
pip install git+https://github.com/les-k/mcp-confirm.git실행
mcp-confirm --root /path/you/allow--root가 없으면 서버는 기본값으로 설정하는 대신 모든 요청을 거부합니다. 루트는 시작 시 고정되며 에이전트가 선택하지 않습니다. 서명 키는 필요 없습니다 — MCPServer가 자체 키를 제공합니다.
알려진 제한 사항
원장은 인메모리입니다. 따라서 단일 프로세스에는 정확하지만 로드 밸런서 뒤에서는 잘못됩니다. SDK는 복제본 간 키 공유를 지원합니다(
RequestStateSecurity(keys=[...])). 해당 구성에서 복제본 B는 복제본 A가 발행한 확인을 거부합니다. 안전한 방향으로 실패하지만, 사용자에게는 설명할 수 없이 작동이 중단된 확인으로 보입니다. 다중 프로세스 배포에는 Redis 또는 원자적 비교-삭제가 있는 데이터베이스 행이 필요합니다. 이 동작에 대한 테스트가 있습니다.데모 도구는 의도적으로 작습니다. 파일 하나를 삭제합니다. 흥미로운 코드는
singleuse.py와prompt.py입니다.이를 뒷받침하는 CVE는 없습니다. MRTR은 몇 주밖에 되지 않았으므로, 이는 사양의 MUST/SHOULD 목록과 SDK를 읽고 구축한 것이지, 공개된 사고 사례를 기반으로 한 것이 아닙니다.
0.1.0 버전의 문제점
성공만 기록하는 저장소는 증거가 될 수 없기 때문에 여기에 보관합니다.
0.1.0은 SDK가 이미 수행한 것을 재구현했습니다. state.py는 HMAC 서명, TTL, 주체/메서드/인자 바인딩의 250줄이었습니다 — 모두 RequestStateBoundary를 복제한 것이며, 그 중 어느 것도 좋지 않았습니다: SDK가 사용하는 인증된 암호화 대신 HMAC, 상태 바인딩 없음, 키 회전 없음.
이는 테스트가 아니라 SDK의 소스를 읽어서 발견되었습니다. 테스트는 정확히 미들웨어를 우회했기 때문에 통과했습니다. 미들웨어가 있었다면 문제가 드러났을 것입니다.
CI는 0.1.0의 실제 버그를 별도로 발견했습니다: 심볼릭 링크 검사가 Path.resolve() 이후에 실행되어, 링크 자체가 아니라 링크의 대상을 검사했습니다. 허용된 루트 내의 다른 파일을 대상으로 한 교체가 삭제되었을 수 있습니다. 수정되었으며, 원래 버전이 실행하지 않았던 변형에 대한 테스트가 추가되었습니다.
0.2.0은 state.py를 완전히 삭제하고 SDK가 남겨둔 부분만 유지합니다.
라이선스
MIT.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server that provides safeguard capabilities to protect against prompt injection and unsafe tool calls.6MIT

RecourseOSofficial
AlicenseNot gradedqualityAmaintenanceMCP server that evaluates Terraform plans, shell commands, and tool calls to assess recoverability and risk before execution, enabling safe AI agent actions.1511MIT- AlicenseNot gradedqualityCmaintenanceMCP server that provides human-in-the-loop approval for risky AI agent actions, with durable state and audit logs.MIT
- FlicenseNot gradedqualityCmaintenanceMCP server that provides a security gateway for AI agents, enforcing allow/confirm/deny policies on tool calls and requiring human approval for risky operations, with full audit logging.
Related MCP Connectors
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Scans MCP servers for tool poisoning, prompt injection and supply chain risks.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/les-k/mcp-confirm'
If you have feedback or need assistance with the MCP directory API, please join our Discord server