Claude Code 체크리스트로 인증·권한·입력 검증·시크릿 처리·인젝션 표면을 빠르게(30~60분) 점검해 배포 전 명백한 위험을 찾아내세요.

{id}GET /projects/{id}ORDER BYIN (...)convertPATCH /api/profile?accountId=123와 JSON { "displayName": "Sam" }\n\nClaude Code에게 핸들러를 찾고 accountId가 어떻게 사용되는지 추적해 서버가 소유권을 강제하는지 증명하라고 요청합니다.\n\n자주 보이는 결과:\n\n- Authn: 요청은 세션이나 토큰을 요구하므로 보호된 것처럼 보입니다.\n- Authz: 핸들러가 쿼리 문자열의 accountId를 신뢰하고 그 계정을 검사하지 않고 업데이트합니다.\n- 입력 검증: displayName은 트림되지만 accountId는 정수인지 검증되지 않습니다.\n- 인젝션 표면: SQL이 "... WHERE account_id=" + accountId처럼 문자열 연결로 만들어집니다.\n\n좋은 작성 방식은 구체적입니다:\n\n- 심각도: 높음 (IDOR + 잠재적 SQL 인젝션)\n- 증거: 유효한 로그인으로 다른 사용자의 accountId를 바꿔 요청하면 다른 계정이 변경됨; SQL이 신뢰할 수 없는 입력으로부터 구성됨\n- 수정: 클라이언트의 accountId를 무시하고 서버에서 인증된 사용자의 계정 ID를 사용; 쿼리를 파라미터화하세요\n- 테스트: 다른 계정을 업데이트 시도하고 403을 기대; 숫자가 아닌 accountId는 거부\n\n수정 후 빠르게 재확인하세요:\n\n- 같은 요청을 다른 accountId로 시도해 실패하는지 확인하세요.\n- 로그가 쿼리 파라미터가 아닌 인증된 ID를 사용함을 보여주는지 확인하세요.\n- 쿼리가 문자열 빌드가 아니라 플레이스홀더/파라미터를 사용하는지 확인하세요.\n- 잘못된 입력(문자, 매우 큰 숫자)에 대한 음수 테스트 하나를 실행하세요.\n\n## 스팟체크에서 실제 이슈를 놓치게 하는 함정\n\n가장 빠르게 취약점을 놓치는 방법은 UI가 시행하는 것을 그대로 신뢰하는 것입니다. 버튼이 숨겨져 있거나 비활성화되어 있다고 해서 권한 검사가 된 것은 아닙니다. 서버가 요청을 허용하면 누구나 다른 사용자 ID나 역할로 재생할 수 있습니다.\n\n또 다른 흔한 실수는 모호한 요청입니다. "보안 리뷰 해줘"는 일반적인 보고서를 낳습니다. 스팟체크는 좁은 범위(어떤 엔드포인트, 어떤 역할, 어떤 데이터)와 엄격한 출력 형식(파일명, 함수, 위험 라인, 최소 재현)을 필요로 합니다.\n\nAI 출력에도 같은 규칙이 적용됩니다: 코드 위치와 실행 단계가 없으면 주장을 수용하지 마세요. 발견에 구체적 코드 위치와 재현 단계가 포함되지 않으면 검증되지 않은 것으로 처리하세요.\n\n### 스팟체크가 빗나가는 빠른 방법들\n\n자주 반복되는 함정:\n\n- 관리자 페이지라서 "관리자 전용"이라고 가정하고 서버가 강제하는지 확인하지 않음\n- "X를 우회할 수 있다"는 식으로 광범위한 결과를 요청하고 구체적 재현을 요구하지 않음\n- "가능한 SQL 인젝션"을 수용하지만 쿼리 구성 지점과 입력 경로를 찾지 않음\n- 웹훅, 예약 작업, 임포트 도구, 내부 관리자 동작 같은 덜 명백한 진입점을 건너뜀\n- 증상만 패치(필터나 정규식 추가)하고 근본 원인(경계에서의 검증 누락, 중앙화된 권한 검사 없음)을 놓침\n\n모든 새 엣지 케이스마다 필터를 추가하고 있다면 멈추세요. 보통 수정은 더 앞단에 있습니다: 경계에서 입력을 검증하고 권한 검사를 명시적이고 중앙화하여 모든 코드 경로가 그것을 사용하게 하세요.\n\n## 배포 전 빠르게 실행할 수 있는 체크\n\n이것들이 전체 리뷰를 대체하지는 않지만, 모두 피곤할 때 실수로 빠지는 문제를 잡아냅니다. 빠르게 증명할 수 있는 요청, 페이지, 로그 라인을 중심으로 하세요.\n\n보통 효과적인 다섯 가지 빠른 스팟체크:\n\n- 인증 마찰: 연속으로 잘못된 로그인 10회를 시도하세요. 속도 제한, 잠금, 또는 최소한 지연이 있는가? 오류 메시지나 타이밍으로 이메일 존재 여부를 알 수 있는가?\n- ID 교체로 권한 확인: 실제 리소스(주문, 송장, 프로필)를 골라 URL, JSON 바디, GraphQL 변수의 ID를 바꿔보세요. 자신의 것이 아닌 데이터(메타데이터 포함)를 받는가?\n- 입력 가드레일: 핵심 필드(이메일, 이름, 검색, 파일 업로드)에 긴 문자열, 특이한 유니코드, 예상치 못한 타입(문자열 대신 숫자)을 넣어보세요. 길이 제한과 허용목록을 적용하는가?\n- 시크릿 노출: 최근 로그와 클라이언트 번들에서 토큰, API 키, JWT, 또는 "Authorization: Bearer" 문자열을 검색하세요. 에러 페이지도 확인하세요. "스테이징에만 있던 것"이 종종 실수로 배포됩니다.\n- 인젝션 표면: SQL, 필터, 템플릿 렌더링, 셸 명령, 리다이렉트 URL에 문자열 연결이 있는지 확인하세요. 입력이 강한 검증 없이 이러한 곳에 도달하면 위험으로 가정하세요.\n\n다음 주에 배포할 수 있는 상위 3개 수정을 적어 두세요. 바람 목록이 아니라 실제로 배포 가능한 항목을 적습니다. 예: (1) 로그인과 비밀번호 재설정에 속도 제한 추가, (2) "id로 가져오기" 엔드포인트에 서버 측 소유권 검사 적용, (3) 검색 필드에 입력 길이 제한과 불허 문자 거부.\n\n## 다음 단계: 이 체크리스트를 빌드 프로세스의 일부로 만들기\n\n스팟체크는 결과가 실제 배포에 영향을 줄 때만 가치가 있습니다. 이 체크리스트를 일회성 구조가 아닌 작고 반복 가능한 빌드 단계로 취급하세요.\n\n모든 발견을 이해하기 어렵지 않은 백로그 항목으로 만드세요:\n\n- 수정: 코드나 설정에서 무엇이 바뀔지\n- 테스트: 수정되었음을 증명할 방법(요청 하나, 단위 테스트 하나, QA 단계 하나)\n- 담당자: 책임 있는 한 사람\n- 목표일: 다음 릴리스나 특정 날짜\n- 증거: 문제를 보여준 파일/엔드포인트와 정확한 요청 또는 페이로드\n\n팀 규모와 위험에 맞는 주기를 선택하세요. 많은 팀은 모든 릴리스마다 하는 것이 최선입니다. 릴리스가 잦다면 월간 30