
※ 이 글은 2026년 8월 28일의 실제 실행 기록입니다. 발견된 취약점은 모두 수정·배포를 마친 뒤에 공개합니다.
도구 소개 글을 쓰고 나면 늘 찜찜합니다 — "그래서 실제로 쓸 만한가?"에 답을 안 했으니까요. 그래서 이번엔 순서를 바꿨습니다. 어제 글을 쓰자마자, 제가 운영하는 유틸 사이트 저장소에 바로 스캔을 걸었어요.
스캔: 명령 하나, 확인 한 번
절차는 어제 정리한 그대로였습니다. /claude-security → Scan codebase → 범위 선택. 87개 파일짜리 소형 저장소라 "전체 스캔, medium 강도, 저렴함"으로 떴고, 확인을 누르니 에이전트 팀이 움직이기 시작했어요.

▲ 범위 선택 화면. 파일 수와 상대 비용까지 알려줘서 판단이 쉬웠습니다.
인벤토리 → 위협 모델 → 컴포넌트별 조사 → 넓은 스윕 → 세 관점 검증 패널. 진행 상황이 실시간으로 뜨고, 창만 열어두면 자리를 비워도 됐습니다. 9분 26초 뒤에 끝났어요.
결과: MEDIUM XSS 3건, 오탐 0
보고서를 열자 같은 패턴 3건이 나란히 있었습니다 — 이미지 압축·변환·리사이즈 도구. 전부 DOM 기반 XSS였어요. 사용자가 고른 파일의 이름(File.name)을 이스케이프 없이 결과 테이블의 innerHTML에 그대로 넣던 코드였습니다.

▲ 세 건 모두 MEDIUM·HIGH 신뢰도, 검증 패널 만장일치. 오탐이 없어서 보고서가 짧고 읽혔습니다.
공격 시나리오도 구체적으로 적혀 있었습니다 — 파일명이 x"><img src=x onerror=alert(document.domain)>.jpg인 이미지를 사용자가 그 도구에 넣으면, 결과 테이블이 그려질 때 사이트 원본에서 임의 JS가 실행됩니다. 인상 깊었던 건 스캐너가 같은 저장소의 다른 도구 두 개(PDF 병합, JPG→PDF)는 이미 안전하게 처리하고 있다는 것까지 짚어준 점이에요 — "고치는 방법은 저기 이미 있는 그 패턴"이라고요.
재현: 진짜였다
보고서를 믿기 전에 직접 확인했습니다. 로컬 개발 서버를 띄우고, 문제의 파일명을 붙인 이미지를 압축 도구에 넣었더니 —

▲ 팝업이 떴습니다. 보고서가 맞았어요. 이 순간이 좀 서늘했습니다 — 이게 배포돼 있었으니까.
실제로 위험한 시나리오는 아니라고 스스로를 위로할 수도 있었습니다("누가 파일명을 저렇게 지어서 올려?"). 그런데 공유 링크·자동화·타인이 만든 파일을 다루는 순간 이야기가 달라지죠. 낮은 확률이라도 임의 JS 실행은 임의 JS 실행입니다.
패치: 만들어주되, 적용은 내가
"Suggest patches"를 골랐더니 항목마다 패치 생성 에이전트와 검증 에이전트가 따로 돌았습니다. 생성 에이전트가 스크래치 사본에서 수정을 만들고, 다른 에이전트가 그 diff를 독립적으로 리뷰하는 구조예요.

▲ 작성자와 리뷰어가 다른 에이전트. 지난주 글(코드 리뷰 이야기)에서 말한 원칙이 그대로 구현돼 있었습니다.
수정 자체는 한 줄짜리였습니다 — 파일명 셀을 innerHTML 대신 textContent로 채우고, 사용자가 조작할 수 없는 숫자 값(크기·비율)만 따로 삽입. 검증 노트가 정직했던 게 마음에 들었어요: "이 저장소엔 테스트 스위트가 없어서, 동작 불변은 실행 테스트가 아니라 코드 리뷰와 빌드 성공 기반"이라고 한계를 명시했습니다. AI 도구가 자기 검증의 빈틈을 스스로 적어두는 건 흔치 않죠.
적용은 제 몫이었습니다. 브랜치 만들고 git apply로 패치 3개 적용 → 빌드 통과(39페이지) → 아까 그 파일로 재확인.

▲ 같은 파일, 이번엔 팝업이 없습니다. 파일명이 잘리지 않고 통째로 "글자"로 표시됐어요 — textContent가 먹었다는 뜻입니다.
머지하고 배포까지 마쳤습니다. XSS 3건, 처리 완료.
비용: 스캔 한 번에 얼마나 쓰나
제일 궁금하실 숫자죠. /usage로 확인한 이번 작업의 실측입니다.

