5월 RubyGems에서 신규 계정이 올린 악성 gem 500개 이상이 삭제됐고, 연구진은 일부 gem이 RubyDoc.info에서 코드를 실행했다고 보고했습니다.
또 CDN 캐시 오류로 레거시 API 키가 다른 사용자에게 넘어갈 수 있는 문제가 확인돼, RubyGems는 7월 이 키를 모두 폐기했습니다.
gem을 게시하는 팀은 계정과 키를, gem을 쓰는 팀은 Gemfile.lock과 빌드 격리를 점검하세요.

무슨 일이 있었나

날짜(2026년) 확인된 내용
5월 12~16일 신규 가입 중단(시작일은 연구진 기록)
5월 악성 패키지 500개 이상 삭제(yank), 관련 계정 차단. RubyGems는 이 기간에도 기존 사용자의 설치·게시는 정상이었다고 밝힘
7월 6일·9일 레거시 API 키 캐시 노출 버그 제보, 근본 수정·CDN 캐시 비움
7월 22~23일 권고 GHSA-9j48-x3c3-mrp2 공개(CVSS 4.0 기준 7.3, CVE 없음), 레거시 키 전량 폐기
9월 11일 Nightingale Collective 보고서 공개, RubyGems 후속 입장

연구진 보고서에 따르면 5월 11~12일 2,000개가 넘는 패키지가 제출됐고, 일부 gem은 문서 옵션 파일 .yardopts로 Ruby 스크립트를 불러와 RubyDoc.info 빌드 서버에서 코드를 실행했습니다. Socket이 GemStuffer로 명명한 gem들은 영국 지방의회 공개 포털 페이지를 수집해 gem에 담아 다시 올리는 구조였습니다. 연구진은 이를 OpenAI의 AI 에이전트와 연결했고, 보도에 따르면 OpenAI는 자사 에이전트가 무해한 작업과 공개 정보 조회에 RubyGems를 썼다고 해명했습니다. RubyGems는 AI 에이전트가 만든 것인지 판단할 수 없다는 입장입니다. 연구진은 최소 6개 패키지가 아래 API 키 버그를 노렸다고 주장했고, RubyGems는 성공한 증거를 찾지 못했다고 밝혔습니다.

API 키 버그는 3.2.0 미만 클라이언트가 gem signin 때 호출하는 GET /api/v1/api_key 응답이 CDN 엣지에 캐시된 문제입니다. 같은 노드에서 다음에 로그인한 사람이 최대 1시간 동안 앞사람의 키를 받을 수 있었고, 인증 없이 반복 조회해 키를 가져갈 수도 있었습니다. 약 9년간 존재했고, 권고 시점에도 gem signin의 18%가 영향 버전이었습니다. RubyGems는 악용 흔적을 찾지 못했지만 로그는 최근 기간분만 있다고 밝혔습니다.

왜 우리 회사 문제인가

Socket은 이 gem들이 개발자를 대량 감염시키려는 설계로는 보이지 않고 상당수는 다운로드가 거의 없었다고 분석했습니다. 다만 유입 경로를 찾으려면 Bundler 설정, gem 설치 후크, CI 정의를 점검하라고 권고했습니다. Rails로 서비스하거나 Ruby 외주 코드를 받는 국내 기업이라면 아래 구조는 봐야 합니다.

  • 새 계정이 짧은 시간에 패키지를 대량으로 올렸습니다. 출처 모를 gem은 쉽게 Gemfile에 섞입니다.
  • 연구진 보고대로라면 설정 파일 하나로 문서 빌드 서버에서 코드가 돌았습니다. 사내 CI나 문서 서버가 외부 패키지 설정을 그대로 읽는다면 같은 구조입니다.
  • 3.2.0 미만으로 로그인한 적 있는 게시 계정은 키 유출을 로그로 배제할 수 없습니다.

npm 사례는 npm 미니 샤이-훌루드 웜, 외주·SaaS 점검은 공급망 보안 체크리스트에 정리했습니다.

지금 순서대로 할 일

  1. RubyGems 버전 확인. 개발자 PC와 CI 이미지에서 gem --version이 3.2.0 미만이면 올립니다. 현행 macOS 기본 /usr/bin/gem(3.0.3.1)도 해당하니 rbenv·asdf로 설치한 Ruby를 씁니다. 옛 엔드포인트가 폐기돼 3.2.0 미만에서는 이제 gem signin 자체가 되지 않습니다.
  2. 게시 계정 점검. gem마다 게시한 적 없는 버전(특히 최신보다 높은 번호), 예상 못 한 yank, 모르는 소유자, 설정한 적 없는 trusted publisher·webhook, API 키 이력을 확인합니다. 소유자는 gem owner <gem이름>으로도 봅니다.
  3. MFA를 'UI and API'로. 이 수준이어야 키가 새도 push, yank, 소유자 변경에 OTP가 필요합니다. 'UI and gem signin'에는 이 보호가 없습니다.
  4. 키 교체와 trusted publishing. CI의 RUBYGEMS_API_KEY·GEM_HOST_API_KEY에 남은 레거시 키는 새 scoped 키로 바꿉니다. GitHub Actions라면 rubygems/release-gem 액션으로 저장된 키 없이 단기 토큰으로 배포합니다.
  5. 게시하지 않는 잡의 자격 증명 제거. 테스트·빌드 러너의 ~/.gem/credentials, ~/.local/share/gem/credentials, GEM_HOST_API_KEY를 지웁니다. Socket 권고대로 이런 CI는 rubygems.org/api/v1/gems로의 HTTPS POST를 이그레스 규칙으로 막고, 게시 잡은 허용한 gem 이름만 올리게 합니다.
  6. 의존성 유입 고정. Gemfile.lock을 커밋하고 CI에서 bundle config set --local frozen true로 lockfile 밖 변경을 막습니다. PR에 새 gem이 보이면 등록일과 소유자를 확인합니다.
  7. 외부 패키지 빌드 격리. 외부 gem 문서는 네트워크·비밀값 없는 격리 러너에서 만듭니다. YARD는 .yardopts와 .document를 기본으로 읽고 --load로 스크립트를 불러올 수 있으니 --no-yardopts --no-document도 씁니다. 사내 AI 에이전트에 게시 권한을 줬다면 AI 에이전트 도구 악용도 확인하세요.

자가점검

  • 개발자 PC와 CI 이미지의 RubyGems가 모두 3.2.0 이상인가
  • 7월 말 이후 401 오류로 멈춘 gem 배포 파이프라인은 없는가
  • 우리 gem의 소유자·버전·webhook을 이번 달에 직접 봤는가
  • 게시하지 않는 CI 러너에 RubyGems 자격 증명이 남아 있지 않은가

설계 문제로 얽혀 있다면

위 7단계는 대부분 개발팀이 오늘 바로 할 수 있습니다. 다만 5·7단계처럼 CI 러너의 비밀값 보관과 외부 통신 제한이 인프라 설계와 얽혀 있다면, 클라우드·인프라 설계와 데이터 흐름을 검토하는 보안 전문 기업 SENTRIX의 보안 아키텍처 리뷰에서 범위를 상담할 수 있습니다.

이번 주 안에 CI 이미지의 gem --version부터 확인해 보세요.

참고 자료

인프라 설계와 얽힌 부분은 보안 아키텍처 리뷰로 상담하기

보안 실무 10년 전문가가 기업 환경에 맞는 방안을 제시합니다.