NOW Briefing
joblib.load)하는 과정에서 악성 코드가 실행되어 테넌트(고객별로 격리된 독립된 클라우드 공간) 간 격리를 우회하는 RCE(원격 코드 실행)가 발생합니다.
'Pickle in the Middle': Vertex AI SDK 버킷 선점을 통한 크로스-테넌트 RCE
■ 개요
Google Vertex AI는 머신러닝 모델을 학습·배포하는 구글 클라우드의 ML 플랫폼이고, Vertex AI Python SDK(google-cloud-aiplatform)는 이를 코드로 다루는 공식 라이브러리입니다. 이 SDK는 모델을 임시 저장소인 GCS(Google Cloud Storage) staging 버킷에 올린 뒤 Vertex AI로 전달합니다. v1.139.0·v1.140.0은 이 버킷 이름을 프로젝트 ID·리전만으로 예측 가능하게 자동 생성하고, 같은 이름이 이미 있으면 소유권 확인 없이 그대로 사용했습니다.
이 점을 노려 공격자가 그 이름의 버킷을 먼저 차지하면, 피해자가 올린 모델 파일은 악성 pickle(읽는 순간 코드가 실행되는 파이썬 객체 파일)로 바뀝니다. Vertex AI가 이 파일을 불러오는 순간 코드가 Vertex AI 서비스 권한으로 실행돼, 프로젝트 ID 하나로 남의 테넌트에서 코드가 도는 크로스-테넌트 공격이 성립합니다.
Google은 팔로알토 Unit 42의 2026-03-05 제보 직후 공지 없이 두 단계로 패치했습니다. v1.144.0(2026-03-31)이 버킷 이름 예측을 막고, v1.148.0(2026-04-15)이 버킷 소유 검증을 추가해 해소했습니다. CVE는 부여되지 않았지만, Vertex AI 사용 조직은 SDK 버전과 버킷 소유 관계를 점검해야 합니다.
■ 요약
| 항목 | 내용 |
|---|---|
| 식별자 | Unit 42 "Pickle in the Middle" (CVE 미부여) |
| 심각도 | 공식 CVSS 없음, Unit 42 평가 기준 사전 접근 없는 크로스-테넌트 RCE |
| 취약점 유형 | GCS 버킷 스쿼팅, 모델 아티팩트 교체, pickle 역직렬화 RCE (CWE-345 / CWE-502) |
| 영향/위험 |
• 프로젝트 ID·리전 조합만으로 staging 버킷 선점 가능 • Vertex AI 서비스 에이전트 권한으로 코드 실행 • 추론 결과 변조 및 학습 데이터·자격증명 노출 • 크로스-테넌트 권한 상승 |
| 취약 버전 | google-cloud-aiplatform v1.139.0, v1.140.0 (자동 생성 staging 버킷 사용 시) |
| 벤더 대응 현황 |
• v1.144.0 (2026-03-31): 버킷 이름 끝에 uuid4 토큰 추가• v1.148.0 (2026-04-15): GCS 버킷 소유권 검증 도입 |
■ 공격자가 버킷을 가로채는 원리
gcs_utils.py의 stage_local_data_in_gcs() 함수는 사용자가 staging_bucket을 명시하지 않으면 자동 생성 경로로 진입합니다. 이때 SDK는 버킷 이름을 프로젝트 ID와 리전을 단순 연결한 패턴으로 만들었고, 같은 이름의 버킷이 이미 존재하면 그대로 재사용했습니다. GCS 버킷 이름은 전역에서 유일하므로 피해자 프로젝트 ID와 리전 조합을 아는 외부 공격자가 동일한 이름의 버킷을 자기 프로젝트에 먼저 생성해도 SDK는 호출자 프로젝트 소유인지 확인하지 않았습니다.
이 재사용 로직을 차단하기 위해 벤더는 두 단계로 대응했습니다. v1.144.0은 버킷 이름 끝에 uuid4 토큰을 덧붙여 예측 가능성을 낮췄지만 기존 버킷 재사용 로직 자체는 그대로였습니다. v1.148.0은 _verify_bucket_ownership() 함수를 새로 추가했습니다. 이 함수는 버킷의 프로젝트 번호와 호출자 프로젝트 번호를 비교한 뒤 일치하지 않으면 ValueError로 거부합니다. 두 패치를 모두 반영한 v1.148.0이 완전 패치입니다.
# /* [패치 전] gcs_utils.py — staging 버킷 자동 생성 */
staging_bucket_name = project + "-vertex-staging-" + location
# 이름이 존재하면 그대로 재사용, 소유 프로젝트는 검증하지 않음
# /* [패치 후] v1.148.0 — _verify_bucket_ownership 도입 */
else:
# Verify bucket ownership to prevent bucket squatting attacks.
if not _verify_bucket_ownership(staging_bucket, project, client):
raise ValueError(
f'Staging bucket "{staging_bucket_name}" exists but does '
f'not belong to project "{project}". This may indicate a '
f"bucket squatting attack..."
)
ℹ️ INFO
v1.144.0의 uuid4 추가는 신규 자동 생성 버킷에만 영향을 줍니다.
이미 예측 가능한 이름으로 생성돼 운영 중인 staging 버킷은 자동으로 이름이 바뀌지 않으므로, v1.148.0의 소유권 검증 로직과 별개로 기존 버킷의 소유 관계를 직접 확인해야 합니다.
■ 공격 체인 시나리오
Vertex AI는 모델 서빙 컨테이너가 시작될 때 staging 버킷에 저장된 모델 파일을 내려받아 joblib.load()로 역직렬화합니다. pickle 포맷은 이 과정에서 임의의 파이썬 코드를 실행할 수 있어, 공격자가 교체한 페이로드는 피해자 프로젝트가 아니라 Vertex AI 서비스 에이전트 권한으로 실행됩니다. 추론 결과 조작, 서비스 에이전트가 접근 가능한 다른 GCP 리소스 침해, 서빙 환경 내부의 자격증명 탈취가 모두 가능합니다.
이 실행 경로에서 Unit 42 분석에 따르면 피해자가 모델을 업로드한 시점부터 서비스 에이전트가 악성 페이로드를 로드하기까지 약 2.5초가 걸렸습니다. 공격자 측 클라우드 함수가 GCS 객체 생성 이벤트를 감지해 정상 모델을 악성 모델로 덮어쓰는 방식이며, 피해자에게는 업로드가 정상적으로 끝난 것처럼 보입니다. 영향 기간 동안 자동 생성 버킷을 거쳐 배포된 모델은 모두 무결성 재검증 또는 재배포 대상으로 분류해야 합니다.
⚠️ WARN
pickle·joblib로 저장된 모델 파일은 본질적으로 코드 실행 페이로드를 담을 수 있는 포맷입니다.
Vertex AI 외에도 외부에서 수신한 .pkl·.joblib 모델을 그대로 로드하는 학습·서빙 파이프라인이 있다면 동일한 위험 모델이 적용됩니다.
■ 탐지 및 점검
• 위 공격 조건을 배제하기 위해 pip show google-cloud-aiplatform으로 운영 중인 환경에 1.148.0 미만 SDK가 설치돼 있는지 확인합니다.
• Vertex AI를 사용하는 GCP 프로젝트에서 {project_id}-vertex-staging-{region} 패턴의 버킷이 본인 프로젝트 소유인지 GCS 콘솔과 gcloud storage buckets describe로 점검합니다.
• 2026-03-31 이전부터 v1.148.0 적용 시점까지 자동 생성 버킷을 사용해 배포·재학습한 모델 목록을 산출해 무결성 재검증 대상으로 분류합니다.
• Cloud Audit Logs에서 staging 버킷에 외부 프로젝트의 서비스 계정 또는 비인가 주체가 일으킨 storage.objects.create·storage.buckets.create 이벤트를 검색합니다.
• Vertex AI 서비스 에이전트가 자기 프로젝트 외부 버킷에 접근한 흔적이 있는지 IAM 정책 변경과 데이터 액세스 감사 로그를 함께 살핍니다.
✅ CHECK
staging 버킷이 본인 프로젝트 소유인지는 GCS 버킷의 프로젝트 번호 필드로 판단해야 합니다.
버킷 이름이 본인 프로젝트 ID로 시작한다는 사실만으로는 소유권이 보장되지 않습니다.
■ 대응 방안
• 점검 결과 취약 조건이 확인되면 google-cloud-aiplatform을 v1.148.0 이상으로 즉시 업그레이드하고 의존성 잠금 파일과 컨테이너 이미지를 함께 갱신합니다.
• SDK 자동 생성 패턴 대신 사전 생성한 staging 버킷을 staging_bucket 인자로 명시해 자동 생성 경로 자체를 회피합니다.
• 영향 기간 동안 자동 생성 버킷을 거쳐 배포된 모델은 신뢰 가능한 원본에서 재패키징해 재배포하고 추론 결과 무결성을 재검증합니다.
• 노출 기간 동안 Vertex AI 서비스 에이전트가 접근할 수 있었던 GCS 객체·시크릿·하위 API 자격증명을 교체합니다.
• 자체 MLOps 파이프라인에서 GCS 버킷 이름에 무작위 접두/접미사를 강제하고, 생성 시 소유 프로젝트를 검증하는 정책을 적용합니다.
💡 TIP
Vertex AI Workbench·Pipelines·Custom Job 등 SDK를 간접 호출하는 매니지드 컴포넌트도 동일 SDK 버전을 내부적으로 사용합니다.
사용자 코드에서 SDK 버전을 고정하지 않았더라도 베이스 이미지 또는 런타임이 영향 버전에 머물러 있을 수 있으므로 빌드·런타임 이미지의 SDK 버전을 함께 점검합니다.
[참고 자료]
Unit 42 — Hijacking Vertex AI Model Uploads for Cross-Tenant RCE



