어두운 남색 바탕 위에 생성된 추상 일러스트레이션: 왼쪽의 작은 앰버색 서버 큐브가 글리프 모양의 가는 청록색 선을 내뿜고, 그 선은 길쭉한 반투명 파란 유리 막을 곧장 통과해 오른쪽의 어두운 터미널 패널까지 이어지며, 그곳에서 앰버색 커서 블록 하나가 빛납니다. 선은 끊김 없이 이어집니다. 텍스트, 사람, 조직 로고는 나타나지 않습니다. OrcaRouter 로고가 오른쪽 아래 모서리에 합성되어 있습니다.
AI Safety Incidents

OpenCode의 MCP 로그인이 서버 URL을 PowerShell에 넘겼다 — 그리고 이를 지적할 CVE는 존재하지 않는다

작성자

Magnus Corvin

게시일

최신 모델 · 20모든 모델 보기 →
벤치마크: Artificial Analysis · 매일 업데이트
모든 게시물로 돌아가기

에2026년 10월 19일Pillar Security는 원격 코드 실행 취약점을 공개했습니다. 대상은 OpenCode이며, Anomaly가 유지 관리하는 오픈소스 코딩 에이전트입니다: 개발자가 구성해 둔 원격 Model Context Protocol 서버가 MCP OAuth 로그인 중 해당 개발자 자신의 머신에서 임의 코드를 실행할 수 있었으며, 중간에 동의 프롬프트가 전혀 없었습니다. 이 버그는 Windows 및 Windows Subsystem for Linux로 한정되었는데, 여기서 OpenCode는 서버가 제공한 로그인 URL을 이스케이프하지 않고 PowerShell 명령에 넘겼습니다. Pillar는 영향을 받는 범위를 1.0.137부터 1.18.32까지로 봅니다. Anomaly는 1.18.33에서 이를 수정했으며, npm에 2026년 9월 28일에 게시했고, CVE를 요청하지 않았으며 권고문도 게시하지 않았습니다 — 따라서 일반적인 취약점 피드에서는 영향을 받는 팀에 업그레이드하라고 알려 주는 내용이 없습니다. Pillar는 이 결함이 공격에 사용된 증거를 보고하지 않았습니다. 이는 AI 사고 아카이브의 한 기록으로, 각 항목에는 자체 출처, 심각도, 신뢰도 등급 및 이견 표시 플래그가 포함됩니다.

그 결함이 실제로 무엇이었는지

MCP 클라이언트가 인증을 요구하는 원격 서버에 연결하면 OAuth 디스커버리 핸드셰이크를 실행합니다. 서버는 401과 함께 자체 디스커버리 문서를 가리키는 챌린지로 응답하며, 그 문서의 한 필드인 authorization_endpoint는 사용자를 로그인시키기 위해 어디로 보내야 하는지를 클라이언트에 알려줍니다. 이는 자유 형식 문자열이며, 인증받는 주체가 바로 이를 선택하는 주체입니다.

OpenCode 1.18.32에서 그 문자열은 네트워크에서 셸로 이동했습니다. Pillar는 서버의 디스커버리 문서에서 시작해 MCP SDK를 거쳐 oauth-provider.ts, mcp/index.ts 및 browser.ts로 이어지는 경로를 추적했으며, 끝은 open이었습니다. OpenCode가 브라우저를 실행하는 데 사용하는 작은 패키지입니다. 그 경로의 어느 것도 URL의 스킴을 확인하지 않았고, 개발자가 구성한 서버의 오리진과 비교하지도 않았습니다. 핸드셰이크는 설계상 자동입니다 — 요점은 URL을 복사하게 하지 않고 로그인 페이지로 보내는 것이므로 — 서버의 응답과 실행기 사이에는 승인 단계가 없었습니다.

The launcher is where it broke. On macOS and Linux, open passes the address as an argument vector and no shell is involved. On Windows, version 10.1.2 of open — the version every affected OpenCode release pinned — builds a PowerShell command, base64-encodes it and runs it with powershell -EncodedCommand. Pillar quotes the source: the application name is escaped on one line, and the target URL is not. PowerShell evaluates $(...) subexpressions inside double-quoted strings, so an address of the form https://evil.test/$([IO.File]::WriteAllText('C:\Users\Public\pwned.txt','RCE')) runs before the browser launch fails. OpenCode discards that failure.

