어두운 네이비 배경 위의 생성된 추상 일러스트: 왼쪽의 브라우저 창 윤곽선이 좁고 빛나는 소켓을 가로질러 오른쪽의 터미널 패널로 옅은 글리프 모양의 리본을 보낸다. 더 어두운 두 번째 리본이 아래에서 같은 소켓에 합류하며, 그 글리프들은 첫 번째와 구별할 수 없을 만큼 터미널에 도착한다. 텍스트, 사람, 조직 로고는 나타나지 않는다. OrcaRouter 로고는 오른쪽 아래의 흰색 푸터 스트립에 배치되어 있다.
AI Safety Incidents

Tencent BrowserSkill은 확장 프로그램 ID가 실제처럼 보이는지만 확인했다 — 어떤 확장 프로그램이든 에이전트에게 위조된 페이지를 제공할 수 있었다

작성자

Rowan Sterling

게시일

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

2026년 9월 17일, GitHub에 carfeii라는 이름으로 글을 올린 사용자가 Tencent의 오픈소스 BrowserSkill 프로젝트를 대상으로 이슈 #273을 열었습니다. 주장은 범위가 좁았습니다. 브라우저 확장 프로그램을 AI 에이전트에 연결하는 로컬 데몬이 어떤 확장 프로그램이 연결되었는지 확인하지 않고, 연결이 확장 프로그램처럼 보이는지만 확인했다는 것입니다. 사흘 뒤인 9월 20일, VulnCheck는 이 발견을 CVE-2026-94111로 공개하며, 데몬이 "a-p 범위의 32자로 된 chrome-extension origin을 모두 허용한다"고 설명하고, 이를 CWE-346(오리진 검증 오류)으로 분류하며, George Chen에게 공로를 돌렸습니다. 권고문은 이에 CVSS 4.0 6.9, 중간 등급을 부여했으며, 무결성 영향은 높음, 기밀성 및 가용성 영향은 낮음으로 평가했습니다. 기록 어디에도 이 결함이 사용되었다는 정황은 없습니다. 아카이브는 악용 사례를 기록하지 않았고 항목 신뢰도를 A로 평가했으며, real_harm은 false입니다. 이는 한 기록이며, 해당 기록은 AI 사고 아카이브에 있으며, 각 항목에는 자체 출처, 심각도, 신뢰도 등급 및 분쟁 플래그가 포함됩니다.

신원을 전혀 확인하지 않았던 형식 검사

기록의 중심에 있는 코드는 작습니다. crates/bsk-cli/src/daemon/ws.rs에서 함수 origin_allowed()는 WebSocket 핸드셰이크의 Origin 헤더를 받아 문자열 chrome-extension://을 제거하고, 남은 부분이 정확히 32자이며 모든 문자가 a와 p 사이에 있으면 true를 반환합니다. 이것이 전체 테스트입니다. 이 테스트는 HTTP 업그레이드 콜백 안에서 한 번 실행되며, 실패하면 메시지가 "Origin not in chrome-extension allow-list"인 403을 반환합니다. 하지만 게시된 대로라면 들어가 있어야 할 목록 자체가 없었습니다.

이 패턴은 임의적이지 않습니다. Chrome의 Manifest V3 확장 프로그램 ID는 정확히 그 열여섯 글자에서 뽑은 32자이므로, 이 검사는 실제 확장 프로그램 오리진의 형태를 올바르게 인식합니다. 결함은 모든 확장 프로그램이 그 형태를 가진다는 점입니다. 이 검사는 호출자가 브라우저 확장 프로그램처럼 보이는지만 확인할 뿐, 그것이 이 프로젝트의 브라우저 확장 프로그램인지는 결코 묻지 않습니다. 그리고 비교했어야 할 식별자는 이미 공개되어 있었습니다. 프로젝트의 README는 Chrome Web Store 등록 정보를 링크하며, 그 ID는 hhcmgoofomhgciiibhipgmgkgnoenaoi이고, 그 옆에 Edge Add-ons ID도 있습니다. 두 문자열 모두 게이트 어디에도 나타나지 않습니다.

