Preflight logo
Preflight

샘플 리포트

Preflight 리포트의 예시입니다. 가상의 노트·이미지 공유 SaaS 사례로, 실제 리포트는 입력한 스택과 기능에 맞춰 이와 같은 형태로 생성됩니다.

샘플 리포트의 가상 앱 맥락

스택
Next.js (App Router) + Supabase (Auth · Storage · Postgres) + Drizzle ORM, Vercel 배포
단계
출시 전
기능
인증/로그인사용자 데이터 격리파일 업로드

예시 데이터입니다. 실제 리포트는 인터뷰에서 입력한 스택과 기능에 맞춰 생성됩니다.

지금 당장 수정(2)

Supabase 테이블에 행 단위 보안(RLS)이 켜져 있지 않음
확인됨

도서관에서 누구나 모든 회원의 대출 기록을 볼 수 있는 것과 같아서, 한 사용자가 다른 모든 사용자의 노트를 조회할 수 있습니다.

왜 중요한가
Supabase는 클라이언트가 직접 데이터베이스에 질의할 수 있는 구조라, Row Level Security를 켜지 않으면 anon key만 있어도 테이블 전체를 SELECT할 수 있습니다. 브라우저 콘솔에서 supabase-js 한 줄이면 끝납니다.
영향: 전 사용자의 노트 본문·제목·작성 시각이 비공개 설정과 무관하게 외부에 노출
수정 방향
사용자별 데이터가 들어간 모든 테이블에 RLS를 활성화하고, 자기 행만 읽고 쓸 수 있는 정책을 추가하세요. 활성화 직후 anon key로 SELECT가 막히는지 즉시 검증하세요.
현재 service_role key를 사용하는 백엔드 코드가 있나요? 그 경로는 RLS를 우회하므로 별도로 권한 체크가 필요합니다.
Server Action이 호출자 권한을 검증하지 않음
확인됨

택배 기사가 송장 번호만 있으면 누구의 집이든 열어주는 상황과 같아서, 다른 사용자의 노트를 ID만 알면 누구나 수정·삭제할 수 있습니다.

왜 중요한가
deleteNote(noteId), updateNote(noteId, ...) 같은 Server Action이 noteId를 받자마자 DB 작업을 실행하는데, 호출한 사용자가 그 노트의 소유자인지 확인하지 않습니다. 브라우저 개발자 도구에서 fetch 한 번이면 다른 사용자의 노트를 지울 수 있습니다.
영향: 로그인된 임의의 사용자가 다른 사용자의 데이터를 수정·삭제 가능
수정 방향
모든 Server Action 시작 부분에서 현재 세션을 확인하고, 대상 리소스의 user_id가 세션 사용자와 일치하는지 검증하세요. 일치하지 않으면 즉시 에러를 던지세요.
Server Actions에서 데이터를 가져올 때 Drizzle 쿼리에 user_id 조건을 항상 함께 거는 패턴을 쓰고 있나요?

출시 전 수정(2)

Content Security Policy 헤더가 설정되지 않음
확인됨

집 현관문에 보안 시스템이 없는 것과 같아서, 악성 스크립트가 어떤 경로로든 페이지에 들어오면 막을 방법이 없습니다.

왜 중요한가
next.config.js에 CSP 헤더가 없어 브라우저가 어떤 외부 스크립트든 실행을 허용합니다. 사용자가 노트에 마크다운으로 외부 이미지나 링크를 넣을 수 있는 구조라면 stored XSS 가능성이 더 큽니다.
영향: 스크립트 주입 시 사용자 세션 토큰 탈취, 계정 장악
수정 방향
next.config.js의 headers() 함수에서 Content-Security-Policy 헤더를 추가하세요. 처음에는 Content-Security-Policy-Report-Only 모드로 시작해서 위반 사례를 모은 후 강제 모드로 전환하는 것을 권장합니다.
사용자가 입력한 마크다운이나 HTML을 렌더링하는 컴포넌트가 있나요? 있다면 sanitizer 사용 여부도 확인이 필요합니다.
이미지 업로드 시 파일 종류·크기 검증이 없음
가능성 높음

택배를 X-ray 검사 없이 전부 받는 것과 같아서, 사용자가 이미지가 아닌 파일이나 거대한 파일을 올려도 그대로 저장됩니다.

왜 중요한가
업로드 Server Action이 MIME 타입과 파일 크기를 검증하지 않습니다. 악성 SVG에는 JavaScript가 들어갈 수 있어 stored XSS 경로가 되고, 크기 제한이 없으면 한 명의 공격자가 스토리지를 채워 비용을 폭발시키거나 DoS를 일으킬 수 있습니다.
영향: 스토리지 비용 폭발, stored XSS 가능성, 다른 사용자에게 악성 파일 제공
수정 방향
업로드 Server Action에서 MIME 타입을 화이트리스트로 검증하고, 파일 크기 상한을 두세요. SVG는 별도 sanitizer를 거치거나 아예 거부하세요.
현재 SVG 업로드를 허용하고 있나요? 허용한다면 DOMPurify 같은 서버사이드 sanitizer를 거치는지 확인이 필요합니다.

나중에 개선(1)

민감 작업에 대한 감사 로그가 없음
확인됨

CCTV가 없는 매장처럼, 보안 사고가 났을 때 누가 무엇을 했는지 추적할 방법이 없습니다.

왜 중요한가
로그인, 비밀번호 변경, 노트 삭제, 파일 업로드 같은 민감 작업이 어디에도 기록되지 않습니다. 사고가 발생하면 원인 분석과 책임 추적이 사실상 불가능합니다.
영향: 보안 사고 원인 분석 및 책임 추적 불가능
수정 방향
audit_logs 테이블을 만들고 민감 작업의 Server Action에서 작업 종류·대상·IP를 함께 기록하세요. 최소한 인증, 비밀번호 변경, 데이터 삭제는 우선 적용하세요.
GDPR이나 개인정보보호법 대응이 필요한 상황인가요? 그렇다면 감사 로그 보존 기간 정책도 함께 정해야 합니다.

불확실(1)

환경 변수 노출 범위를 코드만으로 확인할 수 없음
불확실

금고 비밀번호가 적힌 메모를 어디에 두었는지 파악이 안 되는 상황과 같아서, service_role key가 클라이언트 번들에 섞여 들어갔는지 확신할 수 없습니다.

왜 중요한가
Next.js는 NEXT_PUBLIC_ 접두사가 붙은 환경 변수만 클라이언트에 노출하지만, 실수로 일반 변수를 클라이언트 컴포넌트에서 import하면 빌드 결과물에 포함될 수 있습니다. service_role key가 노출되면 RLS를 우회해 데이터베이스 전체를 조작할 수 있습니다.
영향: 최악의 경우 데이터베이스 전체 조회·수정 권한이 외부에 유출
수정 방향
빌드 결과물에서 service_role key의 일부 문자열을 grep으로 검색해 직접 확인하세요. 그리고 service_role key를 쓰는 모든 코드 경로가 Server Action 또는 Route Handler에 한정돼 있는지 점검하세요.
현재 어떤 파일에서 service_role key를 사용하고 있나요? 그 파일이 클라이언트 컴포넌트에서 import되지 않는지 확인이 필요합니다.