두 가지 특성 때문에 놓치기 쉬웠다. 페이로드에 공백이 없어 URL 정규화를 거쳐도 그대로 남고, 구문상으로도 평범한 https 주소이기 때문이다. 또한 서버는 구성될 당시부터 악의적이었을 필요가 없었다. Pillar는 나중의 침해, 탈취된 레지스트리 항목, 타이포스쿼팅, 만료된 도메인 중 어느 하나라도 신뢰된 구성 항목을 전달 메커니즘으로 바꿔놓을 수 있다고 지적한다.

누가 노출되었나요?

노출된 집단은 원격 MCP 서버가 구성된 OpenCode를 실행하는 Windows 및 WSL 사용자입니다. Pillar는 OpenCode가 주간 npm 다운로드 약 300만 건과 GitHub 스타 211,000개를 보유하고 있다고 설명합니다; Infosecurity Magazine의 보고서는 스타 수를 218,000개 이상으로 제시합니다. 두 수치 모두 영향을 받은 설치 수를 나타내는 것은 아니며, 아무도 그 수를 발표하지 않았습니다.

트리거는 두 주요 설명이 갈리는 단 하나의 지점이며, 이는 위험도와 심각도 모두에 중요합니다. Pillar는 익스플로잇에 추가적인 사용자 상호작용이나 동의가 필요 없다고 설명합니다. The Hacker News는 10월 22일 보도에서 브라우저 단계는 개발자가 로그인을 시작할 때, 즉 opencode mcp auth를 실행하거나 그에 맞는 요청을 보낼 때만 실행되며, 서버가 구성되어 있거나 세션을 여는 것만으로는 그 단계에 도달하지 않는다고 합니다. 어느 쪽이든 개발자는 별다른 행동을 하지 않습니다. 이미 구성에 포함된 서버에 대해 인증을 시작하는 것은 일상적인 일입니다. 그러나 "상호작용 없음"과 "일상적인 상호작용 한 번"은 서로 다른 주장이며, 그 차이는 점수에 직접 영향을 줍니다.

그 수정은 리팩터링이라고 설명된 채로 도착했다

Pillar는 GitHub 보안 권고를 통해 해당 결함을 비공개로 보고했습니다. 날짜는 2026년 8월 29일이며, 완전한 재현 자료도 함께 제공했습니다. 그런 다음 2026년 9월 25일에 자문 스레드 밖에서 후속 조치를 취했습니다; Anomaly는 보고서가 자사 팀에 전달되었음을 확인했고, 악성 MCP 서버는 자사의 위협 모델 범위를 벗어난다고 답했습니다. 같은 날, 풀 리퀘스트 #51414 — 커밋 29f07e0c로 병합됨 — 가 반영되었습니다. 이는 여덟 개의 브라우저 실행 호출 지점을 하나의 헬퍼로 통합한 것으로 설명됩니다. 버전 1.18.33은 사흘 뒤인 9월 28일에 npm에 도달했습니다.

패치에는 세 개의 계층이 있습니다. open 의존성은 대상을 작은따옴표로 감싸는 11.0.4로 이동했으며, PowerShell은 작은따옴표 안의 어떤 것도 확장하지 않습니다. 새 openUrl() 헬퍼는 HTTP(S)가 아닌 스킴을 거부합니다. 스킴 검사는 redirectToAuthorization 자체, 즉 Pillar가 보고서에서 지목한 경계에 추가되었습니다. 풀 리퀘스트에도 릴리스 노트에도 보안 결함은 언급되지 않았고, Anomaly는 CVE를 요청하지 않았습니다.

The Hacker News는 Anomaly의 공개된 보안 정책에 사용자가 구성한 MCP 서버가 {{1}}우리의 신뢰 경계 밖에{{/1}} 있다고 명시되어 있으며, 회사가 올해 다른 OpenCode 코드 실행 취약점들에 대한 권고를 발표했고 그중 하나는 8월에 수정되었다고 보도했다. Pillar가 받은 답변에 대한 설명은 더 노골적이다: {{2}}"우리는 의존성을 업데이트했지만, 일반적으로 악성 MCP 서버를 다루는 것은 우리의 위협 모델 밖입니다."{{/2}}

