
생성된 앱에는 플랫폼의 분위기가 아닌 패치 소유권이 필요합니다
요약
Google Cloud의 Gemini Enterprise Agent Platform에서 발생한 SSRF 취약점 사례를 통해, AI가 생성한 코드의 보안 책임과 관리 모델을 분석합니다. 플랫폼의 템플릿이 업데이트되더라도 이미 생성 및 배포된 애플리케이션은 사용자가 직접 재생성하고 검증해야 한다는 점을 강조합니다.
핵심 포인트
- AI 플랫폼이 생성한 코드도 소프트웨어 라이프사이클과 보안 책임이 따름
- 플랫폼 템플릿 패치가 이미 배포된 생성형 앱의 취약점을 자동으로 해결하지 않음
- 생성된 애플리케이션의 운영 및 보안 소유권은 최종 사용자에게 있음
- Gemini Agent Studio의 SSRF 취약점 수정 사례를 통한 교훈
Google Cloud는 위협 모델 (threat model)보다 커피가 더 많은 일을 하고 있다면 그냥 지나치기 쉬운 작은 보안 노트를 게시했습니다.
Gemini Enterprise Agent Platform은 2026년 7월 1일 이전에 Agent Studio로 생성된 웹 애플리케이션을 위한 자동 생성된 /api-proxy 백엔드 엔드포인트에서 SSRF (Server-Side Request Forgery) 취약점을 수정했습니다. 권고 사항은 "우리가 플랫폼을 패치했으니 대시보드를 즐기세요"가 아니었습니다. 내용은 다음과 같았습니다: 만약 당신이 해당 웹 앱 코드를 7월 1일 이전에 다운로드, 생성 또는 배포했다면, 이를 다시 생성하고 새 버전을 배포하십시오.
이 부분이 흥미로운 지점입니다.
SSRF가 새로운 것이기 때문이 아닙니다. SSRF는 XML 파서 (XML parsers)에 대해 의견을 낼 수 있을 정도로 오래된 기술입니다. 흥미로운 부분은 소유권 모델 (ownership model)입니다. AI 플랫폼가 백엔드 코드를 생성했습니다. 플랫폼은 템플릿을 수정했습니다. 하지만 이미 생성된 애플리케이션들은 여전히 인간이 다시 생성하고, 재배포하고, 검증해야 했습니다.

생성된 소프트웨어의 세계에 오신 것을 환영합니다. 그것 역시 여전히 라이프사이클 (lifecycle)을 가집니다. 무례하게 들리겠지만, 사실입니다.
생성되었다는 것이 관리된다는 의미는 아닙니다
에이전트 플랫폼 (agent platforms) 주변에는 매우 유혹적인 이야기가 있습니다:
"그것을 설명하고, 버튼을 클릭하면, 앱을 얻습니다."
좋습니다. 유용하죠. 저는 유용한 버튼을 좋아합니다. 저는 OAuth 콜백 (OAuth callbacks)과 회의실에 있는 단 하나의 휴대폰에서만 깨지는 CSS를 연결하는 데 너무 많은 인생을 소비했습니다.
하지만 생성된 코드가 당신이 배포한 애플리케이션이 되는 순간, 운영 스토리 (operational story)는 바뀝니다. 그것은 더 이상 데모 아티팩트 (demo artifact)가 아닙니다. 그것은 라우트 (routes), 의존성 (dependencies), 네트워크 액세스 (network access), 권한 (permissions), 그리고 모델이 초안을 작성했더라도 당신의 것이 될 수 있는 버그를 가진 백엔드입니다.
Google의 노트는 깔끔한 사례입니다. 취약한 부분은 자동 생성된 프록시 엔드포인트였습니다. 업데이트된 백엔드는 허용된 Google Cloud 도메인으로 제한되는, 목적지 호스트 이름에 대한 더 엄격한 허용 목록 (allowlist) 검증을 포함합니다. 좋습니다. 올바른 방향처럼 들립니다.
하지만 수정 사항이 적용되기 전에 생성했다면, 이미 배포된 복사본이 마법처럼 안전해지지는 않습니다.
템플릿은 앞으로 나아갔습니다.
당신의 아티팩트(artifact)는 뒤처져 남겨졌습니다.
이것이 문제의 전부를 담은 지루한 한 문장입니다.
템플릿에도 패치 화요일(patch Tuesday)이 있습니다
우리는 모르는 척할 뿐, 일반적인 스캐폴드(scaffold)에서도 이미 이 사실을 이해하고 있습니다.
오래된 템플릿으로 Rails 앱을 생성하면 여전히 의존성(dependency) 업데이트가 필요합니다. Terraform 모듈을 복사하면 여전히 업스트림(upstream) 수정 사항을 가져와야 합니다. 내부의 골든 패스(golden path)를 통해 서비스를 부트스트랩(bootstrap)하더라도, 누군가 버그나 잘못된 기본값, 혹은 절묘한 타이밍에 비용 폭탄(cost footgun)을 발견하여 골든 패스가 변경되었을 때 이를 알 수 있는 방법이 여전히 필요합니다.
AI가 생성한 앱도 더 큰 자신감과 더 적은 수치심을 가지고 동일한 패턴을 따를 뿐입니다.
제너레이터(generator)는 단순히 코드만 생성하는 것이 아닙니다. 그것은 공급망(supply chain) 자재를 생성하고 있습니다. 즉, 보안 가정(security assumptions), 검증 규칙(validation rules), 프록시 동작(proxy behavior), 인증 연결(auth wiring), 로깅 기본값(logging defaults), 의존성 버전(dependency versions), 그리고 사고가 발생하여 유명해지기 전까지는 아무도 무시하는 작은 헬퍼(helpers)들을 생성하는 것입니다.

