
CVE-2026-52618을 문서화하며, @webfer/mcp-ansible-drupal의 executeDeployment extraVars를 통한 OS 명령 주입에 대한 PoC와 함께 탐지 지침 및 완화 조치를 제공합니다.
executeDeployment extra vars를 통한 OS 명령 주입spawn(cmd[0], cmd.slice(1), { shell: true })는 인자 배열을 이스케이프 없이 단일 /bin/sh -c 문자열로 다시 결합하므로, executeDeployment MCP 도구에 전달된 extraVars 값에 포함된 셸 메타문자가 서버를 실행 중인 호스트에서 실행됩니다.
| CVE | CVE-2026-52618 |
| CWE | CWE-78 (OS 명령에 사용되는 특수 요소의 부적절한 중화) |
| 패키지 | @webfer/mcp-ansible-drupal (npm) |
| 영향 받는 버전 | 2.0.0 |
| 수정된 버전 | 2.0.3 (2026-06-01 게시) |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 High (stdio 전송). 서버가 네트워크 전송으로 래핑된 경우 AV:N → 9.8 Critical. |
| 보고자 | s1ko (github.com/s1ko, [email protected]) |
| CVE 할당 | 2026-07-13, MITRE CNA-LR |
이 문제는 수정되었습니다. 2.0.3 이상으로 업그레이드하세요.
MCP 도구 인자는 공격자의 영향을 받습니다. 이들은 에이전트가 처리하는 콘텐츠 — 문서, 웹 페이지, 도구 출력 — 로부터 LLM이 생성하므로, 간접 프롬프트 주입을 통해 공격자가 도구 핸들러가 받는 값을 제어할 수 있게 됩니다. 이러한 값 중 하나라도 셸로 전달하는 핸들러는 그 영향력을 MCP 서버를 실행 중인 호스트에서의 코드 실행으로 바꿉니다. 이는 선례 사례 aws-mcp-server / CVE-2026-5058과 동일한 모델입니다.
그 결과 "호출자가 신뢰할 수 있는 LLM이다"라는 것은 완화책이 되지 못합니다. 도구 인자는 신뢰할 수 없는 입력입니다.
2.0.0의 src/helpers/runAnsible.ts는 인자 배열을 구성한 다음 셸을 활성화한 상태로 실행했습니다:
const proc = spawn(ansibleCmd[0], ansibleCmd.slice(1), { shell: true });
shell: true를 사용하면 Node는 ansibleCmd[0]을 나머지 요소들을 argv로 하여 실행하지 않는다. 대신 전체 배열을 하나의 문자열로 결합하여 /bin/sh -c에 전달하며, 요소에 대한 인용이나 이스케이프를 적용하지 않는다. 따라서 ;, &&, |, 백틱 또는 $()를 포함하는 요소는 의도된 명령에서 벗어나게 된다.
도달 가능한 경로는 executeDeployment MCP 도구(src/tools/executeDeployment.ts)이며, 이 도구는 호출자가 제공한 extraVars를 --extra-vars key=value 형태로 배열에 전달한다. ; touch /tmp/marker ; 값을 사용하면 다음과 같은 결과가 발생한다:
/bin/sh -c "ansible-playbook -i inv.ini play.yml ... --extra-vars deploy_env=; touch /tmp/marker ; echo INJECTED"
같은 버전의 보조 싱크는 projectRoot를
execSync('ansible-vault encrypt ' + vaultPath)에 보간했습니다.
poc/driver.mjs는 조작된
extraVars 값으로 runAnsible을 직접 호출하고 마커 파일을 확인합니다. ansible-playbook은
설치할 필요가 없습니다 — 선행 바이너리가 해석되는지 여부와 관계없이 주입된 명령은 동일한 /bin/sh -c
문자열에서 실행됩니다.
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
영향받는 버전에서 예상되는 결과:
{"target":"@webfer/mcp-ansible-drupal 2.0.0","sink":"runAnsible -> spawn(cmd[0], cmd.slice(1), {shell:true})","vector":"executeDeployment extraVars value","marker":"/tmp/PWNED_ansible","created":true,"verdict":"CONFIRMED - command injection executed"}
2026-06-01에 격리된 컨테이너에서 검증되었고, 2026-06-13에 무해한 touch 마커로 재검증되었습니다. 테스트 권한이 있는 인프라에 대해서만 실행하십시오.
ansible-playbook에 도달하는 --extra-vars 값 중 ;, &&, ||, |, 백틱 또는 $(를 포함하는 모든 값. 정상적인 Ansible 변수 값에는 사실상 절대 포함되지 않습니다.ansible-playbook이 그리고 구분자 뒤에 두 번째 명령이 포함된 sh -c 프로세스 — 애플리케이션 로깅에 의존하지 않는 프로세스 트리 신호(auditd, eBPF, Falco, EDR)입니다.ansible-playbook, git, ansible-vault는 예상되지만, 셸, 인터프리터 또는 네트워크 클라이언트는 예상되지 않습니다.executeDeployment 인수에 셸 메타문자가 포함된 MCP 도구 호출 로그. 도구 인수를 기록하십시오 — 대부분의 MCP 배포는 이를 기록하지 않으며, 애플리케이션 관점에서 주입된 값이 보이는 유일한 지점입니다.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
@webfer/mcp-ansible-drupal 2.0.3 이상으로 업그레이드하십시오. 현재 소스는 shell 옵션 없이 spawn(ansibleCmd[0], ansibleCmd.slice(1), { … })를 호출하므로, 배열이 argv로 전달되어 메타문자가 의미를 잃습니다.
MCP 도구 핸들러에 대한 일반 규칙이자 이 수정 사항이 여기에 적용하는 내용은 다음과 같습니다:
shell: true를 절대 활성화하지 마십시오. 배열 형식은 바로 셸을 피하기 위해 존재합니다.execFile/spawn을 사용하십시오.z.string()은 값이 문자열임을 증명할 뿐 그 안에 무엇이 있는지는 전혀 증명하지 않습니다. 값 집합이 알려진 경우 허용 목록을 사용하고, 그렇지 않은 경우 셸 메타문자를 거부하십시오.NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; CWE-78 완화 M1 및 M2.
| 날짜 | 이벤트 |
|---|---|
| 2026-06-01 | 2.0.0에 대해 취약점 동적 검증 |
| 2026-06-01 | shell: true가 제거된 2.0.3이 npm에 게시됨 |
| 2026-06-13 | 두 번째 호스트에서 재검증 |
| 2026-07-13 | MITRE CNA-LR이 CVE-2026-52618 할당, s1ko를 발견자로 크레딧 |
| 2026-08-22 | 본 분석 문서 게시 |
aws-mcp-server)동일한 연구 과정에서 나온 동반 권고문: CVE-2026-52616, CVE-2026-52617.
MIT — LICENSE 참조.