▲ 스캔 + 패치 한 사이클의 실측. 소형 저장소인데도 적지 않게 씁니다.
정리하면 — 파일 87개 / 소요 9분 26초 / 토큰 약 120만 / 세션 비용 $8.76 / 주간 한도의 24% 소모(마침 +50% 부스트가 8/31까지 살아있는 기간이라 체감이 덜했습니다). 멀티에이전트가 병렬로 도니 소형 저장소도 이 정도예요. "매일 CI에서 자동으로"보다는 "의미 있는 변경 때 수동으로"가 맞는 비용 감각입니다. 대형 저장소는 영역별로 쪼개 돌리라는 공식 권장이 이해됐어요.
진짜 결론: 스캐너가 못 잡은 걸 내가 잡았다
여기서부터가 이 글을 쓰는 이유입니다. 패치를 검증하려고 로컬에서 정상 이미지(PNG를 JPEG로)를 하나 압축해봤는데 — 결과가 19KB → 43KB로 커졌는데 화면엔 "+124% 절감"이라고 떴습니다. 줄어든 게 아니라 늘었는데 "절감"이라뇨.
이건 취약점이 아니라 표시 로직 버그입니다. PNG를 JPEG로 재인코딩하면 커지는 건 흔한 일이라(플랫한 그래픽·스크린샷 계열) 로직 자체는 정상 동작한 거고, 결과가 원본보다 클 때의 라벨·부호 처리가 틀린 거예요. 그런데 — Claude Security는 이걸 못 잡습니다. 보안 취약점이 아니니까요. 스캐너의 관심 밖입니다.
지난주에 "AI는 코드 안을 보고, 사람은 코드 밖을 본다"고 썼는데(그 글), 오늘 그걸 제 손으로 겪었습니다. XSS 3건은 기계가 코드 안에서 정확히 찾아냈고, "+124%가 이상하다"는 화면을 눈으로 보고 위화감을 느낀 사람이 잡았어요. 둘은 다른 종류의 결함이고, 다른 종류의 관찰자가 필요합니다.
그래서 이 UX 버그는 다음 글에서 고칩니다 — "스캐너가 못 잡은 걸 사람이 어떻게 잡고 고치는가"로요. 오늘은 여기까지가 정직한 기록입니다.
자주 묻는 질문 (FAQ)
Q. 실서비스에 돌려도 안전한가요?
A. 스캔은 로컬 세션에서 코드를 읽기만 하고, 결과 폴더 외에는 저장소를 건드리지 않습니다. 패치도 스크래치 사본에서 만들어 자동 적용되지 않고요. 다만 발견된 취약점 상세는 고치기 전까지 공개하지 마세요 — 공격 힌트가 됩니다. 이 글도 배포 완료 후에 씁니다.
Q. 스캔 결과 폴더를 커밋해도 되나요?
A. 기본적으로 폴더에 자체 .gitignore가 들어 있어 커밋에서 제외됩니다. 취약점 상세가 담기므로 그대로 두는 게 안전하고, 감사 목적으로 남기려면 접근 권한을 통제하는 곳에 따로 보관하세요.
Q. 오탐이 정말 0건이었나요?
A. 이번 87파일 스캔에서는 그랬습니다. 독립 검증 에이전트가 확인한 항목만 보고서에 올리는 구조라 오탐이 걸러지는데, 스캔은 비결정적이라 다른 저장소·다른 실행에서는 결과가 달라질 수 있습니다.
정리하면
실서비스 스캔 결과 = XSS 3건 발견·수정·배포 완료, 9분 26초, 주간 한도 24%. 도구는 기대 이상이었고, 특히 "이미 안전한 형제 코드를 근거로 제시"하는 점이 좋았습니다. 하지만 오늘 제가 가장 크게 배운 건 도구의 성능이 아니라 한계예요 — 스캐너가 XSS를 잡는 동안, +124%라는 이상한 숫자는 사람이 봐야 보였습니다. 좋은 스캐너를 붙이는 것과 사람이 화면을 계속 보는 것은 대체 관계가 아니라 보완 관계입니다. 다음 글에서 그 나머지 절반을 이어가겠습니다.
함께 보면 좋은 글
Claude Code에 보안 스캐너가 들어왔다 (사용법)
코드가 읽는 속도를 추월했다 — 위험 기반 리뷰
AI로 블로그 운영하는 실제 워크플로
참고 자료
'Claude Code' 카테고리의 다른 글
| Claude Code 한도 '영구 25% 인상'의 함정 — 9/14부터 지금보다 17% 줄어든다 (1) | 2026.08.31 |
|---|---|
| Claude Code에 보안 스캐너가 들어왔다: /claude-security 플러그인 사용법 (2026) (0) | 2026.08.26 |
| Claude Code 세션끼리 대화를 시작했다 — 크로스 세션 메시징 & 셀프호스팅 러너 (2026) (1) | 2026.08.20 |
| Claude Code 주간 한도 부스트 8/19 종료: 뭐가 줄고, 이번 주에 뭘 해야 하나 (0) | 2026.08.12 |
| Claude Opus 5 effort 설정 가이드: 언제 올리고, 언제 내리나 (2026) (1) | 2026.08.06 |