최근 공개된 Vercel 보안 사건은 꽤 불편한 사실을 다시 보여 줬습니다. 공격은 직접적인 비밀번호 탈취나 정면 돌파보다, 서드파티 OAuth 앱과 그 주변 토큰 체인을 통해 조직 안으로 들어왔습니다. 공개된 내용 기준으로 보면 Context의 레거시 AI Office Suite 관련 OAuth 토큰이 탈취되었고, 이 경로를 통해 Vercel 직원의 Google Workspace 접근이 이어졌으며, 그 결과 일부 환경에서 읽을 수 있었던 환경변수가 노출됐습니다. Vercel이 곧바로 민감 환경변수 기본값과 활동 로그 개선을 내놓은 것도 의미가 큽니다. 문제의 본질이 단일 취약점보다 권한 모델과 기본값 설계에 있었다는 뜻이기 때문입니다.

저는 이 사건을 단순 사고 요약보다, 2026년 개발 조직이 받아들여야 할 운영 전환 신호로 보는 편이 맞다고 생각합니다. 이제 OAuth 앱은 “로그인 편하게 붙이는 기능"이 아니라 공급망 자산입니다. 특히 AI 도구, 브라우저 도우미, 문서 자동화, 메일/캘린더 에이전트처럼 권한 범위가 넓은 도구일수록 더 그렇습니다. 이 흐름은 Workload Identity + Secretless Runtime, Tool Permission Manifest + Runtime Attestation, Passkey + Device-Bound Session이 왜 단순 보안 유행어가 아니라 실무 기본값이 되는지와도 정확히 이어집니다.

이 글에서 얻는 것

  • 왜 서드파티 OAuth 앱을 이제 공급망 대상으로 봐야 하는지 설명할 수 있습니다.
  • 플랫폼 환경변수, 토큰, 활동 로그, 민감도 기본값을 어떤 순서로 재설계해야 하는지 감을 잡을 수 있습니다.
  • MFA 강화만으로는 부족한 이유와, secretless 전환이 왜 같이 가야 하는지 정리할 수 있습니다.
  • 실무에서 승인 기준, 회전 시간, 철회 SLA를 숫자로 두는 방법을 가져갈 수 있습니다.

핵심 개념/이슈

1) OAuth 앱은 더 이상 “로그인 수단"이 아니다

개발 조직은 오래전부터 OAuth를 익숙한 편의 기능으로 다뤄 왔습니다. “Google로 로그인”, “캘린더 연동”, “메일 초안 생성”, “문서 읽기” 같은 문구는 사용자 경험 문맥에서는 가볍게 보입니다. 하지만 운영 문맥에서는 다릅니다. OAuth 앱은 결국 제3자 소프트웨어가 우리 조직 사용자 권한으로 행동할 수 있게 만드는 위임 장치입니다.

즉 질문이 바뀌어야 합니다.

  • 이 앱이 누구 대신 행동할 수 있는가
  • 어떤 스코프까지 지속적으로 가질 수 있는가
  • 토큰이 탈취되면 어느 시스템까지 가로 이동이 가능한가
  • 철회, 만료, 감사 로그가 현실적으로 가능한가

이 관점이 없으면 서드파티 앱 심사는 늘 “기능이 편한가” 중심으로 흐르고, 사고가 나면 그제야 “왜 이런 권한을 줬지"라는 뒤늦은 질문으로 돌아옵니다. 이건 IAM 문제가 아니라 개발 생산성 도구의 공급망 문제입니다.

2) 이번 흐름의 핵심은 OAuth와 플랫폼 시크릿이 한 줄로 이어졌다는 점이다

이번 사건에서 특히 많은 팀이 불편해한 포인트는, 단순히 OAuth 토큰이 위험했다는 사실이 아닙니다. 한 외부 연동 권한이 플랫폼 내부 접근과 환경변수 노출로 이어질 수 있었다는 점입니다. 여기서 중요한 교훈은 두 가지입니다.

첫째, 플랫폼 환경변수는 이름이 “non-sensitive"이든 아니든 실제로는 종종 실서비스 접근 권한을 담고 있습니다. API key, internal token, webhook secret, 서명 키, DB password가 이름만 다르게 섞여 있기 때문입니다.

둘째, 많은 팀이 환경변수를 저장 방식으로만 봅니다. 하지만 더 중요한 질문은 누가 어떤 문맥에서 읽을 수 있느냐입니다. 암호화 저장이 되어 있어도 플랫폼 내부나 권한 있는 실행 경로에서 평문으로 읽히면 blast radius는 여전히 큽니다.