데몬은 고정된 로컬 포트인 52800에서 수신 대기하며, 이 포트는 CLI에서 DEFAULT_WS_PORT로 선언되고 로컬 연결 경로에서 변형 없이 사용됩니다. 이 포트는 문서화되어 있고 상수이며, 사용자의 브라우저 프로필에서 이미 실행 중인 모든 것에서 접근할 수 있습니다. 위치가 권고의 벡터가 AV:L로 시작하는 이유입니다. 공격자는 머신에 거점을 확보해야 하며, PR:L은 낮은 권한의 거점이면 충분하다는 점을 나타냅니다. 동일한 프로필에 설치된 확장 프로그램이 바로 그러한 종류의 거점입니다.

그 자리의 가치와 그것이 얼마나 확립되어 있는지

권고문의 영향 설명 문장은 범위가 넓습니다. 악성 확장 프로그램을 브라우저 클라이언트로 등록한 공격자는 "AI 에이전트에 반환되는 페이지 콘텐츠, DOM, 스크린샷을 가로채고 조작할 수 있습니다." 이는 CVE, GitHub 권고 레코드 GHSA-x6f2-qp26-2xrh 및 아카이브가 모두 담고 있는 설명이며, CVSS 무결성 등급이 높음인 이유를 설명해 줍니다. 이는 또한 CVE를 할당한 주체가 작성한 요약이지, 실제로 입증된 공격에 대한 보고서는 아닙니다.

같은 주에 이슈 스레드 자체에서 더 신중한 설명이 도착했다. 9월 20일에 bb6894라는 이름으로 글을 올린 댓글 작성자는 코드를 main 기준으로 다시 확인했다고 보고했으며, 커밋 fa953dc6(9월 18일)에서 핸드셰이크 이후 외부 클라이언트가 실제로 도달할 수 있는 범위를 추적했습니다. 댓글에 따르면 대부분의 인바운드 도구 메서드는 WebSocket 피어에 UnknownMethod를 반환하고, 감사 요청은 클라이언트 자신의 기록으로 범위가 제한되며, window_closed, user_interrupt, update_interaction 같은 교차 세션 작업은 다른 브라우저가 소유한 세션에 대해서는 보호됩니다. 그 필터를 통과해 남는 것은 더 좁고, 에이전트 입장에서는 가로채기보다 오히려 더 나쁠 수 있습니다: 외부 확장 프로그램은 공격자가 선택한 instance_id로 브라우저 슬롯을 차지할 수 있고, 그것이 등록된 유일한 브라우저라면 — 콜드 스타트나 데몬 재시작 — 에이전트의 도구 요청을 받아 조작된 페이지 콘텐츠, DOM 또는 스크린샷으로 응답합니다. 댓글 작성자는 이를 "에이전트를 향한 결과 위조"이자 "에이전트의 인식으로 들어가는 채널"이라고 부릅니다. 두 번째 효과는 서비스 거부입니다: 실제 브라우저도 온라인에 있고 선택자가 없으면 세션 시작이 MultipleBrowsersOnline으로 실패할 수 있습니다.

두 설명 모두 공개적으로 입증된 적이 없습니다. 제보자는 개념 증명이 “요청 시 제공 가능”하다고 말했습니다. 아무도 그것을 공개하지 않았고, 악용 사례도 기록되지 않았습니다. 따라서 두 설명 사이의 차이는 이론과 실제 동작하는 익스플로잇 사이의 차이가 아니라, 동일한 소스 파일에 대한 두 가지 해석 사이의 차이입니다. 그리고 그 기사는 하나를 선택하기보다 둘 다를 보도합니다. 단정적으로 말할 수 있는 것은 핸드셰이크 이후 두 번째 신원 확인이 결코 없었다는 점입니다. 따라서 게이트가 허용한 것은 무엇이든 연결이 유지되는 동안 계속 허용된 상태로 남았습니다.

코드는 이미 알고 있었다