An HTML timeline card titled 'How a five-year-old escaping bug reached OpenCode', subtitled 'Dated entries from Pillar Security's report and the open package's own issue history', listing nine rows: 22 October 2020, open issue #202 reports that a URL containing a dollar sign breaks on WSL 2; 18 October 2023, issue #323 titles 'OS command injection on windows when opening urls'; 9 July 2025, CVE-2025-6514 in mcp-remote, same sink, CVSS 9.6; 15 November 2025, open 11.0.0 quotes the PowerShell target; 7 December 2025, OpenCode calls open() with a server-supplied URL; 29 August 2026, Pillar reports privately via GitHub Security Advisory; 25 September 2026, pull request #51414 merged; 28 September 2026, OpenCode 1.18.33 published to npm, no CVE and no advisory; 19 October 2026, Pillar publishes. A footer cites Pillar Security and the open repository.

순서대로 읽어 보면, 이 타임라인은 OpenCode 버그를 5년짜리 흔적의 시작이 아니라 그 끝에 놓는다. 그 버그를 만들어낸 결함은 이미 공개되어 있었고, 그 결함을 사용한 코드 한 줄이 작성되기도 전에 수정본은 이미 배포되어 있었다.

스킴 검증이 왜 그것을 막지 못했는지

이런 부류의 버그에 대해 합의된 해결책은 URL 스킴 검증이다. 이상한 스킴은 차단하고 http와 https는 허용하는 것, 그게 전부다. MCP TypeScript SDK가 배포하는 것이고, OpenCode가 1.18.33에서 추가한 것도 바로 이것이다. Pillar의 페이로드는 https이기 때문에 이러한 검사들을 하나하나 모두 통과한다. SDK의 차단 목록은 다음을 차단한다: javascript:, data: 및 vbscript:; 더 엄격한 http/https 허용 목록은 2025년 8월 SDK 풀 리퀘스트 #841에서 제안되었지만 병합되지 않은 채 닫혔고, 한편 풀 리퀘스트 #877은 v1.17.4에서 세 가지 스킴 차단 목록을 배포했다. — 그리고 Pillar는 자사가 발표했을 당시 SDK 1.32.0에서도 여전히 그 정책이었다고 말한다. OpenCode에서 실제로 구멍을 막은 것은 보안 수정처럼 보이는 검사들이 아니라 의존성 업그레이드였다.

역사를 보면 이것을 한 프로젝트의 실수로 보기는 어렵다. open 패키지는 2021년부터 보안을 보장하지 않으며 입력 정제는 호출자의 몫이라는 README 경고를 달고 있었다. 2020년 10월, 한 사용자가 달러 기호가 포함된 URL이 WSL 2에서 일부가 사라진다고 이슈 #202를 제출했다. 문자열 확장 문제였지만 깨진 링크로 인한 불편 정도로 보고되었다. 2023년 10월, Adobe 엔지니어가 한 줄짜리 개념 증명과 함께 이슈 #323 "OS command injection on windows when opening urls"를 제출했다: open('https://$(calc.exe)'). 메인테이너는 README를 인용하며 이스케이핑을 개선하는 풀 리퀘스트는 환영한다고 말했다. 그 이슈는 "계획되지 않음"으로 종료되었는데, 그로부터 사흘 뒤인 2025년 11월 15일 open 11.0.0이 어쨌든 이스케이핑을 출시했다. OpenCode는 2025년 12월 7일, 수정된 버전의 open이 존재한 지 3주 뒤에, 이미 몇 달이나 지난 핀을 상대로 브라우저 실행 호출을 작성했다.

