글쓰기
프롬프트 한 줄과 Claude Fable 5로 API 보안 취약점 5건을 고친 이야기
VLOP 투명성 대시보드 뒤에는 작은 FastAPI 서비스가 돌아갑니다. TikTok Research API를 본뜬 구조화 쿼리 API로, 집계된 EU DSA 투명성 데이터를 제공합니다. 일부 엔드포인트 — 인터랙티브 쿼리 빌더, 자연어 "질문" 상자, 개요 피드 — 는 의도적으로 공개되어 있습니다. 취미 규모 서비스의 공개 엔드포인트야말로 보안 부채가 조용히 쌓이는 곳입니다. 아무것도 들여다보라고 강제하지 않기 때문입니다.
그래서 Anthropic의 새로운 Claude 5 패밀리 첫 모델인 Fable 5를 탑재한 Claude Code에 들여다봐 달라고 했습니다. 프롬프트는 한 줄: "API 보안 점검을 실행하고 취약점이 있으면 고쳐줘." 돌아온 것은 각각 회귀 테스트가 딸린 다섯 건의 수정과, 자기 diff에 대한 셀프 리뷰가 포함된 풀 리퀘스트였습니다.
발견된 문제
웹훅 콜백의 SSRF 틈새. 이 API는 쿼리에 callback_url을 지정하면 작업 완료 시 해당 URL로 POST를 보냅니다 — 전형적인 서버 사이드 요청 위조(SSRF) 공격면입니다. 기존 가드는 사설, 루프백, 링크로컬, 클라우드 메타데이터 대역을 차단했지만, 차단 목록 방식은 이 문제에 맞지 않는 형태였습니다. 캐리어급 NAT(100.64.0.0/10)처럼 사설도 공인도 아닌 대역을 놓치고 있었던 것입니다. 수정은 검사를 뒤집어, 콜백 대상이 전역 라우팅 가능하지 않으면 거부하도록 했습니다.
CSV 수식 인젝션. 쿼리 결과는 CSV로 내보낼 수 있고, 데이터셋에는 제3자 투명성 보고서에서 온 자유 텍스트 필드가 포함됩니다. =, +, -, @로 시작하는 셀은 Excel이나 Sheets에서 여는 순간 수식으로 실행됩니다 — 즉 다른 회사가 공표한 보고서 속 값이 연구자의 컴퓨터에서 코드를 실행할 수 있다는 뜻입니다. 이런 접두사를 가진 텍스트 셀은 이제 서버 측과 대시보드의 클라이언트 측 내보내기 양쪽에서 무력화됩니다.
무제한 요청 본문과 쿼리 복잡도. 공개 쿼리 엔드포인트는 인증 없이 구조화 쿼리 모델 전체를 받습니다. 요청 본문 크기에도, 쿼리에 쌓을 수 있는 조건 수에도 상한이 없었습니다. 이제 한도를 넘는 본문은 파싱 작업에 들어가기 전에 413으로 거부되며, 쿼리 모델 자체가 조건당 값 개수, 절당 조건 수, 요청당 필드 수를 제한합니다.
API 키 검증의 타이밍 부채널. 키는 딕셔너리 조회로 검증되었는데, 첫 번째로 다른 문자가 나오는 순간 비교가 중단됩니다 — 원리상 응답 시간으로 키 접두사가 새어 나갑니다. 이제 설정된 모든 키에 대해 상수 시간 비교를 수행합니다.
그 밖의 자잘한 보강 — 페이지네이션 파라미터 상한 같은, 체크리스트를 전수 점검하면 나오지만 바쁜 메인테이너는 놓치는 종류의 항목들입니다.
놀라웠던 부분
이 풀 리퀘스트는 또 다른 AI인 Gemini Code Assist의 자동 리뷰를 트리거했고, 두 건의 제안이 달렸습니다. Fable 5는 행동하기 전에 두 제안을 실제 소스 코드와 대조했고 — 그중 하나에서 봇의 논증이 불완전하다는 것을 짚어냈습니다. Gemini는 공격자가 임의 길이로 줄 수 있는 Content-Length 헤더를 정수로 파싱하면 CPU를 소모할 수 있다고 지적했습니다. 맞는 말이지만 사소합니다. 더 날카로운 문제는, Fable 5가 답글에서 짚고 설명했듯, Python 3.11+는 약 4,300자리를 넘는 정수 파싱을 거부하고 예외를 던지기 때문에, 병적인 헤더는 의도된 413이 아니라 500 오류를 냈을 것이라는 점입니다. 또한 Gemini의 하드코딩된 수정안을 설정된 한도를 따라가도록 일반화하고, 5,000자리 헤더를 보내는 회귀 테스트도 추가했습니다. AI가 다른 AI가 첫 번째 AI의 코드에 남긴 리뷰를 리뷰하고, 그 견해 차이에서 옳은 쪽에 서는 것 — 2026년 제 예상 빙고판에는 없던 일입니다.
여기서 얻은 것
이는 전에 쓴 컴플라이언스 업무에서의 LLM 활용과 운율이 맞습니다. 승부처는 검증 가능한 산출물이 있는 구조화된 작업입니다. 작은 코드베이스의 보안 전수 점검이 바로 그것입니다 — 유한한 체크리스트(인젝션 표면, SSRF, 부채널, 자원 고갈)를 빠짐없이 적용하고, 모든 발견은 코드를 읽어 확인할 수 있으며, 모든 수정은 테스트로 고정할 수 있습니다. "빠짐없고 지루한" 영역이야말로 이제 모델이 지친 인간을 안정적으로 이기는 곳입니다.
판단은 제 몫으로 남았습니다. 메트릭 엔드포인트를 무인증으로 둘지, 데모 키를 프로덕션 밖에서 허용할지, 데모 서비스에 인메모리 작업 저장소면 충분한지 — 이것들은 이 서비스가 무엇을 위한 것인지에 관한 위협 모델 차원의 판단이고, 모델도 그것을 대신하는 척하지 않았습니다. 테스트를 포함한 전체 diff는 풀 리퀘스트에 있습니다. 테스트 스위트는 122건, 모두 통과입니다.