이 기록에서 가장 불편한 문서는 권고문이 아니다. 그것은 권고문이 가리키는 태그된 릴리스에 포함된, 함수 바로 위의 주석이다. 이 주석은 그 공백을 TODO(M10/M12)로 표시하고, 구축하려는 허용 목록, 즉 DaemonConfig::allowed_extension_ids 세트(구성 파일이나 페어링 흐름에서 채워짐)를 명시한 뒤, 연기된 이유를 밝힌다: "현재로서는 페어링이 팝업을 통해 이루어지기 때문에 수용 가능한 심층 방어 공백이지만, 같은 머신에 사이드로드된 확장은 현재 게이트를 통과한다."

있는 그대로 읽자면, 유지 관리자들은 게이트가 어떤 호출자를 통과시켰는지 알고 있었고, 자신들이 알고 있었다는 사실을 기록해 두고 배포했다. 그렇다고 해서 노출 범위가 권고문이 말하는 것보다 커지는 것은 아니다. 이는 덜 놀라운 일이 될 뿐이며, 질문을 “어떻게 이것이 리뷰를 통과했는가”에서 “무엇이 미뤄 둔 수정을 긴급하게 만들었을까”로 옮긴다. 완화 설계 가정은 실제이며 문서화되어 있다. 로컬 연결은 옵트인 방식이다. README에 따르면 사용자가 확장 프로그램을 설치하고 팝업을 열어 로컬 연결을 활성화해야 하며, 이 중 어느 것도 도달 가능하려면 데몬이 실행 중이어야 한다. 확장 프로그램이 설치되어 있지만 토글이 꺼져 있는 프로필이나 bsk 데몬이 실행 중이지 않은 프로필은 리스닝 대상이 아니다.

5주 후에도 게이트는 변함이 없다

An HTML timeline card titled 'From a filed issue to an unmerged patch', subtitled 'Nine dated entries in the BrowserSkill daemon origin-check record', listing: 16 September 2026 BrowserSkill extension 0.3.0 tagged; 17 September the bsk CLI 0.3.0 release, and issue #273 filed the same day at 15:14 UTC; 20 September CVE-2026-94111 published by VulnCheck and listed by NVD and GitHub, with a narrower impact analysis posted in the thread; 21 September CISA's SSVC assessment records exploitation none and automatable no; 23 September CLI 0.3.1 released with the same origin check; 28 September pull request #363 opened from a fork to pin the store extension IDs; 30 September CLI 0.3.2, same check; 15 October CLI 0.3.3, same check; 27 October issue still open and the patch still unmerged. A footer cites the GitHub issue, the VulnCheck advisory, NVD and the project's release tags, with the OrcaRouter logo in a white strip at the bottom right.

기록의 영향을 받는 범위는 "0.3.0까지"이며, 이는 CNA가 지정한 범위입니다. 그것이 저장소에서 이야기의 끝은 아닙니다. CLI의 0.3.0 릴리스는 9월 17일 02:22 UTC에 태그되었고, 이슈는 같은 날 15:14 UTC, 약 13시간 후에 제출되었습니다. 그 이후 추가로 세 번의 CLI 릴리스가 배포되었습니다 — 0.3.1 9월 23일, 0.3.2 9월 30일, 그리고 0.3.3 10월 15일 — 그리고 해당 태그 각각의 origin_allowed() 함수는 위에서 설명한 것과 동일한 검사이며, 그 위에 TODO가 여전히 있습니다. 10월 27일 기준으로 main 브랜치에도 이것이 있습니다.

