Code Review Is Not an Authority Boundary
코드 리뷰는 권한 경계가 아닙니다
AI가 생성한 코드의 안전성을 코드 리뷰와 테스트에만 맡기면, 코드가 실제로 행사할 권한은 통제하지 못합니다. 글쓴이는 최소 권한(capability-based security)을 적용한 실험으로 권한을 런타임에서 제한하는 방법과 자동 권한 발견 방식의 한계를 보여줍니다.
- 주제
AI 요약
AI가 코드를 빠르게 만들수록 더 중요한 질문은 코드가 올바른지뿐 아니라 실행 중 어떤 일을 할 권한을 받는지입니다. 코드 리뷰는 구현을 살피고 테스트는 동작을 확인하지만, 둘 다 권한 범위를 강제하지는 않습니다. 글쓴이는 이 문제를 살피려고 약 200줄의 Python으로 capability 기반 도구 호스트를 만들었습니다.
샌드박스와 권한은 다른 경계입니다
샌드박스(sandbox)는 코드가 실행 환경 밖으로 나가지 못하게 제한합니다. 하지만 호스트가 고객 정보 읽기·수정, 환불, 이메일 발송, 데이터베이스 내보내기 기능을 모두 제공하면 샌드박스 안의 코드도 그 기능을 호출할 수 있습니다. 실행 위치를 격리해도 코드가 시스템에 미칠 영향까지 제한하지는 않습니다. 따라서 실행 환경이 어떤 기능을 노출하는지가 실제 신뢰 경계가 됩니다.
글에서 소개하는 capability-based security는 코드를 믿고 넓은 접근을 준 뒤 행동을 감시하는 대신, 처음부터 필요한 권한만 명시적으로 부여합니다. 이 접근은 1966년 Dennis와 Van Horn의 연구로 거슬러 올라가며, Mark Miller의 principle of least authority, FreeBSD의 Capsicum, seL4, Deno의 권한 모델, WASI Preview 2와 WebAssembly Component Model에서도 이어집니다.
같은 결과를 내도 필요한 권한은 다릅니다
실험에서는 두 에이전트가 청구서와 결제 정보를 대조해 같은 보고서를 만듭니다. agent_a는 청구서와 결제 정보 읽기만 수행합니다. agent_b는 환불을 처리하고 알림도 보내려 합니다. 두 구현 모두 테스트를 통과합니다. 출력이 같으므로 결과를 확인하는 테스트만으로는 agent_b가 더 넓은 권한을 요구한다는 사실을 찾아낼 수 없습니다.
최소 권한 manifest를 적용하면 agent_a는 필요한 읽기 권한을 받아 완료합니다. 반면 agent_b는 부여받지 않은 refunds.issue 권한으로 환불을 요청하다 런타임에서 차단됩니다. 거부 기록은 리뷰어가 코드를 살펴 위험을 발견하지 못했다는 판단이 아니라, 권한 경계가 실제 실행에서 강제됐다는 증거입니다. 다만 이 작은 호스트는 직접 부여된 권한만 통제합니다. 권한을 가진 다른 구성요소를 호출해 간접적으로 행동을 일으키는 권한까지 계산하지는 않습니다. 실제 capability 시스템에서는 구성요소 사이의 참조 관계도 권한 분석 대상입니다.
권한을 실행 기록만으로 정하면 놓치는 경로가 생깁니다
글쓴이는 실행 중 사용한 기능을 기록해 최소 권한 manifest를 자동으로 만드는 방법도 시험합니다. 평범한 조정 작업에서는 invoices.read와 payments.read만 기록되어 그럴듯한 manifest가 나옵니다. 하지만 발견 단계에서 보지 못한 신용 메모 입력은 조정 결제 기록을 쓰는 payments.write 권한을 필요로 합니다. 이 권한이 manifest에 없어 정상적인 작업도 중단됩니다.
실행 기록은 특정 입력에서 코드가 실제로 한 일을 보여줄 뿐, 모든 유효한 입력에서 필요한 권한을 알려주지 않습니다. 관찰만으로 만든 권한 목록은 필요한 권한의 하한을 부여할 권한의 상한처럼 취급하는 오류를 낳습니다. 글쓴이는 기능 명세가 신용 메모 같은 경로를 정의하듯, 권한 목록도 실행 기록보다 명세에 함께 두어야 한다고 봅니다. 권한 거부 기록은 지나치게 좁은 부여를 찾는 데 도움을 주지만, 그 기록만으로 적절한 권한 범위를 확정하지는 못합니다.
권한 부여는 생성 모델과 분리해야 합니다
같은 모델이 구현과 테스트를 만들고 필요한 권한까지 스스로 정하면, 세 결정이 모두 같은 정보에 기대게 됩니다. 글쓴이는 모델이 필요한 권한을 제안할 수는 있어도 실제 부여 여부는 별도 정책이 결정해야 한다고 주장합니다. 예를 들어 청구서 대조 작업이라는 정책이 invoices.read를 허용하고, 런타임은 payments.write와 refunds.issue를 주지 않습니다. 실행 때 실제로 부여한 권한은 감사 기록에 남깁니다.
Android 권한이나 브라우저 확장 manifest처럼 권한 목록이 사용자 피로와 형식적인 승인으로 무력화될 수 있다는 반론도 다룹니다. 글쓴이는 여기서 권한 부여 주체가 사람이 아니라 버전 관리하고 테스트할 수 있는 정책이라는 점, 권한이 부족할 때 생성 코드를 다시 만드는 비용이 낮다는 점을 차이로 듭니다. 권한을 넓히는 대신 구현을 부여된 범위에 맞출 여지가 커진다는 설명입니다.
정확성과 권한은 별도로 검증해야 합니다
권한 경계는 코드의 정확성을 증명하지 않습니다. 반대로 테스트 통과도 코드가 불필요한 작업을 하지 않는다는 보장이 아닙니다. 이미지 크기 조절 플러그인이 올바르게 동작하더라도 급여 정보에 접근할 이유는 없습니다. 코드 리뷰는 논리 오류, 취약점, 의존성 선택을 살피는 데 여전히 필요하지만, 리뷰어가 위험한 동작을 모두 찾아낼 것이라고 기대해서는 안 됩니다. 구현이 바뀌거나 다시 생성돼도 동작 명세와 권한 경계는 유지해야 한다는 것이 글의 제안입니다.
원문: dev.to / 번역·요약: Trawling