시도하고자 했던 것
2주차에 저는 이런 결론으로 글을 마쳤습니다 — "게이트 평가는 잡은 것이 아니라 놓친 것으로 해야 한다." 게이트의 출력만 보면 사각지대는 영원히 안 보이니까요.
그런데 그 글을 쓰고 나서 질문이 하나 남았습니다. 놓친 것은 대체 어떻게 세는 가? 안 잡힌 건 애초에 안 보이는데요.
3주차 답은 반대 방향이었습니다. 찾지 말고 심는다. 결함을 내가 만들어서 집어넣고, 게이트가 잡는지 본다.
진행 방법 — 기준선 · 실패 증거 · 최소 수리 · 같은 기준 재평가
과제 양식대로 네 단계로 갈라 적습니다. 제일 중요한 칸은 마지막입니다 — 통과시키려고 기준을 바꾸면 안 되는 자리라서요.
단계
제 경우
기준선(동결)
결함 5종 주입 시 검출 2/5. 이 5종이 이후 내내 고정 기준
실패 증거
F1·F4·F5가 안 막힘 — 셋 다 PASS_WITH_CAVEATS · errors 0으로 통과
최소 수리
검사 2개만 추가(F1·F4). 검증기 전면 개편 안 함
같은 기준 재평가
똑같은 5종을 다시 주입 → 4/5. 기준도, 입력도 안 바꿈
1) 설계 — 결함 5종을 성격별로
최근에 통과(PASS)한 번들의 복사본에 결함을 하나씩 단독 주입했 습니다. 원본과 공용 검증기는 손대지 않았습니다.
ID
심은 결함
노리는 층
F1
끊긴 참조 — 근거 위치가 없는 파일을 가리키게
서류↔실물 대사
F2
등급 위조 — 근거 없이 "검증됨" 도장
승격 규칙
F3
원자료 변조 — 원본 파일 1바이트 수정
무결성(해시)
F4
계보 공백 — 원본은 있는데 매니페스트에서 누락
캡처 계보
F5
인용 앵커 위조 — 원문에 없는 문구를 인용으로
인용 대조
2) 실행 — 결과는 예상보다 나빴습니다
검출률 2/5 (40%)
✅ 잡음: F2(등급 위조) · F3(해시 변조)
❌ 통과시킴: F1(끊긴 참조) · F4(계보 공백) · F5(앵커 위조)
→ 셋 다 "PASS_WITH_CAVEATS · errors 0"
못 잡은 3종에 공통점이 있었습니다. 전부 "참조가 실물과 맞는가"를 안 봅니다. 근거 위치가 실재하는지(F1), 매니페스트가 원본을 다 덮는지(F4), 인용 문구가 원문에 있는지(F5).
즉 이 검증기는 서류(JSON)끼리의 정합만 보고, 서류와 실물을 대사하지 않고 있었습니다. 값을 바꾸는 공격(해시·등급)에는 강하고, 가리키는 곳이 비어 있는 것에는 무력했습니다.
3주차 강의에서 스터디장님이 "실패 사례를 일부러 넣어서 테스트하는 것"을 두고 "되게 좋은 검증 방법, 고난이도 기법 중 하나"라고 짚으셨는데, 저희가 그걸 저희 게이트에 대본 결과가 40%였습니다.
3) 증거 — 그런데 패치보다 오탐 예방이 본작업이었습니다
F1·F4를 잡는 검사를 넣는 건 코드 몇 줄입니다. 문제는 그다음이었습니다.
근거 위치가 순수한 파일 경로일 거라 가정하고 단순 존재검사를 넣었다면 오탐 386건이 났을 겁니다. 실제 표기는 raw/파일.md §섹션 설명 처럼 경로 뒤에 주석·쪽수·앵커가 붙는 형식이었거든요.
그래서 배포 전에 보유 번들 25개를 전수 조사해 파서를 3번 보정했고, 진성 1건만 남겼습니다. 2주차에 오탐을 두 번 맞고 배운 걸, 이번엔 사전 조사로 대체한 셈입니다.
4) 수리 — 그리고 진짜 결함이 하나 나왔습니다
패치 후 전수 재검사에서 실제 결함 1건이 잡혔습니다. 한 번들의 근거가 존재하지 않는 파일을 가리키고 있었습니다(해당 원본이 통째로 없음). 예측했던 1건과 정확히 일치했습니다.
결과와 배운 점
실행 영수증
칸
내용
Trace
통과 번들 복사본에 결함 1종씩 단독 주입 → 검증기 실행 → 판정 수집 → 패치 → 같은 5종 재주입 → 보유 번들 25개 전수 재검사
Proof
주입 명세, 검증기 원출력(JSON·exit code), 전수 검사 로그. 전부 기계 출력이고 보존했습니다
Verdict
PASS — 검출 2/5 → 4/5. 단 F5는 의도적 보류라 not_checked가 아니라 "안 막기로 정함"으로 기록
Repair
검사 2종 추가 + 파서 3회 보정(오탐 386 → 0)
결과 [전부 기계 출력 기준]
검출률 2/5(40%) → 4/5(80%). 남은 1종(앵커 위조)은 발생 실측이 없어 의도적으로 보류했습니다 — 안 막는 게 아니라 아직 안 막기로 정한 것이고, 그 사유를 기록에 남겼습니다
오탐 386 → 0 (진성 1건만 남김)
회귀 하네스로 영구화: 검증기를 고칠 때마다 이 5종이 자동으로 다시 주입되고, F1~F4 중 하나라도 놓치면 "게이트 퇴행"으로 판정해 실패 처리합니다. 반대로 F5가 잡히면 개선으로 보고합니다
시행착오
"검증 장치가 6개나 있다"와 "그게 작동한다"는 완전히 다른 문장이었습니다. 저희는 게이트를 여러 개 운용하면서 게이트의 고장을 재는 장치는 0개였습니다. 40%는 그 대가입니다.
패치보다 오탐 조사가 훨씬 오래 걸렸습니다. 검사 추가는 몇 줄, 오탐 386건을 1건으로 줄이는 게 본작업이었습니다. 검증을 강화한다는 건 대개 "잡는 코드를 짜는 일"이 아니라 "안 잡을 것을 정확히 정의하는 일"이더군요.
표본이 작습니다. 번들 1개·결함 5종뿐이라 결함 클래스 전수가 아닙니다. 요약문 위조·감사로그 조작 같은 건 아직 안 심어봤습니다. 그리고 시험한 건 검증기 1개고, 다른 게이트 2개는 아직 대상이 아닙니다 — 이건 다음 라운드입니다.
꿀팁
결함은 한 번에 하나만 심으세요. 여러 개를 동시에 넣으면 어느 검사가 죽었는지 안 갈립니다.
못 잡은 항목을 바로 패치하지 마세요. 왜 못 잡았는지 먼저 묶어보면 개별 버그가 아니라 층 전체가 비어 있다는 게 보입니다. 저희는 그래서 "서류↔실물 대사가 통째로 없다"를 발견했습니다.
주입 스크립트를 버리지 말고 회귀로 남기세요. 안 그러면 다음 수정에서 조용히 퇴행합니다.
도움이 필요한 부분
인용 앵커 대조(F5)를 감당 가능한 비용으로 하는 방법이 궁금합니다. 원문 전문 검색이라 큰 파일에서 비용이 큽니다 — 샘플링으로 하시나요, 아니면 인용 길이 제한을 두시나요?
결함 클래스를 어떻게 늘려가시나요? 지금은 겪은 사고에서 역산했는데, 안 겪은 사고는 못 심습니다.
도움 받은 글·강의
3주차 강의 — "실패 사례를 일부러 넣어서 테스트"가 고난이도 검증 기법이라는 언급. 이 실험을 실행에 옮긴 계기입니다
3주차 강의의 코드 애즈 게이트 / 프루프 오브 아티팩트 — "코드 게이트가 맞고 증거가 없으면 통과가 안 된다"는 원칙을, 이번엔 게이트 자신에게 적용해봤습니다
2주차 제 사례글 — "놓친 것으로 평가하라"는 결론이 이번 주 출발점이 됐습니다