이는 제너레이터 벤더(vendor)에게는 하나의 라이프사이클(lifecycle)이 있고, 당신이 생성한 아티팩트에는 또 다른 라이프사이클이 있음을 의미합니다. 이 둘은 연관되어 있지만, 동일한 것은 아닙니다.
만약 벤더가 템플릿을 수정한다면, 당신은 다음과 같은 실질적인 질문에 답해야 합니다.
- 어떤 애플리케이션들이 오래된 템플릿에서 생성되었는가?
- 제너레이터의 어떤 버전이 그것들을 생성했는가?
- 팀들이 생성된 백엔드(backend)를 생성 후에 수정했는가?
- 수정 사항을 안전하게 재생성(regenerate), 패치(patch), 또는 체리픽(cherry-pick)할 수 있는가?
- 재배포(redeployment)의 책임은 누구에게 있는가?
- 프로덕션(production)에서 실제로 업데이트된 코드가 실행되고 있는지 누가 검증하는가?
만약 이 질문들이 일반적인 플랫폼 인벤토리(inventory) 작업처럼 들린다면, 그것은 실제로 그렇기 때문입니다. AI 부분이 지루한 부분을 삭제한 것이 아닙니다. 단지 지루한 부분을 잊어버리기 더 쉽게 만들었을 뿐입니다.
SSRF는 생성된 앱이 초래하는 바로 그 종류의 버그입니다
Server-Side Request Forgery (SSRF)는 마법이 아닙니다. 아주 단순한 수준에서 설명하자면, 서버 측 코드(server-side code)가 사용자가 제어해서는 안 되는 네트워크 요청을 보내도록 속아 넘어갈 때 발생하는 현상입니다. 위험한 버전은 해당 요청이 내부 서비스, 메타데이터 엔드포인트 (metadata endpoints), 관리자 패널 (admin panels), 또는 신뢰할 수 있는 클라우드 API (cloud APIs)에 도달할 때입니다.
API 프록시 (API proxy)는 이러한 종류의 버그가 나타나기 아주 자연스러운 장소입니다. 프록시 엔드포인트 (Proxy endpoints)는 요청을 받아 다른 곳으로 호출하기 위해 존재합니다. 그것이 그들의 역할입니다. 불행히도, "다른 곳을 호출한다"는 점이 바로 보안 문제가 까다로워지는 지점입니다.
허용 목록 (Allowlists)이 도움이 됩니다. 호스트 이름 검증 (Hostname validation)이 도움이 됩니다. 사설 IP 범위 (private IP ranges)를 거부하는 것이 도움이 됩니다. 링크 로컬 주소 (link-local addresses)를 차단하는 것이 도움이 됩니다. 사용자가 제어하는 전체 URL (full URLs)을 피하는 것이 훨씬 더 도움이 됩니다. 앱이 어쨌든 실수를 저지를 때 네트워크 정책 (Network policy)이 도움이 됩니다.
지루하지만 중요한 규칙은 이것입니다: 프록시는 단순히 이름표만 더 멋지게 바꾼 브라우저여서는 안 됩니다.
하지만 생성된 코드 (generated code)는 종종 데모를 작동시키는 데 최적화되어 있습니다. 프론트엔드 (frontend)를 백엔드 (backend)에 연결합니다. 호출을 수행합니다. 어색한 부분들을 숨깁니다. 프롬프트 (prompt)를 클릭 가능한 무언가로 바꿉니다. 이는 "임시" /api-proxy 경로가 프로덕션 트래픽 (production traffic)을 만날 만큼 오래 살아남기 전까지는 아주 훌륭합니다.
이것이 바로 생성된 백엔드 (generated backends)를 직접 작성한 백엔드와 동일한 의구심을 가지고 검토해야 하는 이유입니다. 어쩌면 더 엄격해야 할지도 모릅니다. 팀이 각 경로 (route)가 왜 존재하는지 완전히 이해하지 못할 수도 있기 때문입니다.
모델이 코드를 생성했습니다.
하지만 사고가 발생하면 결국 사람이 호출을 받게 됩니다.
플랫폼 팀은 생성된 코드 인벤토리가 필요합니다
실질적인 대응책은 "생성된 앱을 절대 사용하지 마라"가 아닙니다. 그것은 어리석은 일입니다. 스캐폴드 (Scaffolds)는 유용합니다. 오후 한나절 만에 작동하는 내부 도구를 배포하는 것은 진정으로 가치 있는 일일 수 있습니다. 특히 대안이 의식을 가진 스프레드시트가 되는 상황이라면 더욱 그렇습니다.
대응책은 생성된 코드를 소유권이 있는 산출물 (owned artifact)로 취급하는 것입니다.
최소한, 어딘가에 지루할 정도로 상세한 매니페스트 (manifest)가 있기를 바랍니다. 어떤 생성기 (generator)가 이 앱을 만들었는가? 어떤 템플릿 버전인가? 어떤 프롬프트 (prompt)나 설정 (configuration)을 사용했는가? 어떤 클라우드 프로젝트인가? 어떤 서비스 계정 (service account)인가? 어떤 네트워크 경로인가? 생성된 파일 중 어느 것이 여전히 대부분 업스트림 (upstream) 상태이며, 어느 것이 커스텀 코드 (custom code)가 되었는가?
벤더 (vendor)가 이런 공지사항을 게시하고, 당신이 점심시간 전까지 영향을 받는 모든 앱을 찾아내야 하는 상황이 오기 전까지는 이것이 오버헤드 (overhead)처럼 들릴 것입니다.
인벤토리 (inventory)가 없다면, 복구 계획은 고고학이 되어버립니다.
"7월 이전에 Agent Studio 웹 앱을 생성한 사람이 있나요?"
"아마도요."
"그게 어디에 배포되었죠?"
"슬랙 (Slack)을 확인해 볼까요?"
훌륭하군요. 엔터프라이즈급의 슬픔입니다.
훌륭한 플랫폼 팀은 생성된 경로를 추적하기 쉽게 만들 것입니다. 그들은 산출물 (artifacts)에 생성기 메타데이터 (generator metadata)를 찍어낼 것입니다. 그들은 템플릿의 버전을 관리할 것입니다. 그들은 재생성 (regeneration) 동작을 문서화할 것입니다. 그들은 팀들이 마치 인신공양을 치르는 의식처럼 느끼지 않고도, 오래된 생성 코드와 새로운 생성 코드를 디프 (diff) 할 수 있는 방법을 제공할 것입니다.
그리고 네, 재생성된 앱을 배포해도 안전한지 결정하기 위해서는 여전히 인간이 필요할 것입니다.
미안하지만, 소프트웨어는 여전히 소프트웨어입니다.
재생성은 마이그레이션 (migration)이다
"재생성 후 배포 (regenerate and deploy)"라는 문구는 단순하게 들립니다. 때로는 실제로 그렇습니다. 의미 있는 커스텀 변경 사항이 없는 아주 작은 내부 앱은 다시 빌드하고, 테스트하고, 배포한 뒤 다시 잊어버릴 수 있습니다.
하지만 다른 경우에는, 생성된 앱이 몇 주 동안 수정되었을 수도 있습니다. 누군가 인증 (auth)을 변경했습니다. 누군가 테넌트 라우팅 (tenant routing)을 추가했습니다. 누군가 UI를 패치 (patch) 했습니다. 누군가 "스테이징 (staging) 환경일 뿐이니까"라며 시크릿 (secret)을 추가했고, 이제 레포지토리 (repo)의 .env.example에는 작은 범죄 현장이 남겨져 있습니다.
그런 세상에서, 재생성은 마이그레이션 (migration)입니다.
새로운 템플릿에서 무엇이 변경되었는지 알아야 하고, 로컬 변경 사항을 보존하며, 프록시 (proxy) 동작을 테스트하고, 허용 목록 (allowlists)을 검증하며, 배포 설정 (deployment config)을 확인해야 합니다. 또한, 로드 밸런서 (load balancer), 캐시 (cache), 프리뷰 환경 (preview environment), 또는 agent-demo-final-v3-real이라는 이름으로 잊혀진 서비스 뒤에 이전의 취약한 경로 (route)가 여전히 살아있는지 확인해야 합니다.
AI가 생성한 코드는 마치 팀 외부에서 온 것처럼 느껴질 수 있습니다.
하지만 프로덕션 (production) 코드는 결코 팀 외부에 머물러 있지 않습니다.
내가 가장 먼저 할 일
만약 개발자가 앱을 생성하고 배포할 수 있는 플랫폼을 내가 소유한다면, 나는 네 가지 지루한 통제 장치부터 시작할 것입니다.
첫째, 생성된 모든 앱에 메타데이터 (metadata)를 찍어야 합니다: 생성기 (generator), 템플릿 버전 (template version), 생성 날짜, 소스 프롬프트 (source prompt) 또는 설정 (config), 그리고 소유 팀 (owning team).
둘째, 생성된 백엔드 (backends)를 일반적인 백엔드와 동일한 보안 검토 게이트 (security review gates)를 통과하게 해야 합니다. SSRF 점검, 의존성 스캐닝 (dependency scanning), 비밀 정보 스캐닝 (secret scanning), 인증 검토 (auth review), 네트워크 정책 (network policy) 등, 이 즐겁지 않은 모든 과정을 거쳐야 합니다.
셋째, 배포된 생성된 아티팩트 (artifacts)의 레지스트리 (registry)를 유지해야 합니다. 템플릿 권고 사항 (advisory)이 발표되었을 때 "누가 영향을 받는가?"라는 질문에 답할 수 있는 실제 인벤토리 (inventory)가 필요합니다.
넷째, 탈출구 (escape hatches)를 테스트해야 합니다. 안전하게 재생성할 수 있는가? 취약한 파일만 패치 (patch)할 수 있는가? 생성된 버전들을 비교할 수 있는가? 프로덕션에서 더 이상 이전 경로가 실행되지 않음을 증명할 수 있는가?
이 중 그 어떤 것도 화려하지 않습니다. 좋습니다. 화려함이야말로 우리가 12개의 대시보드를 가지면서도 정작 소유자는 없게 만든 원인이니까요.
핵심 (the punchline)
Agent Studio SSRF 노트는 생성된 앱에 대해 공포에 떨 이유가 아닙니다.
그것은 생성된 앱을 대하는 태도를 성숙하게 가져야 할 이유입니다.
생성된 애플리케이션도 패치 (patching), 소유권 (ownership), 인벤토리 (inventory), 검토 (review), 그리고 재배포 (redeployment)에서 예외가 될 수 없습니다. 플랫폼은 템플릿을 개선할 수 있습니다. 권고 사항 (advisory)을 발행할 수 있습니다. 더 엄격한 검증 (validation)을 추가할 수 있습니다. 하지만 일단 코드가 생성되어 당신의 계정 아래에 배포되면, 해당 아티팩트 (artifact)에 대한 라이프사이클 (lifecycle)이 필요합니다.
기존의 규칙은 여전히 유효합니다:
트래픽을 받을 수 있다면, 소유자가 필요합니다.
네트워크 호출을 할 수 있다면, 경계 (boundaries)가 필요합니다.
생성된 것이라 할지라도, 여전히 유지보수 (maintenance)가 필요합니다.
AI가 소프트웨어 운영 (operations)을 없앤 것은 아닙니다. 단지 운영이 필요한 더 많은 소프트웨어를 더 쉽게 만들 수 있게 했을 뿐입니다.
놀라운 진보입니다. 체크리스트를 준비하세요.
references
- Google Cloud release notes: Gemini Enterprise Agent Platform SSRF security update
- OWASP: Server Side Request Forgery Prevention Cheat Sheet
제 프로젝트를 테스트하기 위해 저는 Railway를 사용합니다. 시작할 때 20달러(USD)를 받고 싶다면, 이 링크를 사용하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기