수정 사항은 존재하지만 제안에 불과합니다. 9월 28일에 dangzitou라는 이름으로 글을 올린 기여자가 개인 포크에서 "fix(daemon): pin WS origin gate to BrowserSkill's own extension ids"라는 제목의 풀 리퀘스트 #363을 열었습니다. 이는 형태 테스트를 두 스토어 ID와의 비교로 대체하고, 설치 경로에서 언패키지 ID가 파생되는 사이드로드 및 개발 빌드를 위한 명시적 허용 경로로 BSK_ALLOWED_EXTENSION_IDS를 추가합니다. 풀 리퀘스트 본문은 이것이 위조 경로와 MultipleBrowsersOnline 서비스 거부 공격을 모두 막는다고 주장합니다. 10월 27일 현재 여전히 열려 있고 병합되지 않았으며, 해당 이슈도 벤더의 성명이 첨부되지 않은 채 열려 있습니다.

실질적인 결과는 수정 사항이 포함된, 업그레이드할 버전이 존재하지 않는다는 것입니다. "0.3.0 이후로 업그레이드하라"고 조언하는 사람은 아직 존재하지 않는 단계를 조언하는 것입니다. 이후 릴리스는 더 나중에 나온 것이지 수정된 것이 아닙니다. 기록의 범위는 0.3.1 이후가 깨끗하다는 진술이 아니라 CNA가 9월 20일에 평가한 범위로 읽어야 합니다.

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

• 확인됨: 태그 cli-v0.3.0의 릴리스된 소스에는 임의의 32자 a–p chrome-extension 오리진을 허용하는 오리진 게이트가 포함되어 있습니다. 리포터, CNA, 그리고 파일 자체가 이에 동의하며, 코드는 공개되어 있습니다.

• 확인된 사실: 게이트는 WebSocket 업그레이드 시 고정 로컬 포트 52800에서 한 번 실행되었으며, 이후 신원 확인은 없었습니다.

• 확인된 사항: 프로젝트 자체의 소스 주석에서 사이드로드된 확장 프로그램이 통과될 것임을 인정하면서도 허용 목록은 보류했습니다.

• 확정: CVSS 4.0 6.9 및 CVSS 3.1 6.6은 모두 VulnCheck의 점수이며, NVD에는 보조 점수로 기록되었습니다. 해당 항목에 대한 NVD 자체 상태는 Deferred로, 이는 NVD가 직접 작성한 분석을 추가하지 않고 CNA의 데이터를 게시했음을 의미합니다.

• 확인된 사항:CISA의 SSVC 평가(9월 21일자)는 악용을 '없음', 자동화 가능을 '아니요', 기술적 영향을 '부분적'으로 기록합니다. FIRST의 EPSS는 10월 26일 기준 향후 30일 내 악용 확률을 0.00135, 즉 2.9백분위수로 제시합니다.

• 확인되지 않음: 실제 환경에서의 사용 사례가 없습니다. 악용 사례도, 공개된 개념 증명(PoC)도, 영향을 받은 설치 수에 대한 정보도 없습니다. 프로젝트의 저장소 지표는 설치 수를 나타내지 않으며, 누구도 그 수치를 공개하지 않았습니다.

• 확립되지 않음: 어떤 영향 평가가 성립하는지. CNA의 "가로채기 및 조작"과 해당 스레드의 "결과 위조 및 서비스 거부"는 서로 다른 상한을 설명하며, 어느 것도 코드 검토 외에는 입증되지 않았다.

• 확인되지 않음: 결함이 0.3.0에서 멈춘다는 점. 버전 문자열은 CNA의 평가이며, 그 이후 세 개 릴리스에서 코드는 변경되지 않았고, 해당 릴리스들을 문제없다고 해소하는 벤더의 성명도 없다.

• 반박되었으나 미해결: 한 애그리게이터인 DevGuard가 출처, IOC 또는 텔레메트리 제공자를 밝히지 않은 채 이 CVE에 대해 "익스플로잇 시도가 탐지됨" 신호를 표시합니다. 이는 익스플로잇이 없다는 CISA의 기록된 평가와, 공개된 보고가 전무하다는 점에 배치됩니다. 아카이브에도 익스플로잇 기록이 없습니다. 해당 애그리게이터의 표시를 두 번째 데이터 포인트로 보지 말고 근거가 불충분한 것으로 취급하십시오.