해당 호출이 작성되기 전 몇 달 동안 MCP 생태계는 동일한 싱크 또는 동일한 필드에서 세 개의 CVE를 기록했습니다: CVE-2025-6514가 mcp-remote에 존재하며(CVSS 9.6, JFrog가 2025년 7월 9일에 공개), CVE-2025-58062가 openmcp-client에 존재하고, CVE-2025-10619가 sequa-mcp에 존재합니다. Pillar가 대조하는 대상은 원격 문자열로 셸 명령을 전혀 구성하지 않는 클라이언트들이다: Pillar는 gemini-cli, Claude Code, github-mcp-server, Docker의 mcp-gateway를 URL을 인수 벡터로 전달하는 클라이언트로 지목하며, 이로써 문자열에 무엇이 들어 있는지라는 질문은 더 이상 결정적인 문제가 되지 않게 된다.

A generated abstract illustration on a dark navy field: a long cyan ribbon of abstract glyph shapes runs left to right and splits in two at a hollow chrome ring, which the upper branch passes straight through while the lower branch curves downward into a glowing amber terminal rectangle at bottom right. A faint dotted outline of an empty browser window floats in the upper right. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

무엇이 확립되었고, 무엇이 그렇지 않은가

이 기록은 아카이브에서 신뢰도 A 등급을 받았으며, 그 배경이 되는 보도도 신빙성이 있다. Infosecurity Magazine은 10월 20일 Pillar의 Eilon Cohen과의 자체 인터뷰를 게재했고, The Hacker News는 10월 22일 자체 보도를 냈으며, 덴마크 국가 CERT인 DKCERT는 10월 21일 Infosecurity를 인용해 해당 발견을 요약했다. 또한 Cloud Security Alliance의 연구소는 아래에 있는 단 하나의 실질적 유의 사항을 덧붙인 분석을 발표했다. 이들 중 어느 것도 최초 보도 주체가 아니며, 이들은 취약점 메커니즘과 버전, 무공지 수정에 대해 일치한다. Anomaly 자체는 이 결함에 관해 아무것도 발표하지 않았다.

공식 기록으로 확립되었습니다:

• 결함, 그 메커니즘 및 플랫폼 범위. Pillar는 특정 소스 라인을 식별하며 수정 사항은 공개된 1.18.32-to-1.18.33 diff에서 확인할 수 있습니다. 두 개의 독립적인 뉴스 보도는 동일한 데이터 흐름을 설명합니다.

• 영향을 받는 범위는 1.0.137부터 1.18.32까지이며, 수정된 릴리스는 2026년 9월 28일에 게시된 1.18.33입니다.

• CVE도 보안 권고도 존재하지 않는다는 점. 이는 확인 가능하며, 방어자에게 결정적으로 중요한 사실입니다.

• 악용된 사례가 보고된 바 없습니다. Pillar는 공격에 사용된 흔적을 발견하지 못했다고 밝혔으며, The Hacker News는 공개된 침해 지표가 없다고 언급했습니다. 공개된 지표가 없다는 것이 곧 지표가 존재하지 않는다는 증거는 아니며, 벤더의 텔레메트리 없이는 어느 쪽 해석도 확인할 수 없습니다.

확립되지 않았거나 긴장 관계에 있음:

• 9.8입니다. 그 수치는 Pillar가 제안한 CVSS v3.1 점수이지 공식 점수가 아닙니다. CVE가 없으므로 NVD 점수도, 벤더 점수도 없습니다. Cloud Security Alliance의 연구 노트는 9.8이 사용자 상호작용이 없음을 가정한다고 지적하며, The Hacker News의 트리거 설명이 맞다면 사용자 상호작용이 필요한 등급 — 약 8.8 — 이 더 적합할 것이라고 말합니다. 이 글은 그것을 확정하지 않습니다. 아카이브 자체의 고심각도 태그는 분류일 뿐 점수가 아닙니다.

• 발행일. Pillar 보고서는 머리말에 2026년 10월 19일자로 되어 있고, 두 언론 보도 모두 그 날짜를 사용한다. 반면 Pillar 자체 보고서 하단의 공개 일정에는 발행일이 10월 4일로 기재되어 있다. 아카이브에는 10월 19일이 일 단위 정밀도로 기록되어 있다.

• 노출된 인구 집단의 규모. 공개된 수치는 없습니다. 위의 다운로드 및 스타 수치는 저장소 지표일 뿐 설치 수가 아닙니다.