이 지점에서 비밀 관리 실전, CI/CD 보안과 공급망, OAuth2/OIDC 심화를 따로 보지 말고 하나의 체계로 묶어야 합니다. 로그인, 토큰 저장, 배포 플랫폼, 시크릿 회전이 분리된 팀 구조일수록 사고 대응이 느립니다.

3) MFA 강화만으로는 절반만 맞다

사건이 터지면 거의 모든 조직이 가장 먼저 MFA 공지를 강화합니다. 물론 필요합니다. 패스키와 추가 인증은 계정 탈취 난이도를 꽤 올립니다. 하지만 이번 흐름이 보여 주는 건 정상적인 OAuth 위임 경로를 통한 접근도 충분히 큰 사고로 이어질 수 있다는 사실입니다. 즉 계정 로그인 강화를 해도, 이미 승인된 서드파티 앱 토큰이 길게 살아 있고 스코프가 넓으면 위험은 남습니다.

그래서 MFA는 필수지만 충분조건이 아닙니다. 보통 아래 네 가지가 같이 가야 합니다.

  1. 고위험 OAuth 스코프 allowlist
  2. 서드파티 앱별 토큰 만료/철회 기준
  3. 플랫폼 환경변수의 민감도 기본값 강화
  4. 장기 비밀값을 줄이는 secretless 전환

이때 Passkey + Device-Bound Session은 사용자 세션 탈취를 줄이는 층이고, Workload Identity + Secretless Runtime은 런타임에서 장기 시크릿 자체를 줄이는 층입니다. 층이 다르기 때문에 둘 중 하나만으로는 부족합니다.

4) 잘하는 팀은 앱 승인을 “보안 예외"가 아니라 “벤더 온보딩"으로 다룬다

서드파티 OAuth 앱 심사는 종종 IT 헬프데스크 티켓처럼 처리됩니다. 요청자가 “이 앱 필요해요"라고 하면, 보안팀은 스코프 몇 개만 보고 통과시키는 식입니다. 그런데 이제는 이런 방식이 위험합니다. 서드파티 OAuth 앱은 사실상 다음 항목을 같이 봐야 합니다.

  • 토큰 저장 위치와 암호화 방식
  • vendor 내부 직원 접근 가능성
  • 감사 로그 제공 여부
  • 토큰 철회 API/관리 콘솔 존재 여부
  • 세분화 스코프 지원 여부
  • 고객 데이터 학습/2차 활용 기본값
  • incident disclosure SLA

이건 거의 SaaS 벤더 심사와 같습니다. 실제로 AI 기반 문서 자동화나 브라우저 에이전트류 제품은 메일, 드라이브, 캘린더, 코드 호스팅, 티켓 시스템까지 한꺼번에 엮는 경우가 많아서 blast radius가 더 큽니다. 기능은 편하지만, 한 번 연결되면 조직 경계 안에 들어와 버립니다.

5) 2026년의 기준은 “비밀값을 더 잘 숨기는가"보다 “비밀값이 덜 필요한가"로 움직인다

이 사건이 다시 밀어 올린 방향은 분명합니다. 가능하면 장기 시크릿을 플랫폼 환경변수에 덜 두고, 런타임 신원 기반으로 바꾸는 것입니다. 이미 여러 팀이 Workload Identity + Secretless Runtime 쪽으로 가는 이유가 여기에 있습니다.

예를 들어 아래 전환은 실무 효과가 큽니다.

  • 정적 클라우드 키 → OIDC 기반 단기 자격증명
  • 장기 DB 패스워드 → 동적 자격증명 또는 short-lived token
  • 공용 webhook secret 남발 → endpoint별 key 분리 + 빠른 회전
  • 플랫폼 env var 의존 → 외부 secret manager 참조 + 최소 노출

핵심은 “시크릿 저장소를 더 안전하게 만들자"보다 시크릿 자체의 수명과 노출 면적을 줄이자입니다. 저장을 아무리 잘해도 읽을 수 있는 경로가 많으면 대응 비용은 계속 큽니다.

실무 적용

1) 의사결정 기준(숫자·조건·우선순위)

실무에서는 아래 순서가 현실적입니다.

1순위, 고위험 OAuth 인벤토리 7일 내 완료

  • Gmail/Drive/Calendar write, Git repo write, cloud admin, deployment write, issue tracker admin 스코프를 가진 앱부터 전수 조사
  • 조직 전체 앱 중 상위 고위험 20개만 먼저 봐도 효과가 큼

2순위, 철회 SLA 문서화

  • 서드파티 앱 침해 의심 시 토큰 철회 시작: 15분 이내
  • 프로덕션 시크릿 1차 회전 시작: 4시간 이내
  • 고위험 통합 전체 회전 완료 목표: 24시간 이내

