← 블로그로
Ai약 14 분 읽기

Cloudflare가 자사 감사 도구를 공개했다, 핵심은 '반박' 구조

게시일 2026년 10월 28일
Cloudflare가 자사 감사 도구를 공개했다, 핵심은 '반박' 구조

Cloudflare가 이번 주 코딩 에이전트를 보안 감사자로 바꿔주는 스킬을 공개했고, 그것은 GitHub 주간 순위에서 가장 빠르게 성장한 저장소가 됐다. 7일 동안 약 16,400개의 스타, 누적 51,000개. 회사 측의 설명은 유난히 겸손하다. 자사 내부 취약점 발굴 하네스가 진화해 나온 단일 저장소 출발점이며, 다른 팀이 각자의 것을 만들 수 있도록 공개했다는 것이다.

읽을 만한 것은 공격 클래스 목록이 아니다. 물론 그것도 방대하다. 흥미로운 부분은 발견 사항이 어떻게 반박당하는가에 대한 대목이다.

여섯 단계, 그중 하나는 그저 기록 작업

워크플로는 대화형이 아니라 구조화되어 있다. 이것이 'Claude에게 버그를 찾아달라고 하기'와 가장 먼저 갈라지는 지점이다.

1단계는 정찰이다. 아키텍처, 신뢰 경계, 입력 면을 그려내고, 여기가 특이한 부분인데, 그것을 architecture.md와 coverage-ledger.json에 적어 넣는다. 2단계는 원장의 단위마다 격리된 사냥꾼을 배정하고, 각자가 무엇을 확인했는지 기록한 뒤, 아무도 보지 않은 곳을 찾기 위해 커버리지 비평가를 돌린다. 3단계는 개별 후보를 새 검증자에게 넘긴다. 그 검증자의 임무는 그것을 반증하는 것이다. 4단계는 confirmed, needs_validation, rejected 레코드를 findings.json에 쓰고 JSON 스키마로 검증한다. 5단계는 새 에이전트가 최종 소스 주장을 검증하고, 실질적인 교체가 있으면 또 다른 독립 검증자가 붙는다. 6단계는 검증된 레코드에서 보고서를 도출한다.

두 검증기는 의존성이 없는 순수 Node 스크립트다. validate-coverage-ledger.cjs는 원장이 만들어진 뒤와 갱신될 때마다, validate-findings.cjs는 4단계에서 그리고 5단계의 교체가 있을 때마다 실행된다. 저장소에서 가장 재미없는 파일이며, 나머지 전체를 성립시키는 이유이기도 하다. 스키마에 맞는 발견 사항을 내놓지 못하는 에이전트는 발견했다고 주장할 수 없다.

暗色墙面上层层叠叠的便利贴与一张六格流程图,两个格子之间拉着红线,左下一盏台灯投出狭窄的暖光

세 가지 판정이 실제 설계다

대부분의 에이전트 보안 도구는 출력이 두 가지뿐이다. 버그 목록, 아니면 아무것도 없음. 이 도구는 세 가지이고, 가운데 범주에 사고가 담겨 있다.

confirmed는 완전한 소스 추적과 경계가 정해진 관측 결과를 뜻한다. needs_validation는 정확히 하나의 미해결 사실이 있고 심각도는 배정되지 않은 상태다. rejected는 적극적으로 반증된 후보로, 삭제하지 않고 기록한다.

세 번째는 드문 경우이고, 내 생각에는 옳다. 반증된 후보는 코드베이스에 대한 증거다. 다음 실행에 그곳에 시간을 쓰지 말라고 알려주고, 검토자에게 무엇이 고려되었는지 알려준다. 대부분의 도구는 그것을 버린다.

바탕에 깔린 설계 원칙은 README에 퉁명스럽게 적혀 있다. 확립된 경계 실패만 확인하고, 소스에 근거한 단서가 막히면 발견 사항으로 승격하지 말고 미해결 사실을 정확히 붙여 needs_validation로 남겨 두라는 것. 관련 규칙도 있다. 심층 방어의 공백은 취약점이 아니다. A 계층이 공격을 막고 있다면 B 계층의 부재는 강화 메모일 뿐이다.

기계가 생성한 취약점 보고서를 읽어본 사람이라면 이 규칙들이 왜 존재하는지 정확히 안다. LLM 보안 검토의 실패 모드는 버그를 놓치는 것이 아니다. 자신감 넘치는 잡음이다. 취약점처럼 보이는 패턴이 고위험으로 보고되어 분류 팀의 일주일을 태운다.

적대적 검증, 말 그대로

가장 중요한 한 줄. 발견 사항을 검사하는 에이전트는 그것을 발견한 에이전트가 절대 아니다.

이것은 프롬프트 지시가 아니라 오케스트레이션 제약이며, 이런 종류의 도구가 신뢰할 만한 무엇인가를 만들어내는 유일한 방법이다. 자신의 출력에 대해 '이 발견 사항이 맞나'라고 물으면 LLM은 자기 자신에게 동의한다. 새로운 문맥과 다른 에이전트 인스턴스, 그리고 반증이라는 명시적 임무를 주면 코드 리뷰에 더 가까운 무언가를 얻는다.

5단계는 이것을 한 겹 더 밀어붙인다. 새 에이전트가 최종 소스 주장을 검증하고, 주장이 실질적으로 교체되면 또 다른 독립 검증자가 그 교체를 확인한다. 사냥꾼과 살아남는 기록 사이에 두 단계의 분리가 있는 셈이다.

정직한 숫자

설계 원칙 속에 이런 문장이 박혀 있다. Cloudflare의 테스트 실행에서 한 번의 실행은 반복 실행이 합쳐서 찾아낸 취약점의 약 절반을 찾았다.