An HTML card titled 'Established, and not', split into two columns. The left column, headed 'Established', lists: an origin gate that accepts any 32-character a-p chrome-extension origin, in the released cli-v0.3.0 source; checked once at the WebSocket upgrade on local port 52800; the project's own comment conceded sideloaded extensions pass; CVSS 4.0 6.9 and 3.1 6.6 are VulnCheck's scores, NVD status Deferred; CISA SSVC records exploitation none and automatable no; EPSS 0.00135 as of 26 October. The right column, headed 'Not established', lists: any real-world use or published proof of concept; which impact account holds, interception or result forgery; that the flaw stops at 0.3.0, since 0.3.1 to 0.3.3 carry the same check; an installation count; an unsourced aggregator claim of exploitation attempts. A footer cites VulnCheck, NVD, CISA, FIRST and the GitHub issue, with the OrcaRouter logo in a white strip at the bottom right.

왜 전송이 흥미로운 대상인가

프롬프트 인젝션 지침 대부분은 같은 경계를 긋습니다. 가져온 페이지 텍스트는 신뢰할 수 없는 것으로 취급하고, 그것을 전달하는 기제는 신뢰하는 것으로 취급합니다. 웹 페이지를 읽는 도구는 그 페이지를 읽고 있다고 가정되며, 문제는 그 페이지가 무엇을 말하는가입니다. 이 기록은 그것을 뒤집습니다. 에이전트가 페이지 콘텐츠, DOM, 스크린샷으로 받는 것은 로컬 소켓 반대편의 클라이언트가 보내기로 선택한 무엇이든이며, 그 소켓의 유일한 관문은 모든 후보가 올바르게 답할 수 있는 질문을 했습니다. 클라이언트가 외부의 것이라면, "페이지가 말하는 것을 검증하라"에는 검증할 대상이 남아 있지 않습니다.

그것이 또한 심각도가 더 높게 책정되지 않고 현재의 위치에 머무는 이유이기도 합니다. 이 공격은 로컬 공격이며, 프로필에 이미 설치된 확장 기능이나 다른 로컬 코드를 전제로 하고, 데몬이 로컬 연결이 활성화된 상태로 실행 중이어야 합니다. 이러한 조건은 이 도구의 의도된 사용자에게는 일상적이지만 그 외의 모든 사람에게는 이례적입니다. 아카이브의 중간 심각도와 피해가 없었다는 기록은 그 형태와 일관됩니다: 설계가 통제해야 했던 바로 그 경계에서 신뢰가 실제로 확장되었지만, 누군가 그것을 통과했다는 증거는 없습니다.

뒤따르는 좁은 범위의 실용적 조언은 누구도 공개한 완화책이 아니라, 코드가 남겨 둔 경계일 뿐입니다. 공개된 포트에서 핸드셰이크 시 승인이 한 번 결정되므로, 도달 가능한 표면은 데몬을 실행하는 프로필에 어떤 확장이 설치되어 있는지와 당시 해당 데몬 및 확장의 로컬 연결이 켜져 있는지에 의해 정해집니다. 확장 ID 허용 목록이 출시될 때까지는 이 두 가지 사실이 제어의 전부입니다.

A generated abstract illustration on a dark navy field: two identical hexagonal tokens of the same size and colour approach a narrow blue aperture from opposite sides; both pass through, and beyond it their outputs merge into a single stream of pale glyph shapes entering a terminal panel. A faint dotted outline of a browser window sits above. No text, people or organisation logos appear. The OrcaRouter logo is set in the white footer strip at the bottom right.

CVE-2026-94111은 두 가지 방식 중 하나로 평가될 것입니다. 풀 리퀘스트가 병합되어 이 기록이 오래 걸린 알려진 격차에 관한 짧은 항목이 되거나, 아니면 1년 후에도 같은 형태 검사가 트리에 그대로 남아 있어 이 항목이 속한 분류의 초기 사례로 인용될 것입니다. 적대적 지시를 담은 페이지가 아니라, 에이전트가 어떤 페이지를 읽고 있는지 결정하는 파이프로서 말입니다.