3순위, 환경변수 민감도 기본값 강화

  • 새 시크릿은 기본적으로 sensitive 취급
  • “민감하지 않음” 예외는 owner, 만료일, 근거를 남길 때만 허용

4순위, 로그 보존 연장

  • OAuth 감사 로그와 플랫폼 활동 로그는 최소 180일
  • 기본 보존이 30~90일이면 사고 조사 시 부족한 경우가 많음

5순위, secretless 전환 후보 선정

  • 배포, CI, object storage, DB 접속처럼 회전 비용이 큰 경로부터 단기 자격증명으로 이동

2) 승인 테이블 예시

항목허용 기준보류 기준권장 조치
Gmail/Drive write 스코프업무 owner 명시, 만료일 존재, 로그 확인 가능개인 생산성 목적, 무기한 사용기본 보류 후 allowlist
Git repo write저장소 범위 제한, 철회 가능전체 org write, 감사 불가bot 계정 분리
Cloud/Deploy 접근최소 권한, MFA 강제, 활동 로그 제공broad admin, shared accountworkload identity 우선
플랫폼 env var 사용sensitive 기본값, rotation runbook 있음owner 불명, long-lived key 방치secret manager 이관
AI agent 연동tool/action scope 명시“allow all” 권한 요청기능 분리 후 재심사

핵심은 승인을 “가능/불가” 두 칸으로 끝내지 않는 것입니다. owner, 만료일, 철회 가능성, 로그, 회전 난이도까지 같이 봐야 합니다.

3) 운영 런북 예시

사건 대응은 아래 정도로 단순해야 실제로 굴러갑니다.

  1. OAuth 앱 식별: 어떤 vendor, 어떤 사용자, 어떤 스코프인지 파악
  2. 사용자/조직 차단: 해당 앱 revoke, 세션 재인증, 필요한 경우 조직 차단
  3. 시크릿 분류: 노출 가능성이 있는 env var를 prod, staging, low-risk로 구분
  4. 우선 회전: prod signing key, payment key, DB credential, deploy token 우선
  5. 행위 추적: 활동 로그, 배포 이력, unusual access, token usage 확인
  6. 재발 방지: 해당 앱 allowlist 재평가, 기본값 수정, secretless 후보 지정

여기서 중요한 것은 4단계 우선순위입니다. 모든 시크릿을 동시에 회전하려 하면 현장이 마비됩니다. 보통은 외부 피해 가능성이 큰 것부터 순서를 고정해 두는 편이 낫습니다.

4) 어떤 숫자를 대시보드로 봐야 하나

보안팀과 플랫폼팀이 같이 보는 숫자는 아래 정도면 충분히 강합니다.

  • 고위험 OAuth 앱 수
  • 무기한 토큰 비율
  • sensitive 미지정 시크릿 비율
  • rotation overdue 시크릿 수
  • revoke-to-complete 시간
  • 활동 로그 공백 시간
  • secretless 전환 완료 비율

제가 추천하는 초기 목표치는 이 정도입니다.

  • 고위험 앱 owner 지정률: 100%
  • 무기한 토큰 비율: 10% 미만
  • sensitive 미지정 프로덕션 시크릿: 0건 목표
  • revoke-to-complete P95: 4시간 이내
  • 활동 로그 공백: 24시간 초과 금지

이 숫자를 안 보면 매번 사고 후 회의가 추상적으로 흐릅니다. 반대로 숫자가 있으면 “이번 분기에는 고위험 앱 8개 줄이고, prod long-lived secret 12개를 identity 기반으로 치환한다” 같은 실행 항목으로 바뀝니다.

5) 작은 팀의 현실적인 도입 순서

큰 조직이 아니어도 할 수 있습니다. 보통 4주면 시작점은 만들 수 있습니다.

1주차

  • Google Workspace, GitHub, Slack, Notion, Vercel 같은 핵심 SaaS의 OAuth 앱 목록 수집
  • 고위험 스코프 기준표 작성

2주차

  • 프로덕션 env var를 sensitive/rotate-later/remove 세 그룹으로 분리
  • owner 없는 키 정리 시작

3주차

  • 배포/CI 경로에서 workload identity 또는 short-lived credential 가능한 대상 선정
  • revoke runbook과 연락 체계 문서화

4주차

  • 한 개 고위험 앱을 가정한 tabletop drill 수행
  • 15분 내 차단, 4시간 내 1차 회전이 가능한지 측정

이 정도만 해도 “문제가 생기면 누구에게서 어떤 키를 얼마나 빨리 끊을 수 있는가"가 훨씬 명확해집니다.

6) 사건 요약에서 끝내지 않고 팀 정책으로 바꾸는 30일 플랜