• 어떤 머신이 실제로 침해되었는지 여부. 이를 뒷받침하는 공개 자료는 없으며, 기록에도 실질적인 피해는 없습니다.

An HTML card titled 'Established, and not', split into two columns. The left column, headed 'Established', lists: affected versions 1.0.137 to 1.18.32, Windows and WSL only; fixed in 1.18.33 on 28 September 2026; no CVE and no security advisory issued; no exploitation reported and no indicators published. The right column, headed 'Not established', lists: official severity, since 9.8 is Pillar's proposed score with no CVE to attach it to; the publication date, 19 October in the report header and 4 October in its own timeline; the number of exposed installations; whether any host was compromised. A footer cites Pillar Security, The Hacker News and the Cloud Security Alliance research note.

변경된 내용과 해야 할 일

해결 방법은 버전 확인입니다. 다른 어떤 방법으로도 알려주지 않기 때문입니다. OpenCode 1.18.33 이상에서는 수정되었습니다. 영향을 받은 설치를 찾으려면 패키지를 직접 인벤토리해야 합니다. Pillar의 권고는 피드를 기다리는 대신 OpenCode 자체를 인벤토리하라는 것이며, Cloud Security Alliance 노트는 피드가 일치시킬 식별자가 없으므로 opencode-ai 패키지 버전을 조회하라고 제안합니다. 업그레이드할 수 없고 Windows 또는 WSL(Windows Subsystem for Linux)에서 실행하는 팀은 검토하지 않은 원격 MCP 서버를 OpenCode 구성에서 제거해야 합니다. opencode mcp list는 어떤 서버가 있는지 보여줍니다.

MCP 클라이언트를 유지 관리하는 사람이라면, Pillar의 지침은 일반적인 조언보다 더 좁습니다: URL을 인수 벡터로 전달하고 원격 문자열로 명령줄을 절대 구성하지 말며, OAuth 검색을 사용자가 구성한 서버의 오리진에 바인딩하고, 검색 문서, 서버 메타데이터 및 도구 설명자를 설정이 아닌 신뢰할 수 없는 입력으로 취급하십시오. Cloud Security Alliance 노트는 헌팅 휴리스틱을 추가합니다 — 예를 들어 OpenCode 프로세스가 powershell.exe를 -EncodedCommand와 함께 생성하는 경우처럼 — 이는 탐지 엔지니어링을 위한 제안일 뿐 게시된 침해 지표가 아니라고 강조합니다.

Console 침해가 아닙니다

Pillar의 공개는 Anomaly가 OpenCode의 호스팅 Console에 대한 별도의 침해를 확인한 지 며칠 후에 나왔다. 이 침해로 저장된 API 제공업체 키가 노출되었을 수 있다. 두 사건은 서로 관련이 없으며, Pillar의 Eilon Cohen은 Infosecurity Magazine과의 인터뷰에서 그 차이를 분명히 밝혔다. "이번 침해는 호스팅 키 프록시 뒤에 있는 레거시 시스템을 공격했고, 사용자가 그곳에 저장해 둔 제공업체 키를 노출시켰다"라고 그는 말했다. "우리가 보고한 취약점은 정반대입니다. 악의적인 원격 MCP 서버가 OAuth 핸드셰이크 중에 개발자 자신의 머신에서 코드를 실행하는 것입니다. 표적과 공격자 위치가 다릅니다." Console 침해는 아카이브에서 별도의 기록이며, 두 사건은 별개의 항목으로 읽어야 한다.

코헨의 틀에서 이 둘을 연결하는 것은 둘 다 밑에 깔린 질문입니다. "AI 코딩 도구에 자격 증명과 입력을 넘기도록 당신이 누구를 허용하는지, 그리고 그 도구가 그것들로 무엇을 하는지."

공개 격차는 버그보다 더 오래 남는 부분이다. 발견자들이 치명적이라고 평가한 결함이 의존성 버전 업데이트에서 수정되었지만, 방어자가 평소 의존하는 모든 자동 신호에는 나타나지 않는다면, 직접 인벤토리 조사만이 유일한 탐지 방법으로 남는다 — 그리고 벤더는 그러한 조사를 수행하라고 알리는 권고문을 발표하지 않았다.