노출된 API 키로 인한 AI 에이전트 보안 사고로 4,000달러를 손해 본 경험
요약
노출된 API 키로 인해 발생한 AI 에이전트 보안 사고 사례와 그 위험성을 다룹니다. API 키 유출 경로와 공급망 공격(Supply Chain Attack)의 위험성을 경고하며 보안 의식의 중요성을 강조합니다.
핵심 포인트
- 프론트엔드 코드에 포함된 API 키가 Gemini API와 결합될 때 막대한 비용 피해 발생 가능
- AI 에이전트 사용 시 채팅 기록, 환경 파일 등을 통한 자격 증명 유출 위험 존재
- Axios 사례와 같은 오픈소스 패키지 공급망 공격을 통한 자격 증명 탈취 주의
확장된 FAQ 및 프레임워크 방법론이 포함된 전체 버전은 여기에서 확인하세요.
이번 달에 저는 Google로부터 이례적으로 큰 청구서를 받았습니다.
제 프로젝트의 Google API 키는 설계상 공개되어 있습니다. 프론트엔드 (frontend) 코드에 포함되는 종류이며, 이는 아키텍처적으로 정상적이고 예상된 일입니다. 그런데 그 과정 중 어딘가에서 팀원 중 한 명이 동일한 프로젝트에 Gemini API 액세스를 활성화했습니다. Gemini API는 유료이며, 비용이 많이 들고, 공격의 표적이 되기 쉽습니다. 인터넷에는 정확히 그러한 조합을 찾기 위해 공개된 리소스를 지속적으로 탐색하는 스캐너들이 돌아다닙니다. 그들이 찾아낸 것입니다. Google의 예산 경고가 도착했을 때, 피해는 이미 발생한 상태였습니다.
지원팀과의 협상 끝에 Google은 약 75%를 보상해 주었습니다. 나머지는 제 사비로 충당했습니다. 지금 바로 LinkedIn을 검색해 보시면 저와 똑같은 이야기를 가진 수십 명의 사람들을 발견할 수 있을 것입니다.
하지만 Google 청구서는 시작에 불과합니다.
아무도 명명하지 않는 AI 에이전트 보안 문제
당신이 AI 에이전트에게 Cloudflare 설정, 서버 SSH 접속, 리포지토리 (repo) 푸시, 외부 API 호출 등 실질적인 작업을 요청할 때마다, 당신은 에이전트에게 자격 증명 (credential)을 넘겨주게 됩니다. 그 자격 증명은 어딘가로 흘러갑니다. 채팅 기록 (Chat history), 환경 파일 (environment file), 프로젝트 컨텍스트 (Project context) 등 말이죠. 이 모든 곳에서 자격 증명이 밖으로 유출될 수 있습니다.
저는 예전에 API 키를 채팅창에 직접 붙여넣곤 했습니다. 그게 어떻게 들릴지 저도 잘 압니다. 솔직히 말씀드리면, 워크플로우 (workflow) 자체가 그렇게 만들어져 있었기에 매우 자연스럽게 느껴졌습니다. 에이전트에게 키가 필요하고, 저에게 키가 있으니, 끝이었습니다. 인터페이스가 저에게 보안 결정을 내리도록 요구하지 않았기 때문에, 그것이 보안 결정이라는 사실조차 인지하지 못했습니다.
이 부분은 제가 정말 못하는 분야입니다. (일회성 작업이 끝나면 키를 폐기해야 한다는 것을 알고 있습니다. 하지만 저는 같은 키를 다시 사용할지도 모른다고 스스로를 설득합니다. 3개월이 지나도 키는 여전히 활성화되어 있고, 저는 그것이 존재한다는 사실조차 완전히 잊어버리곤 합니다.)
그리고 때로는 위협이 당신이 한 행동을 통해 오지 않기도 합니다. 때로는 당신이 수년간 신뢰해 온 패키지 (package)를 통해 찾아오기도 합니다.
모두가 2시간 54분 동안 신뢰했던 패키지
2026년 3월 31일, 한 공격자가 axios의 주요 유지 관리자(lead maintainer)의 npm 계정을 탈취하여 주간 다운로드 수가 1억 회가 넘는 라이브러리에 백도어가 심겨진 두 가지 버전을 배포했습니다. 이 악성 버전들은 합법적인 crypto-js와 유사하게 보이도록 의도적으로 명명된 새로운 의존성(dependency)인 plain-crypto-js를 추가했습니다. Axios 자체 코드에서는 이를 호출한 적이 없으며, 호출할 필요도 없었습니다. 해당 의존성의 역할은 설치 시 자동으로 실행되는 것이었습니다.
유지 관리자는 자신의 공개 사후 분석(post-mortem) 게시물을 통해 해당 버전들이 UTC 기준 00:21부터 03:15까지 활성화되어 있었음을 확인했습니다. 2시간 54분 동안 말입니다.
그 시간 동안, 드롭퍼(dropper)는 macOS, Windows, Linux용 플랫폼별 페이로드(payload)를 다운로드한 뒤, 스스로를 삭제하고 깨끗한 package.json을 복구하여 증거를 인멸했습니다. 결과적으로 생성된 RAT(Remote Access Trojan)는 60초마다 명령 서버로 비콘(beacon)을 보냈습니다: 원격 셸(remote shell), 파일 브라우징, 프로세스 목록 확인, 전체 시스템 정찰 등이 포함되었습니다. Huntress는 해당 시간 동안 세 가지 운영 체제 모두에서 활발한 악용이 발생했음을 확인했습니다.
제가 소스라치게 놀란 세부 사항은 다음과 같습니다: Huntress는 현대적인 OIDC 신뢰 게시(trusted publishing)가 구성된 브랜치에서조차, CI/CD 워크플로가 폴백(fallback) 환경 변수로 수명이 긴 NPM_TOKEN을 여전히 전달하고 있다는 사실을 발견했습니다. 두 가지가 모두 존재할 때, npm은 토큰을 기본값으로 사용합니다. 더 안전한 방식이 활성화되어 있었음에도 불구하고, 아무도 제거하지 않은 레거시 자격 증명(credential)이 조용히 우선순위를 점유하고 있었기 때문에 실제로 사용되는 방식은 아니었던 것입니다.
이것은 axios가 부주의했기 때문이 아닙니다. 이것은 자격 증명이 부여된 작업이 끝난 후에도 아주 오랫동안 보이지 않게 축적되는 방식의 전형적인 모습입니다. 저는 이것이 제 자신의 실수와 정확히 일치하는 형태였기에 즉시 알아차릴 수 있었습니다.
npm install axios는 일상적인 유지보수를 수행하는 개발자의 작업이었을 수도 있습니다. 혹은 아무도 지켜보지 않는 새벽 2시에 의존성 업데이트 (dependency update)를 실행하던 에이전트의 작업이었을 수도 있습니다. 해당 패키지는 수년간 신뢰받아 왔습니다. 당신도, 당신의 에이전트도 그것에 의문을 제기할 이유가 전혀 없었습니다.
4계층 자격 증명 격리 모델 (The Four-Layer Credential Containment Model)
단 하나의 통제 수단만으로 이 문제를 완전히 해결할 수는 없습니다. 이 네 가지 계층이 하는 역할은 키가 유출될 수 있는 각 지점에서 폭발 반경 (blast radius)을 줄이는 것입니다. 이를 통해 단 한 번의 실패만으로 네 자릿수 달러의 예상치 못한 손실이 발생하는 것을 방지합니다.
| 계층 | 방지하는 것 | 소요 시간 | 생략 시 잔존 리스크 |
|---|---|---|---|
| IP / 네트워크 제한 (IP / network restriction) | 유출된 키가 지구상 어디에서나 사용되는 것 | 주요 제공업체 기준 키당 약 15분 | 운영 서버의 IP로 제한된 키는 유출되더라도 가치가 없습니다. 하지만 어떤 IP에서든 작동하는 키는 누군가 집어 들 수 있는 장전된 무기와 같습니다. |
| ... |
처음 세 가지 계층은 오늘 오후에도 바로 구현할 수 있습니다. 네 번째 계층은 문제를 좁히는 것이 아니라, 문제의 형태 자체를 실제로 변화시키는 단계입니다.
이러한 계층이 없을 때 발생하는 문제
설계상 공개된(public-by-design) 키는 자동으로 안전하다고 가정하는 것. 프론트엔드에 노출된 키는 원래의 범위 (scope) 내에서는 괜찮습니다. 하지만 선의를 가진 팀원을 포함하여 누군가가 키의 범위를 재설정 (re-scoping)하지 않고 동일한 프로젝트에서 유료 기능을 활성화하는 순간, 더 이상 안전하지 않게 됩니다.
예산 알림 (budget alert)을 안전장치로 취급하는 것. 알림이 울릴 때쯤이면 이미 지출은 완료된 상태입니다. 알림은 통지일 뿐, 사용을 중단시키는 실제 지출 한도 (spending cap)와 결합되지 않는 한 회로 차단기 (circuit breaker) 역할을 할 수 없습니다.
인기가 많다는 이유로 패키지를 신뢰하는 것. Axios는 주간 다운로드 수가 1억 회가 넘으며 현존하는 거의 모든 JavaScript 프로젝트에서 신뢰받아 왔습니다. 바로 그 인기가 해킹된 유지 관리자 계정 (compromised maintainer account)을 공격자에게 매우 가치 있게 만드는 요소입니다.
OIDC가 무엇과 함께 실행되느냐에 따라 보안 수준이 결정된다는 사실을 망각하는 것. axios 사고의 근본 원인은 신뢰할 수 있는 게시 (trusted publishing) 방식의 실패가 아니었습니다. 그것은 제거되지 않고 여전히 조용한 폴백 (fallback)으로서 활성화되어 있던 레거시 토큰 (legacy token) 때문이었습니다. 두 개의 자격 증명 (credentials)이 존재할 때 시스템이 무엇을 기본값으로 사용하는지 감사 (auditing)하는 것은, 더 안전한 방식을 채택한 이후에는 선택 사항이 아닙니다. 기존 방식은 실제로 완전히 사라져야 합니다.
워크플로가 자연스럽게 느껴진다는 이유로 채팅창에 키를 붙여넣는 것. 저에게도 그것은 자연스럽게 느껴졌습니다. 바로 그것이 문제입니다.
두 사고 모두 정교한 공격자를 필요로 하지 않았습니다. 저의 사례는 잊혀진 API 스코프 (scope) 하나가 필요했을 뿐입니다. Axios는 아무도 삭제하지 않고 방치해 둔 토큰 하나가 필요했습니다. 두 경우 모두 피해는 문제가 가시화되기 훨씬 전, 그동안 접근 가능한 상태로 남아있던 무언가에 의해 이미 결정되었습니다.
작성자: Iaroslav Belkin, 홍콩 소재 Belkin Marketing(Web3 및 AI 콘텐츠 마케팅) 설립자.
출처: Wiz 기술 분석, Huntress 사고 보고서, axios 유지 관리자 사후 분석 (post-mortem).
FAQ가 포함된 전체 기사는 여기에서 확인하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기