현장에서 자주 놓치는 부분은 사고 뉴스를 읽고 고개를 끄덕인 뒤, 실제 팀 정책은 그대로 두는 것입니다. 그래서 저는 30일 플랜으로 강제하는 편이 낫다고 봅니다.

0~3일: 가장 위험한 앱 10개를 뽑아 owner, 스코프, 마지막 사용 시점, revoke 경로를 같은 시트에 적습니다. 이 단계의 목적은 완벽한 보안 설계가 아니라, 지금 무엇이 조직 안으로 들어와 있는지 가시화하는 것입니다.

4~10일: 프로덕션 시크릿을 고객 영향 큼, 내부 운영 영향, 낮은 위험으로 나누고, 각 항목에 회전 난이도와 소유자를 붙입니다. 이 작업을 해 두면 실제 사고 때 “무엇부터 돌릴지"를 회의로 정하지 않아도 됩니다.

11~20일: GitHub Actions, 배포 플랫폼, 클라우드 접근처럼 장기 토큰 의존이 큰 경로 1개만 골라 short-lived credential 또는 workload identity로 바꿉니다. 모든 경로를 한 번에 바꾸려 하면 실패하지만, 한 경로라도 성공하면 이후 설득이 훨씬 쉬워집니다.

21~30일: 고위험 OAuth 앱 1개를 가정해 revoke-to-rotate 드릴을 실제로 돌려 봅니다. 15분 안에 차단이 되는지, 4시간 안에 1차 회전이 가능한지, 활동 로그가 충분히 남는지 확인해야 문서가 아니라 운영 체계가 됩니다.

이 플랜의 좋은 점은 조직 규모와 상관없이 적용할 수 있다는 것입니다. 작은 팀도 owner, 만료일, 회전 순서, drill 한 번만 갖춰 두면 “우리도 대응할 수 있다"는 상태로 올라섭니다.

트레이드오프/주의점

첫째, 모든 OAuth 연동을 막는 방식은 현실적이지 않습니다. 생산성 도구를 쓰지 말자는 답은 대부분 오래 못 갑니다. 그래서 중요한 건 전면 금지보다 고위험 스코프 중심 allowlist 입니다.

둘째, sensitive 기본값만으로는 충분하지 않습니다. 저장 시 읽기 보호가 개선돼도, 이미 외부 앱이 사용자 대신 행동할 수 있다면 문제는 남습니다. 저장 보안과 실행 권한은 다른 층입니다.

셋째, MFA를 과신하면 안 됩니다. MFA는 계정 탈취 방어에는 좋지만, 이미 승인된 OAuth 앱의 장기 권한 남용까지 막아 주지는 않습니다.

넷째, secretless 전환도 만능은 아닙니다. 런타임 장기 시크릿은 줄여 주지만, SaaS 앱이 문서·메일·이슈 본문에 접근하는 문제까지 사라지지는 않습니다. 데이터 접근 정책은 별도로 다뤄야 합니다.

다섯째, 로그를 오래 보관하지 않으면 사고 원인 규명이 어렵습니다. 기본 보존 기간을 그대로 두면 나중에 “무슨 토큰이 언제 쓰였는지"가 흐려지는 경우가 많습니다. 저장 비용보다 조사 실패 비용이 더 큽니다.

체크리스트 또는 연습

체크리스트

  • 고위험 OAuth 앱과 스코프가 인벤토리돼 있다.
  • 각 앱마다 owner, 만료일, 철회 경로가 문서화돼 있다.
  • 프로덕션 시크릿은 sensitive 기본값 또는 외부 secret manager 기준을 따른다.
  • 장기 토큰과 장기 자격증명을 줄이기 위한 secretless 전환 계획이 있다.
  • revoke-to-rotate 런북이 있고 최소 분기 1회 연습한다.
  • OAuth 감사 로그와 플랫폼 활동 로그 보존 기간이 180일 이상이다.
  • “allow all” 권한 요청 앱은 기본 보류한다.

연습 과제

  1. 현재 조직에서 가장 위험한 OAuth 앱 3개를 고르고, 각 앱의 스코프, owner, revoke 방법, 대체 가능성까지 한 표로 정리해 보세요.
  2. 플랫폼 환경변수 중 실제로는 민감하지만 이름만 일반값처럼 관리되는 항목을 10개만 골라 분류해 보세요. 이 작업만 해도 위험 노출이 꽤 선명해집니다.
  3. 배포 파이프라인에서 long-lived token 하나를 골라, OIDC 기반 단기 자격증명이나 외부 secret manager 참조로 바꿀 수 있는지 검토해 보세요. 보통 여기서 가장 큰 개선이 나옵니다.

관련 글

참고 링크