OpenCode 사용자 1.4%의 AI API 키가 털렸다, 교체 순서는 이렇다
OpenCode 콘솔에 Anthropic·OpenAI·Google 키를 맡긴 사용자 1.4%가 해당됩니다. 내 키가 어디 있는지 가르는 질문 셋, 키 교체 여섯 단계, 업체별 한도 위치를 점검 순서로 정리했습니다.
1.4%. OpenCode가 이번 사고에서 밝힌 영향 비율인데, 분모가 전체 사용자가 아니라는 점을 먼저 짚어야 합니다. 호스팅 서비스인 콘솔 사용자 가운데, 외부 AI 업체 계정을 연결해 둔 사람만 해당합니다. 그 조건에 맞는 사람에게는 1.4%가 아니라 100%의 일이고, 조건에 맞지 않으면 안내 메일을 받지 않았을 것입니다. 이 글은 내가 어느 쪽인지 가리고, 해당한다면 키를 무슨 순서로 바꾸고 어디서 확인하는지를 그대로 따라 할 수 있게 적은 점검 순서입니다. 시각은 모두 UTC입니다.
결론을 하나만 먼저 적으면, 키는 OpenCode가 아니라 각 AI 업체 콘솔에서 폐기해야 멈춥니다. 복사된 키는 OpenCode 화면에서 지워도 살아 있습니다.
키가 있던 자리 셋
OpenCode는 두 부분으로 나뉩니다. 내 컴퓨터에서 도는 오픈소스 명령줄 도구와 데스크톱 앱, 그리고 선택 사항으로 쓰는 호스팅 서비스 콘솔입니다. 콘솔에서는 작업 공간(workspace)을 만들어 팀원을 초대할 수 있고, 공식 문서에 따르면 소유자와 관리자가 모델을 고르고, 작업 공간과 구성원별 월 예산을 걸고, 자기 AI 업체 계정을 연결합니다. Infosecurity Magazine 설명대로 콘솔은 그렇게 등록된 키를 보관했다가 요청 때 대신 쓰므로 팀원은 원래 키를 볼 일이 없습니다.
이번 사고는 이 보관 자리에서 났습니다. OpenCode의 안내 메일은 폐기 절차를 밟던 예전 시스템에 무단 접근이 있었고, 그 안에 있던 작업 공간 저장 키가 노출됐을 수 있다고 알렸습니다. 공동 창업자 Dax Raad는 내 컴퓨터의 앱에 설정한 키는 회사 서버로 오지 않는다고 설명했고, TechCrunch가 이를 전했습니다. 에이전트 본체는 이 사고 뒤에도 계속 갱신되어 GitHub 별은 10월 26일 기준 약 22만 2천 개, 10월 22일에는 v1.19.4가 나왔습니다.
그림 1. 내 컴퓨터, 콘솔, 업체 사이의 경계와 이번에 뚫린 자리
그림에서 볼 것은 초록 화살표와 붉은 화살표의 출발점입니다. 내 컴퓨터에만 둔 키는 업체로 곧장 가고 콘솔을 거치지 않습니다. 붉은 쪽은 콘솔이 보관하던 키가 노출되어 공격자가 업체 API를 직접 부르는 경로이고, 그 청구는 키 주인에게 갑니다. 공격자의 호출은 콘솔을 지나지 않으므로 콘솔에 건 예산은 막아 주지 못하고, 마지막 방어선은 업체 쪽 한도가 됩니다.
노출 가능 시각은 10월 17일 00:30 UTC
안내 메일은 가장 이른 노출 가능 시각을 UTC 10월 17일 00:30으로 적었고, BleepingComputer가 그 메일 화면을 보도했습니다. 이 시각 이후 주요 장면을 같은 축에 늘어놓으면 아래와 같습니다. 00:30을 뺀 시각은 각 발언·게시글에 적힌 현지 시각을 편집부가 UTC로 환산한 값입니다.
그림 2. 10월 17~19일의 대응 순서(UTC, 편집부 환산)
공지가 나온 17시 56분은 노출 가능 시각에서 17시간 반쯤 뒤입니다(편집부 계산). 사고 연표를 정리한 사이트에 따르면 공지에 앞서 17일 이른 시간부터 사용자들이 Reddit과 X에 예상 밖 사용량을 올리고 있었고, 그래서 공지 시각이 아니라 노출 가능 시각부터 확인해야 합니다. Anthropic은 영향받았다고 본 키를 폐기했고 Google도 노출된 Gemini 키를 차단했으며, OpenAI는 OpenCode와 협력해 접근을 복구하고 공격에 쓰인 크레딧을 환불하겠다고 19일에 밝혔습니다. TechCrunch가 보도한 19일 시점에도 OpenCode는 사건이 진행 중이라고 했습니다.
사용량 검토는 노출 가능 시각보다 하루 앞선 10월 16일부터 하라는 안내가 Safeguard 같은 보안 업체 글에 많고, 이 글도 그 기준을 따릅니다. 시작점을 넉넉히 잡아 두면 시각 환산이나 화면의 날짜 구분 때문에 놓치는 일이 없습니다.
메일에는 키의 끝 4자리가 적혀 있다
첫 번째 할 일은 받은편지함 검색입니다. Safeguard 보고서를 인용한 Infosecurity Magazine에 따르면 제목은 “Action Required: Potential provider key breach”입니다. 스팸함도 함께 찾으세요. 메일은 예전 시스템에 무단 접근이 있었다는 사실, 작업 공간에 저장한 업체 키가 노출됐을 수 있다는 점, 해당 키를 폐기하고 교체해 쓰는 앱을 갱신하고 최근 사용량을 살피라는 권고를 담습니다. eSecurityPlanet은 메일이 저장된 키를 작업 공간, 업체, 끝 네 글자 단위로 구분해 나열한다고 전했습니다. 그 목록이 곧 교체 대상 명단입니다. 업체 콘솔의 키 목록에서 같은 업체와 끝자리를 가진 키를 찾아 대조하세요.
메일 안의 링크는 누르지 않는다. 사고 직후에는 안내 메일을 흉내 낸 피싱이 섞이기 쉽습니다. 업체 콘솔 주소를 직접 입력하거나 즐겨찾기로 들어가 키 목록을 확인하세요.
메일이 없다면 회사 설명으로는 영향이 없습니다. 그래도 콘솔을 쓰고 있었다면 다음 절의 질문 셋을 따라가 보는 편이 확실합니다. 팀 관리자가 내 업체 키를 작업 공간에 등록해 둔 경우처럼, 내가 직접 넣지 않은 키가 있을 수 있기 때문입니다.
질문 셋으로 교체 범위 정하기
아래 그림은 내 설정을 앞에서부터 세 번 묻고, 갈래마다 무엇을 바꿀지 정합니다. 위쪽 가로줄을 따라 YES가 나오는 곳에서 아래로 내려가세요.
그림 3. 세 질문으로 가르는 교체 범위
갈래 중 가운데와 오른쪽은 해석이 필요합니다. 메일이 없는데 콘솔에 키가 있는 경우는 회사 설명상 영향 밖이지만, 교체는 몇 분이면 끝나고 콘솔에 키를 맡겨 두는 한 같은 구조의 위험은 남습니다. 오른쪽은 /connect로 넣은 키가 내 컴퓨터의 ~/.local/share/opencode/auth.json에 저장된다는 OpenCode 공식 문서 설명에서 나왔습니다. 보안 업체 StepSecurity는 이 파일에 업체가 적혀 있으면 영향 가능성을 의심하라고 권고했는데, 이는 회사 안내가 아니라 예방 차원의 권고입니다. 회사가 가리킨 대상은 콘솔 작업 공간에 저장된 키입니다.
내 컴퓨터와 프로젝트 폴더에 남은 키 찾기
로컬에서 확인할 것은 두 가지입니다. 하나는 OpenCode가 맡아 둔 업체 목록이고, 다른 하나는 프로젝트 환경 파일에 복사해 둔 키입니다. OpenCode 공식 문서는 opencode auth list로 자격 증명을 추가한 업체가 있는지 보라고 안내합니다. 파일 내용은 채팅이나 이슈에 붙여 넣지 말고 어떤 업체가 있는지만 확인하세요. Windows에서는 같은 파일이 %USERPROFILE%\.local\share\opencode\auth.json에 있습니다.
환경 파일 검색은 키 값이 아니라 파일 이름만 출력하는 -l 옵션을 씁니다. 아래 화면은 가짜 키를 넣은 예시 폴더에서 두 명령을 실제로 실행한 결과입니다.
그림 4. 읽기만 하는 점검 명령(편집부가 만든 예시 폴더, 가짜 키)
sk-ant-는 Anthropic, sk-proj-는 OpenAI 프로젝트 키, AIza는 Google 키에 흔히 보이는 시작 문자열입니다. 파일 이름이 나왔다면 거기에 옛 키가 남아 있다는 뜻입니다. 새 키로 바꾼 뒤 같은 명령을 다시 돌려 아무것도 나오지 않을 때까지 반복합니다. 다만 이 검색은 파일 이름만 보여 주므로, 나온 파일을 열어 어느 업체 키인지는 직접 확인해야 합니다.
교체 여섯 단계
순서가 중요한 이유는 서비스가 끊기는 시간과 옛 키가 살아 있는 시간을 모두 줄여야 하기 때문입니다.
- 대상 적기. 메일에 적힌 키(작업 공간·업체·끝 4자리), 콘솔 Providers 화면에 등록된 모든 키(다른 관리자가 넣은 것 포함), auth.json의 업체를 한 목록으로 모읍니다.
- 새 키 만들기. 업체 콘솔에서 도구 전용 키를 새로 발급하면서 범위를 좁히고 만료일이나 한도를 겁니다.
- 쓰는 곳 갱신. 로컬 설정, CI 작업, 서버 환경 변수, 팀원 컴퓨터, 그리고 콘솔을 계속 쓴다면 콘솔에 등록한 키까지 새 키로 바꿉니다.
- 새 키 동작 확인. 새 키로 호출 한 번이 성공하는지 봅니다.
- 옛 키 폐기. 업체 콘솔에서 옛 키를 폐기합니다. OpenCode 콘솔에서 지우는 것으로 끝내지 않습니다.
- 옛 키 거부 확인. 옛 키로 호출하면 인증 오류가 나는지 확인하되, 키 값을 셸에 직접 입력하거나 채팅에 남기지 않고 환경 변수로 주입합니다.
OpenAI 문서와 Safeguard 보고서 모두 새 키를 만들고 앱을 갱신한 뒤 확인이 끝나면 옛 키를 폐기하는 순서를 권합니다. 키가 실제로 쓰이고 있을 가능성이 큰 지금은 3단계에서 5단계까지의 간격을 몇 분으로 줄이는 것이 핵심입니다. 반대로 그 키를 쓰는 서비스가 하나도 없다면 폐기를 먼저 하고 새 키는 나중에 만들어도 됩니다. 이미 업체가 차단한 키는 호출이 오류로 끝나므로, 그 경우에는 새 키부터 만들어야 도구가 다시 돌아갑니다.
업체 화면마다 다른 폐기와 한도
같은 일을 하는 메뉴인데 업체마다 이름과 위치가 다릅니다. 아래 표는 세 업체의 공식 문서에서 확인한 것입니다.
| 업체 | 키 교체 | 호출을 멈추는 장치 | 범위를 좁히는 법 |
|---|---|---|---|
| Anthropic | 새 키 발급 후 옛 키 폐기 | Billing 페이지의 월 지출 한도. 조직 등급 상한은 Start 500달러, Build 1,000달러, Scale 20만 달러이고 그 아래로만 설정 | 작업 공간을 나눠 작업 공간별 한도를 건다 |
| OpenAI | 프로젝트 키를 만들 때 만료일 지정, 조직·프로젝트 단위로 키 수명 상한 설정 | 하드 지출 한도(도달하면 트래픽 중단). 알림 기준은 이메일만 보낸다 | 개발과 운영을 프로젝트로 분리하고 프로젝트별 한도를 건다 |
| 키 상세에서 Rotate key, 앱을 새 키로 바꾼 뒤 Previous key에서 옛 키 삭제 | 사용량은 Cloud Monitoring과 Cloud Logging으로 감시 | API 제한과 애플리케이션 제한(웹 주소, IP, Android, iOS 중 하나)을 함께 건다 |
Anthropic에서는 한 가지 함정이 있습니다. 문서에 따르면 기본 작업 공간에는 지출 한도를 걸 수 없으므로, 별도 작업 공간을 만들고 그 안에서 도구용 키를 발급해야 작업 공간 한도가 적용됩니다.
한도는 새 키를 만들 때 같이 건다. 교체가 끝난 뒤에 걸려고 미뤄 두면 대개 잊습니다. 피해액은 도난 키에 걸린 한도와 사용자가 키를 끈 시점에 따라 갈렸습니다.
Google은 두 가지를 더 알아 두면 좋습니다. 공식 문서에 따르면 삭제한 키는 30일 안에 복원할 수 있으므로, 폐기한 키를 실수로 되살리는 “Restore deleted credentials” 메뉴는 건드리지 않습니다. 그리고 제한이 없는 키는 아래 명령으로 찾을 수 있습니다. 읽기만 하며, PROJECT_ID는 내 프로젝트로 바꿉니다.
gcloud asset list --project=PROJECT_ID \
--asset-types=apikeys.googleapis.com/Key \
--content-type=resource \
--filter="-resource.data.restrictions:*"
노출된 Gemini 키를 차단한 Google은 새 키를 AI Studio에서 만들라고 안내했습니다(eSecurityPlanet).
낯선 호출은 이렇게 찾는다
키를 바꿨다면 이미 쓰인 흔적이 있는지 봅니다. 업체마다 화면이 다르지만 보는 기준은 같습니다.
- 기간. 10월 16일(UTC)부터 지금까지로 잡습니다.
- 화면. Anthropic은 Console의 Usage 페이지, OpenAI는 Billing과 사용량 화면, Google은 Cloud Monitoring과 Cloud Logging에서 키나 프로젝트별로 봅니다.
- 찾을 것. 내가 쓰지 않은 모델, 평소 안 쓰던 시간대의 호출, 갑자기 솟은 비용, 낯선 자동 충전 결제입니다.
- 남길 것. 발견하면 키 끝 4자리, 호출 시각, 금액이 보이는 화면을 저장해 둡니다. 환급 신청에 쓰입니다.
OpenCode 콘솔을 쓴다면 콘솔 쪽도 살펴야 합니다. 문서에 따르면 콘솔에는 잔액이 모자랄 때 크레딧을 사들이는 자동 충전이 있으므로, 켜 두었다면 결제 내역과 구성원별 예산을 함께 확인하세요. 청구가 업체 계정으로만 오는 것은 아닙니다.
BleepingComputer에는 이번 사고로 Google 프로젝트가 정지됐다는 사용자 보고도 실렸습니다. 사유는 탈취된 자원과 일치하는 악용 활동이었다고 합니다. 사용량 화면이 정상이라도 프로젝트 상태 알림이 있는지 보세요.
청구서가 이미 왔다면
환급은 세 갈래로 진행 중입니다. Raad는 10월 18일 00:01 UTC 무렵 영향받은 사용자 모두에게 연락했고 환급이 진행 중이라고 밝혔습니다(사고 연표 정리 사이트 기준, 편집부 환산). OpenAI는 19일에 공격에 쓰인 크레딧을 API 고객에게 환불하겠다고 밝혔고, 안내 메일은 Google과도 사기성 청구 보상을 논의하고 있다고 적었습니다. 업체별 신청 방법은 다르니 해당 업체 지원 창구로 진행합니다.
사용자들이 올린 금액은 아래와 같습니다. 이 그림은 크기를 견주기 위한 것이지 피해 규모를 합산하려는 것이 아닙니다.
그림 5. 자체 보고된 무단 청구액(달러, 서로 다른 사용자·업체·시간)
A는 한 사용자가 OpenAI와 Anthropic에서 각각 받은 청구, B는 다른 사용자가 키를 끄기 전까지 쌓인 OpenAI 사용량으로 700달러를 넘었고, C는 하룻밤에 1,700달러쯤 청구됐다고 보고한 경우입니다(Dealroom 정리). 막대 길이가 다른 이유는 도난 키에 걸린 한도, 공격자가 호출을 이어 간 시간, 사용자가 키를 끈 시점의 차이입니다. OpenCode나 업체가 확인한 금액이 아니므로 합산하거나 평균 내지 않습니다.
이 구도에서 최대 손실을 정하는 것은 한도입니다. 직접 한도를 걸지 않았다면 Anthropic은 조직 등급 상한이 이론상의 최대 지출이므로, 자동 충전을 켜 두었거나 팀 계정을 쓴다면 직접 한도를 더 낮게 거는 편이 안전합니다.
증류라는 이름표와 막혔던 조사
OpenCode는 이번 사건을 “대규모 증류 공격”이라고 불렀습니다. 증류는 강한 모델의 답변을 대량으로 모아 더 작은 모델을 가르치는 기법이고, 남의 모델을 복제하는 수단이 되면 공격으로 분류됩니다. Anthropic은 2026년 2월 글에서 약 2만 4천 개의 가짜 계정으로 1,600만 건이 넘는 대화를 모은 사례를 공개했고, 계정 하나가 막혀도 다른 계정이 바로 대신하는 구조였다고 설명했습니다. 신규 계정은 검증에 걸리지만 정상적으로 요금을 내 온 고객의 키는 이미 신뢰받는 통로이므로 키를 훔치는 편이 낫다는 분석이 한 글에서 추론으로 제시됐습니다. 다만 증류라는 규정은 회사의 표현이고, 일부는 단순한 침해로 본다고 TechCrunch가 전했습니다. 사용자가 치르는 비용은 어느 쪽이든 같습니다.
조사 과정에서는 다른 일이 있었습니다. BleepingComputer에 따르면 OpenCode가 쓰던 AI 모델들이 안전장치 때문에 방어 목적의 요청까지 거부해 조사가 막혔고, OpenAI의 방어자용 프로그램 Daybreak에 접근한 뒤 상황이 나아졌습니다. TechCrunch에 따르면 접근한 것은 검증된 사용자에게 방어 작업을 거부할 가능성이 낮은 모델을 주는 Daybreak Blue입니다. TechCrunch는 7월 Hugging Face 사고에서도 안전장치가 대응자와 공격자를 구분하지 못한 일이 있었다고 적었습니다. 공격자는 AI 에이전트로 최소 48시간을 쉬지 않고 두드렸는데 방어하는 쪽은 같은 AI에게 거절당한 셈입니다.
한도에 닿으면 나오는 응답
새 키에 한도를 걸었다면 그 한도에 닿을 때 무엇이 나오는지 알아 두어야 합니다. 한도 오류를 재시도로 풀려다 CI가 계속 실패하는 일이 흔하기 때문입니다. Anthropic 문서는 두 경우를 구분합니다.
- 조직 등급 상한에 닿았을 때: HTTP 429이고
error_code는enforced_spend_limit_reached입니다.retry-after헤더가 없으며 다음 달 1일 00:00 UTC까지 호출이 멈춥니다. SDK의 자동 재시도로도 풀리지 않습니다. - 직접 건 한도에 닿았을 때: HTTP 400이고 오류 유형은
invalid_request_error입니다. 메시지가 “You have reached your specified API usage limits”로 시작하고, 작업 공간 한도라면 “specified workspace API usage limits”로 시작하며, 언제부터 다시 쓸 수 있는지 함께 적습니다. 한도를 올리거나 지우면 바로 풀립니다.
OpenAI의 하드 한도는 도달하면 해당 트래픽을 멈추고, 알림 기준은 이메일만 보내고 아무것도 막지 않습니다. 갑자기 이 오류가 나오는 것은 장애이면서 동시에 낯선 호출이 있다는 신호일 수 있으니, 원인을 사용량 화면에서 먼저 확인하세요.
교체를 끝낸 뒤 일주일쯤 지나 확인할 것은 네 가지입니다.
- 폐기한 옛 키로 호출하면 여전히 인증 오류가 나는가(키 값은 환경 변수로 주입).
- 세 업체의 사용량이 평소 수준으로 돌아왔고, 새 한도의 알림 메일이 도착하는가.
- 환급을 신청했다면 OpenCode, OpenAI, Google 각각의 진행 상태.
- 콘솔을 계속 쓴다면 등록한 키가 이 용도만을 위해 만든 전용 키인가(운영 키가 아닌가).