이것을 공개하는 것은 선택이다. 도구가 신탁이 아니라 커버리지 기계임을 알려주고, 워크플로의 의미를 바꾼다. 릴리스 전에 한 번 돌리는 것이 아니라, 반복해서 돌리며 원장을 축적하는 것이다. 저장소는 이를 명시적으로 지원한다. 같은 저장소에 대한 여러 번의 실행은 누적되며, 이전 원장과 발견 사항으로 공백을 겨냥하고, 변경된 소스를 재검증하며, 낡은 작업을 커버된 것으로 취급하지 않고 현재 소스의 증거를 이어받는다.

절반은 사람 감사자가 첫 회차에 도달하는 수준으로도 합리적인 추정이다. 그것이 안심이 되는지 절망적인지는 이 직업을 어떻게 보느냐에 달려 있다.

대부분의 사람을 막을 그 요구 조건

README에는 많은 사용자가 그냥 지나쳤다가 곧 마주치게 될 강경한 요구 조건이 있다. 빌드, 테스트, 프로세스, 브라우저, 에뮬레이터, 퍼저, 픽스처를 위한 운영체제 강제 샌드박스, 외부 네트워크 차단, 정제된 허용 목록 환경, 강제 자원 한도, 쓰기는 스크래치 경로로 제한.

이런 통제가 없으면 워크플로는 대상 코드를 실행하지 않고 단서를 needs_validation에 머물게 한다. 옳은 판단이다. 어쨌든 언어 모델의 제안을 코드베이스에 대해 돌리는 일이니까. 하지만 동시에 컨테이너 기반이 없는 사람에게는 이 도구가 정적 분석과 추론 연습으로 격하된다는 뜻이기도 하다.

npx 설치 한 줄이 있음에도 이것이 노트북용 도구가 아니라는 뜻이기도 하다. 설치는 명령 하나다.

npx skills add https://github.com/cloudflare/security-audit-skill \
  --skill security-audit

사용법은 그냥 물어보는 것이다.

security audit this codebase

기묘한 대비다. 호출은 한 문장이고, 전제 조건은 샌드박싱 정책이다. 그 둘 사이의 간극이 배포 작업의 대부분이 들어갈 자리다.

출력은 실제로 어떤 모습인가

세 가지 산출물은 쓰이는 것이 아니라 도출된다. REPORT.md, FINDINGS-DETAIL.md, NEEDS-VALIDATION.md, 그리고 바탕이 되는 findings.json과 커버리지 원장이다.

이 분리는 들리는 것보다 유용하다. 단일 취약점 보고서는 모든 발견을 같은 어조로 밀어 넣는다. 그래서 치명적인 SQL 인젝션과 빠진 CSP 헤더가 나란히 놓이게 된다. 확정된 발견, 열린 질문, 도출된 요약을 나누면 NEEDS-VALIDATION.md를 읽는 사람은 자신이 결과가 아니라 진행 중인 작업을 보고 있다는 것을 안다.

기본 출력 디렉터리는 ~/security-audit-skill/<repo-name>/run-<N>이고, gitignore된 디렉터리를 명시적으로 지정했을 때만 워크플로가 대상 저장소 안에 쓴다. 작은 디테일이지만 직감은 맞다. 저장소 안의 감사 산출물은 실수로 커밋되기 마련이고, 패치되지 않은 취약점 목록이 커밋되는 것 자체가 하나의 사고다.

잘 작동했는지 판단하는 법

두 번 돌려라. README가 말하지 않고 암시하는 테스트다. 실행은 누적되고 한 번의 실행은 약 절반만 찾으므로, 같은 commit에 대한 두 번째 실행은 해당 코드베이스에서 도구의 커버리지를 직접 측정하는 것이 된다. 두 번째 실행에서 새로운 것이 나오지 않는다면, 코드가 깨끗하거나 사냥 클래스가 여러분의 스택과 맞지 않는 것이다.

그다음 rejected 로그를 보라. 다섯 건을 확정하고 마흔 개 후보를 기각한 실행은 제 역할을 하고 있다. 마흔 건을 확정하고 하나도 기각하지 않은 실행은 검증을 멈춘 것이다. 그 마흔 개는 믿기 전에 직접 읽어야 한다.

이 범주에 대해 말해주는 것

세 가지, 짧게.

에이전트 스킬은 유통 형태가 되고 있다. import하는 라이브러리가 아니라 마크다운 폴더와 두 개의 검증 스크립트이고, 모델이 런타임에 읽는다. 저장소는 스무 개 남짓의 지시 파일과 대상 유형별로 나뉜 공격 클래스 목록이다. 메모리 안전과 바이너리, LLM과 에이전트 면, 웹 프로토콜과 인증, 클라이언트 측, 공급망, 클라우드와 배포, RPC와 메시징, 자원 고갈, 데이터 격리, 데스크톱과 로컬 IPC. 그 구조 자체가 제품이다.

검증이 차별화 요소가 되고 있다. 이제 모든 벤더가 그럴듯한 발견 사항을 생성할 수 있다. 그러나 어느 것이 적대적 검증을 통과해 살아남았고, 스키마에 기록되었고, 반증된 것까지 보존되었는지 말해줄 수 있는 곳은 거의 없다.

그리고 '정직한 숫자' 습관이 퍼지고 있다. '우리는 절반을 찾았다'고 공개하는 벤더의 다음 주장은 더 믿을 만하다.

저장소는 MIT 라이선스다. 즉 흥미로운 질문은 그것이 작동하느냐가 아니라, 여러분의 팀이 제대로 작동시키는 데 필요한 샌드박스를 감당할 수 있느냐다.

관련 글