본 사이트는 파트너스 활동으로 수수료를 받을 수 있으며, 서버 운영과 무료 앱 개발에 사용됩니다. 본 사이트는 파트너스 활동으로 수수료를 받을 수 있으며
서버 운영과 무료 앱 개발에 사용됩니다.
목록

바이브 코딩 보안 가이드

SECURITY GUIDEOWASP·개인정보·RLS·LLM

AI Coding · Security · Operations

바이브 코딩과 보안

개인정보 수집하다 털려 형사처벌, 민사소송 당하지 말자

AI가 코드를 빨리 만들어주는 시대에는 “서비스를 만들 수 있느냐”보다 “사고가 났을 때 책임질 수 있느냐”가 더 중요합니다. 초보자가 바로 확인할 항목부터 전문가가 증거로 남길 감사 기준까지 한 번에 읽히도록 정리했습니다.

핵심 결론

프런트에서 숨긴 것은 보안이 아니다. 서버가 매 요청마다 권한을 확인한다.

먼저 볼 것

인증/세션, RLS, service key, 결제 웹훅, 파일 업로드, LLM agent 권한.

검증 기준

OWASP Top 10 2025, API 2023, LLM 2025, ASVS, NIST SSDF.

실전 도구

체크리스트와 복사용 감사 프롬프트를 바로 가져다 쓴다.

Part 01 · Threat Map

먼저 무엇이 터지는지 한눈에 잡는다

개인정보, 법 리스크, OWASP 계보, AI가 만든 앱의 반복 사고 패턴을 먼저 훑고 나면 뒤의 체크리스트가 훨씬 빨리 읽힙니다.

01 · 시작

바이브 코딩은 빠르지만 책임도 빠르다

바이브 코딩은 좋습니다. 아이디어를 말하면 화면이 나오고, 로그인도 붙고, DB도 붙고, 배포까지 갑니다. 그런데 보안은 속도와 반대로 움직입니다. 빠르게 만든 서비스일수록 “일단 돌아간다”는 착각이 생기고, 그 착각이 가장 비싼 버그가 됩니다.

특히 개인정보를 받는 순간 이야기가 달라집니다. 이메일, 닉네임, 문의 내용, IP, 접속 로그, 구매 내역, AI 대화 내용은 모두 유저의 흔적입니다. “나는 작은 개인 사이트니까” 라는 말은 공격자에게도, 법에도, 피해자에게도 큰 방어 논리가 되지 않습니다.

이 글의 한 줄 결론

바이브 코딩에서 보안은 나중에 붙이는 장식이 아니라, DB를 만들기 전, 로그인 붙이기 전, 배포 버튼 누르기 전에 먼저 잡아야 하는 운영 책임입니다.

02 · 읽는 법

초보자와 전문가가 다르게 읽는 법

보안 글은 처음부터 끝까지 같은 깊이로 읽으면 금방 지칩니다. 초보자는 “오늘 당장 막을 사고”를 먼저 잡고, 운영자는 “서비스가 계속 굴러가는 최소 체계”를 만들고, 전문가는 “검증 가능한 증거”를 남겨야 합니다. 같은 글을 보더라도 읽는 목적이 다릅니다.

처음 만드는 사람

  • 개인정보를 덜 모으고, 서버에서 권한을 확인하고, 키를 브라우저에 넣지 않는 세 가지만 먼저 잡는다.
  • 체크리스트 섹션의 “공개 전 30분”과 “수동 10분 테스트”를 실제 브라우저와 계정 2개로 따라 한다.
  • 어려운 용어는 뒤의 키워드 사전에서 먼저 확인하고, 모든 항목을 한 번에 완벽히 하려고 하지 않는다.

1인 개발자와 운영자

  • 데이터 지도, 시크릿 관리, 인증/인가/RLS, 로그와 사고 대응을 최소 운영 체계로 만든다.
  • Supabase, D1, Turso, VPS Postgres 중 현재 쓰는 저장소의 “안전한 사용선”을 기준으로 배포 전 테스트를 한다.
  • AI에게 기능 구현을 맡긴 뒤에는 반드시 별도 대화에서 악용 시나리오와 방어 검증만 시킨다.

전문가와 감사 담당자

  • OWASP Top 10을 단순 매핑표가 아니라 ASVS, API Top 10, LLM Top 10, NIST SSDF, 사고 대응까지 연결한다.
  • source에서 sink까지 데이터 흐름을 추적하고, “방어 확인”, “취약 확인”, “판단 불가”로만 결론을 낸다.
  • Critical/High 수정 뒤 회귀 테스트와 로그 기반 탐지까지 확인해야 완료로 본다.

빠르게 읽어도 놓치면 안 되는 축

공개 API, 권한 검사, service key, RLS, 로그 개인정보, 파일 업로드, 결제 웹훅, AI agent 권한은 규모와 무관하게 바로 확인해야 합니다. 추가 보강 기준으로는 인증/세션, 로그인 brute force, open redirect, 공급망, CORS/CSRF, 결제 webhook, SSRF/파일 업로드 순서로 먼저 봅니다. 이 항목들은 “나중에”가 아니라 “배포 전” 항목입니다.

같이 보면 칼럼이 완성되는 심화 위키

이 칼럼은 전체 지도이고, 아래 다섯 문서는 각 위험을 더 깊게 파고드는 실전 매뉴얼입니다. 보안 감사를 실제로 돌릴 때는 해당 섹션에서 다시 연결해 두었습니다.

04 · 바이브 코딩 위험

AI가 만든 앱이 특히 잘 틀리는 지점

AI는 보통 “요청한 기능을 완성하는 방향”으로 코드를 씁니다. 보안 요구사항을 명확히 말하지 않으면 접근 통제, rate limit, 로그 마스킹, RLS 테스트, CSRF, 파일 업로드 검증, 웹훅 서명 검증 같은 비기능 요구사항은 빠지기 쉽습니다.

클라이언트 보안 착각

버튼을 숨기고 메뉴를 막았지만 API는 열려 있다. 공격자는 브라우저 UI를 쓰지 않고 직접 요청한다.

service key 노출

Supabase service_role, Turso token, Cloudflare API token이 브라우저 번들, Git, 로그, 스크린샷에 들어간다.

RLS 누락

anon key는 공개돼도 된다고 듣고 테이블 RLS를 켜지 않는다. 그 순간 공개 DB가 된다.

비용 폭탄

AI API, 이미지 생성, D1 write, Turso read, 이메일 발송, 크론 수집에 rate limit과 quota가 없다.

패키지 과신

존재하지 않거나 악성에 가까운 패키지를 AI 추천만 믿고 설치한다. 공급망은 이제 코드의 일부다.

LLM 출력 과신

LLM이 만든 HTML, SQL, shell 명령, 파일 경로, API 요청을 검증 없이 실행한다.

바이브 코딩 앱은 기능보다 감사 프롬프트가 먼저다

공개된 바이브 코딩 앱에서 반복적으로 발견되는 패턴은 IDOR, SQL injection, 클라이언트 인증 착각, 하드코딩 시크릿, RLS 누락, 관리자 우회입니다. 그래서 보안 점검은 “코드 예쁘게 정리”가 아니라 공격자가 URL 숫자, body 필드, 토큰, role, 파일 경로, 결제 금액을 어떻게 조작할지 묻는 방식이어야 합니다.

실전 감사 프롬프트 세트는 바이브코딩 보안 위협·감사 프롬프트에 따로 정리해 두었고, 이 칼럼의 복사팩에도 같은 사고방식으로 확장해 넣었습니다.

05 · OWASP 탄생

OWASP는 왜 2003년에 시작됐나

OWASP는 Open Worldwide Application Security Project입니다. 웹 애플리케이션 보안을 개선하기 위한 글로벌 비영리 커뮤니티이고, Top 10은 개발자와 조직이 가장 중요한 애플리케이션 보안 위험을 공통 언어로 이해하도록 만든 인식 문서입니다.

2003년의 웹은 지금보다 단순해 보였지만 위험은 이미 지금과 닮아 있었습니다. 입력을 검증하지 않고, 로그인과 권한을 섞고, XSS와 인젝션을 방치하고, 오류 메시지로 내부 정보를 흘리고, 비밀번호와 세션을 안전하지 않게 저장했습니다. 20년이 지나 API, 모바일, 클라우드, LLM이 붙었지만 뿌리는 같습니다.

Top 10은 완전한 법전이 아니다

OWASP Top 10은 가장 중요한 위험을 보여주는 출발점입니다. 실제 제품 보안에는 ASVS, SAMM, Cheat Sheet Series, API Security Top 10, LLM Top 10, ZAP, Dependency-Check, Dependency-Track, CycloneDX 같은 도구와 표준을 함께 써야 합니다.

06 · 전체 계보

2003부터 2025까지 Top 10 전체 계보

OWASP Top 10은 2003, 2004, 2007, 2010, 2013, 2017, 2021, 2025의 흐름으로 보는 것이 좋습니다. 항목 이름은 바뀌었지만, 접근 통제, 인증, 입력 검증, 암호화, 설정, 공급망, 로깅이라는 큰 축은 계속 남아 있습니다.

2003

최초 Top 10: 입력 검증과 접근 통제가 출발점

  • A1 Unvalidated Input
  • A2 Broken Access Control
  • A3 Broken Authentication and Session Management
  • A4 Cross Site Scripting
  • A5 Buffer Overflow
  • A6 Injection Flaws
  • A7 Improper Error Handling
  • A8 Insecure Storage
  • A9 Application Denial of Service
  • A10 Insecure Configuration Management

처음부터 핵심은 “사용자 입력을 믿지 말 것”, “로그인과 권한을 구분할 것”, “오류와 저장소를 안전하게 다룰 것”이었다. 2026년 AI 코딩에서도 이 원칙은 그대로 반복된다.

2004

2003년판 유지: 보안 인식 문서로 정착

  • 2003년과 같은 10개 항목 유지
  • 입력 검증, 접근 통제, 인증, XSS, 인젝션, 오류 처리, 저장, DoS, 설정 관리 중심

초기 OWASP Top 10은 세밀한 표준이라기보다 개발자에게 공통 언어를 주는 문서였다. 지금도 Top 10은 완전한 체크리스트가 아니라 출발점이다.

2007

XSS 1위, CSRF와 IDOR 부상

  • A1 Cross Site Scripting
  • A2 Injection Flaws
  • A3 Malicious File Execution
  • A4 Insecure Direct Object Reference
  • A5 Cross Site Request Forgery
  • A6 Information Leakage and Improper Error Handling
  • A7 Broken Authentication and Session Management
  • A8 Insecure Cryptographic Storage
  • A9 Insecure Communications
  • A10 Failure to Restrict URL Access

URL 숫자 하나 바꿨더니 남의 주문이 보이는 IDOR, 로그인된 브라우저를 악용하는 CSRF, 업로드 파일 실행 같은 문제가 독립 항목으로 떠올랐다.

2010

Injection 1위 복귀, 위험 기반 정리

  • A1 Injection
  • A2 Cross Site Scripting
  • A3 Broken Authentication and Session Management
  • A4 Insecure Direct Object References
  • A5 Cross Site Request Forgery
  • A6 Security Misconfiguration
  • A7 Insecure Cryptographic Storage
  • A8 Failure to Restrict URL Access
  • A9 Insufficient Transport Layer Protection
  • A10 Unvalidated Redirects and Forwards

SQL, OS 명령, LDAP, XPath처럼 해석기에 사용자 입력을 섞는 문제가 큰 축으로 정리됐다. 지금의 프롬프트 인젝션도 같은 사고방식으로 보면 이해가 쉽다.

2013

컴포넌트 위험과 민감 데이터 노출 부상

  • A1 Injection
  • A2 Broken Authentication and Session Management
  • A3 Cross Site Scripting
  • A4 Insecure Direct Object References
  • A5 Security Misconfiguration
  • A6 Sensitive Data Exposure
  • A7 Missing Function Level Access Control
  • A8 Cross Site Request Forgery
  • A9 Using Components with Known Vulnerabilities
  • A10 Unvalidated Redirects and Forwards

패키지와 프레임워크를 붙여 만드는 시대가 되면서 오래된 라이브러리와 민감 데이터 보호 실패가 Top 10의 핵심 언어가 됐다.

2017

XXE, 역직렬화, 로깅과 모니터링 추가

  • A1 Injection
  • A2 Broken Authentication
  • A3 Sensitive Data Exposure
  • A4 XML External Entities
  • A5 Broken Access Control
  • A6 Security Misconfiguration
  • A7 Cross Site Scripting
  • A8 Insecure Deserialization
  • A9 Using Components with Known Vulnerabilities
  • A10 Insufficient Logging and Monitoring

마이크로서비스, SPA, REST API, Node.js 생태계가 커지며 “사고가 났는지 모르는 문제”와 “외부 데이터 구조를 믿고 복원하는 문제”가 전면에 나왔다.

2021

근본 원인 중심 전환

  • A01 Broken Access Control
  • A02 Cryptographic Failures
  • A03 Injection
  • A04 Insecure Design
  • A05 Security Misconfiguration
  • A06 Vulnerable and Outdated Components
  • A07 Identification and Authentication Failures
  • A08 Software and Data Integrity Failures
  • A09 Security Logging and Monitoring Failures
  • A10 Server Side Request Forgery

증상보다 원인을 묶는 방식으로 바뀌었다. XSS는 Injection으로, 민감 데이터 노출은 Cryptographic Failures로, XXE는 Misconfiguration 쪽으로 흡수됐다.

2025

최신 8번째 개정: 공급망과 예외 처리까지

  • A01 Broken Access Control
  • A02 Security Misconfiguration
  • A03 Software Supply Chain Failures
  • A04 Cryptographic Failures
  • A05 Injection
  • A06 Insecure Design
  • A07 Authentication Failures
  • A08 Software or Data Integrity Failures
  • A09 Security Logging and Alerting Failures
  • A10 Mishandling of Exceptional Conditions

접근 통제 실패가 계속 1위이고, SSRF는 A01로 흡수됐다. 보안 설정 오류가 2위로 올라왔고, 공급망 실패와 예외 상황 처리 실패가 새롭게 강조됐다.

Part 02 · Standards

기준 문서를 실전 언어로 바꾼다

OWASP 2025, API, 모바일, LLM, 보안 원칙을 바이브 코딩 프로젝트에서 바로 쓸 수 있는 판단 기준으로 압축합니다.

07 · 최신판

2025 Top 10으로 보는 최신 위험

2025년판의 핵심은 두 가지입니다. 첫째, 접근 통제 실패가 여전히 가장 심각합니다. 둘째, 단일 취약점보다 설계, 설정, 공급망, 예외 처리, 경보처럼 운영 전체의 실패가 더 크게 다뤄집니다. 바이브 코딩 앱은 바로 이 지점에서 자주 넘어집니다.

OWASP는 2025년판에서 분석 대상 CWE가 크게 늘었고, 280만 개가 넘는 애플리케이션 데이터와 커뮤니티 설문을 바탕으로 10개 범주를 구성했다고 설명합니다. 그래서 2025년판은 “SQL injection만 조심하라”가 아니라 “어떻게 설계하고, 어떻게 배포하고, 어떻게 탐지하고, 예외에서 어떻게 실패하는가”를 묻는 문서로 읽어야 합니다.

항목의미바이브 코딩에서 터지는 방식첫 조치
A01
Broken Access Control
로그인은 했지만 이 데이터, 이 파일, 이 관리자 기능에 접근할 권한이 있는지 확인하지 않는 문제다.프런트 버튼만 숨기고 `/api/admin/delete?id=1` 같은 서버 API는 누구나 호출 가능하게 둔다.모든 API에서 세션 기준의 owner, role, tenant_id를 서버에서 검증한다.
A02
Security Misconfiguration
디버그 모드, 넓은 CORS, 공개 소스맵, 기본 계정, 과한 오류 메시지, 잘못된 클라우드 권한이다.AI가 “개발 편의”로 `Access-Control-Allow-Origin: *`와 자세한 에러 응답을 남긴다.production 설정을 별도로 두고 보안 헤더, CORS allowlist, 에러 응답, public 폴더를 점검한다.
A03
Software Supply Chain Failures
패키지, 빌드 도구, CI/CD, 모델, 플러그인, 컨테이너 이미지, 배포 토큰이 공격면이 되는 문제다.AI가 추천한 npm 패키지를 이름만 보고 설치했는데 타이포스쿼팅이거나 postinstall script가 숨어 있다.lockfile, npm audit, 패키지 출처 확인, GitHub Actions 최소 권한, 시크릿 스캔을 기본으로 둔다.
A04
Cryptographic Failures
암호화가 필요한 데이터를 평문 저장하거나 약한 해시, 잘못된 키 관리, TLS 누락으로 보호하지 못하는 문제다.비밀번호를 SHA-256으로 한 번 해시하거나 JWT payload에 민감 정보를 넣는다.비밀번호는 Argon2id, bcrypt, scrypt 같은 느린 KDF를 쓰고 민감 토큰은 HttpOnly Secure 쿠키에 둔다.
A05
Injection
사용자 입력이 SQL, 명령어, 템플릿, HTML, LLM 프롬프트 같은 해석기에 명령으로 섞이는 문제다.검색어를 raw SQL 문자열에 붙이거나 LLM 출력을 그대로 HTML, SQL, shell 명령에 전달한다.파라미터 바인딩, allowlist, escaping, sanitizer, 프롬프트 출력 검증을 적용한다.
A06
Insecure Design
코드는 정상 동작하지만 설계 자체가 남용, 권한 우회, 비용 폭탄, 데이터 과다 수집을 허용하는 문제다.무료 체험, 포인트, 쿠폰, AI 호출량 제한을 프런트 값으로만 판단한다.기능마다 악용 시나리오, 권한 행렬, rate limit, 서버 기준 상태 전이를 설계한다.
A07
Authentication Failures
로그인, 세션, 비밀번호 재설정, MFA, 토큰 만료, 계정 복구가 약한 문제다.JWT 만료가 없고 로그아웃해도 refresh token이 살아 있으며 재설정 링크가 재사용된다.짧은 access token, refresh token rotation, logout invalidation, MFA, 실패 제한을 적용한다.
A08
Software or Data Integrity Failures
검증되지 않은 업데이트, 웹훅, 역직렬화, 빌드 산출물, 백업 복구가 데이터와 코드를 변조하게 만드는 문제다.결제 웹훅 서명을 검증하지 않고 “paid=true” 이벤트만 보고 주문을 완료한다.서명 검증, idempotency key, 불변 로그, 빌드 서명, 검증 가능한 배포 경로를 둔다.
A09
Security Logging and Alerting Failures
침해가 일어나도 기록이 없거나 경보가 없어 뒤늦게 발견하는 문제다.로그에는 토큰과 이메일 전체가 찍히는데 정작 로그인 실패 급증, 관리자 변경, 대량 다운로드 경보는 없다.민감 정보는 마스킹하고 로그인 실패, 403 증가, 429 증가, 관리자 기능 호출, 대량 export에 경보를 둔다.
A10
Mishandling of Exceptional Conditions
예외, 경계값, 타임아웃, 부분 실패, 동시 요청, 외부 API 장애를 잘못 처리해 fail open이 되는 문제다.결제 검증 API가 실패하면 “사용자 경험”을 위해 결제를 성공 처리하거나 권한 검사를 건너뛴다.보안 판단은 실패 시 차단하고, 재시도와 보상 트랜잭션, 타임아웃, circuit breaker를 설계한다.

08 · 확장판

API, 모바일, LLM으로 확장된 보안

웹 Top 10만 보면 부족합니다. 지금의 앱은 API로 데이터를 주고받고, 모바일 앱이나 PWA로 확장되고, LLM이 요약, 추천, 검색, 자동 실행을 맡습니다. 그래서 OWASP도 API, 모바일, LLM 보안 문서를 별도로 운영합니다.

OWASP API Security Top 10 2023

  • API1 Broken Object Level Authorization
  • API2 Broken Authentication
  • API3 Broken Object Property Level Authorization
  • API4 Unrestricted Resource Consumption
  • API5 Broken Function Level Authorization
  • API6 Unrestricted Access to Sensitive Business Flows
  • API7 Server Side Request Forgery
  • API8 Security Misconfiguration
  • API9 Improper Inventory Management
  • API10 Unsafe Consumption of APIs

바이브 코딩 앱은 화면보다 API가 먼저 뚫린다. 객체 ID, 속성, 함수, 비즈니스 흐름 권한을 서버에서 모두 확인해야 한다.

OWASP Mobile Top 10 2024

  • Improper Credential Usage
  • Inadequate Supply Chain Security
  • Insecure Authentication and Authorization
  • Insufficient Input and Output Validation
  • Insecure Communication
  • Inadequate Privacy Controls
  • Insufficient Binary Protections
  • Security Misconfiguration
  • Insecure Data Storage
  • Insufficient Cryptography

모바일 앱을 함께 만들면 기기 저장소, API 키, 앱 권한, 바이너리 분석, 통신 보안까지 봐야 한다. 앱 안의 키는 결국 보인다고 생각해야 한다.

OWASP Top 10 for LLM Applications 2025

  • LLM01 Prompt Injection
  • LLM02 Sensitive Information Disclosure
  • LLM03 Supply Chain
  • LLM04 Data and Model Poisoning
  • LLM05 Improper Output Handling
  • LLM06 Excessive Agency
  • LLM07 System Prompt Leakage
  • LLM08 Vector and Embedding Weaknesses
  • LLM09 Misinformation
  • LLM10 Unbounded Consumption

LLM은 검색창이 아니라 판단하고 도구를 부르는 실행면이다. 프롬프트, 검색 결과, 파일, 웹페이지, 다른 사용자 입력을 모두 적대적 입력으로 봐야 한다.

09 · 보안 원칙

보안 원칙을 먼저 세워야 한다

보안 항목을 외우기 전에 원칙을 잡아야 합니다. 원칙이 없으면 “CORS 켰으니 안전한가요?”, “JWT 쓰면 암호화된 건가요?”, “D1은 RLS가 없으니 위험한가요?” 같은 질문이 매번 흔들립니다. 원칙이 있으면 플랫폼이 바뀌어도 같은 판단을 반복할 수 있습니다.

기밀성

볼 수 없어야 할 사람이 데이터를 보지 못하게 하는 원칙입니다. 개인정보, 토큰, 결제 정보, 관리자 로그, 백업이 여기에 속합니다.

무결성

데이터와 코드가 허가 없이 바뀌지 않게 하는 원칙입니다. 웹훅 서명, 빌드 산출물 검증, 관리자 변경 로그, 결제 금액 서버 검증이 여기에 속합니다.

가용성

서비스가 과도한 요청, 비용 폭탄, 큐 적체, 외부 API 장애에도 버티게 하는 원칙입니다. rate limit, timeout, retry, circuit breaker, quota가 필요합니다.

인증과 인가 분리

로그인은 신원 확인일 뿐입니다. 로그인한 사용자가 특정 리소스와 기능을 사용할 수 있는지는 매 요청마다 따로 확인해야 합니다.

최소 권한

사람, 서버, DB 계정, API key, AI agent, CI job이 자기 일에 필요한 권한만 갖게 합니다. 편하다는 이유로 관리자 권한을 기본값으로 주면 안 됩니다.

안전한 실패

보안 검사, 결제 검증, 권한 확인, 외부 API 검증이 실패하면 허용이 아니라 차단으로 끝나야 합니다. 예외 처리 실패는 2025 Top 10의 독립 항목입니다.

공격 표면 최소화

쓰지 않는 API, admin route, debug page, source map, public bucket, preview deployment, old domain, old token을 줄입니다.

심층 방어

프런트 UI, 서버 API, DB RLS, WAF, rate limit, 로그와 경보를 겹쳐 둡니다. 한 계층이 뚫려도 다음 계층이 막아야 합니다.

바이브 코딩 프롬프트에 넣을 기본 문장

“프런트 UI 숨김은 보안으로 보지 말고, 모든 민감 API는 서버에서 인증과 인가를 검증하고, 검증 실패 시 fail closed로 처리하고, 권한 없는 요청은 401/403/404로 차단하며, 로그에는 민감 정보를 남기지 마라.”

10 · 데이터

개인정보는 덜 모을수록 안전하다

보안의 첫 번째 기술은 암호화가 아니라 수집하지 않는 것입니다. 이메일이 없어도 되는 기능이면 이메일을 받지 않습니다. 전화번호가 꼭 필요하지 않으면 받지 않습니다. AI 대화 원문을 저장하지 않아도 된다면 저장하지 않습니다. 수집하지 않은 데이터는 유출될 수 없습니다.

  1. 1데이터 목록을 만든다. 회원 정보, 문의, 로그, 쿠키, 파일, 결제, AI 대화, 백업을 모두 적는다.
  2. 2각 항목에 목적, 법적 근거, 보존 기간, 삭제 방법, 접근 권한, 외부 전송 여부를 붙인다.
  3. 3화면에 필요한 필드만 API로 내려준다. user 객체 전체를 클라이언트로 넘기지 않는다.
  4. 4로그와 에러 추적 도구에는 PII 마스킹을 적용한다. 이메일 전체, 토큰, Authorization 헤더는 금지한다.
  5. 5테스트와 데모에는 실제 유저 데이터를 쓰지 않는다.

11 · 데이터 지도

데이터 지도와 신뢰 경계

보안 점검은 “우리 앱이 뭘 저장하지?”에서 시작합니다. DB 테이블만 보면 부족합니다. 로그, 파일, 캐시, 큐, 백업, 이메일 발송 내역, AI provider로 보낸 프롬프트, 분석 도구로 전송된 이벤트까지 포함해야 실제 유출 범위를 판단할 수 있습니다.

자산예시 데이터처리 목적접근 주체보존/삭제
회원 정보이메일, 닉네임, OAuth subject, role, plan가입, 로그인, 결제 권한 확인사용자 본인, 관리자 최소 인원탈퇴와 법정 보존 기간에 맞춰 삭제 또는 익명화
접속 로그IP, User-Agent, 요청 경로, 상태 코드, 시간보안 탐지, 장애 분석, 남용 방지운영자, 보안 로그 시스템짧게 보존하고 PII 마스킹
파일과 이미지업로드 파일, 썸네일, EXIF, 원본 파일명사용자 콘텐츠 제공소유자, 권한 있는 관리자삭제 요청 시 원본과 파생 파일 함께 삭제
AI 대화와 RAG 문서프롬프트, 첨부문서, 검색 결과, 모델 응답요약, 검색, 자동화기능별 최소 권한 agent원문 저장 여부를 별도 선택하고 민감 정보 필터링
결제와 과금주문 ID, 결제 상태, 상품, 금액, PG webhook ID서비스 제공과 정산재무/관리자 역할카드 원문은 저장하지 않고 PG token/reference만 사용
시크릿과 운영키DB URL, service key, API token, JWT secret서버 간 인증과 배포서버 런타임, 제한된 운영자노출 즉시 폐기하고 회전

신뢰 경계도 같이 그려야 합니다. 브라우저, 서버 API, DB, storage, queue, AI provider, 결제 provider, 관리자 페이지, 로그 시스템은 서로 다른 경계입니다. 한 경계에서 안전한 데이터가 다른 경계로 넘어가는 순간 새 위험이 생깁니다.

Copy Prompt

데이터 지도 감사 프롬프트

이 프로젝트의 데이터 지도를 작성하고 개인정보/민감정보 위험을 감사해줘.

확인할 것:
- DB table, storage bucket, cache, queue, log, backup, analytics, email, AI provider로 이동하는 데이터
- 이메일, 닉네임, IP, User-Agent, 결제, 파일, AI 대화, 관리자 로그, token 포함 여부
- 각 데이터의 수집 목적, 보존 기간, 삭제 방법, 접근 주체, 외부 전송 여부
- 화면/API 응답/로그에 과다 노출되는 필드

출력:
| 데이터 | 위치 | 개인정보 여부 | 목적 | 접근 주체 | 보존/삭제 | 위험 | 조치 |

실제 개인정보 값은 출력하지 말고 마스킹해줘.

Part 03 · Core Defenses

서버, DB, 계정, 관리자 권한을 먼저 잠근다

시크릿, 인증, 인가, RLS, 관리자 페이지, DB 플랫폼 보안선은 보안 칼럼의 중심입니다. 여기서 막히면 나머지 방어도 흔들립니다.

12 · 시크릿

시크릿, 환경변수, 키 관리

키는 비밀번호보다 더 위험할 때가 많습니다. 사용자 비밀번호는 보통 특정 계정 하나를 열지만, service key와 DB password는 전체 데이터베이스를 열 수 있습니다. 바이브 코딩에서 가장 흔한 실수는 “돌아가게 하려고” 강한 키를 클라이언트나 Git에 넣는 것입니다.

저장 위치

  • `.env`, `.env.local`, production secret은 Git에 커밋하지 않는다.
  • `.env.example`에는 실제 값이 아니라 placeholder만 둔다.
  • Vercel, Cloudflare, Railway, GitHub Actions의 Production, Preview, Development secret을 분리한다.
  • Dockerfile에 `ENV API_KEY=...`나 `COPY .env .`를 넣지 않는다.
  • Slack, Notion, Google Drive, Figma, 이슈, 스크린샷, 커뮤니티 질문에도 키가 남지 않게 검색한다.

노출 대응

  • Git 히스토리에 키가 들어갔다면 `.gitignore` 추가만으로 끝나지 않는다. 키를 즉시 폐기하고 새로 발급한다.
  • gitleaks, trufflehog, GitHub secret scanning으로 전체 히스토리를 확인한다.
  • 히스토리 정리는 BFG나 git filter-repo를 쓰되, 이미 노출된 키는 무조건 교체한다.
  • CI 로그, 빌드 로그, 에러 로그에 `${{ secrets.* }}` 값이 출력되지 않게 masking을 확인한다.
  • 오래된 키, 미사용 키, 권한이 큰 키는 정기적으로 폐기한다.

권한과 회전

  • service_role, DB password, Cloudflare API token, Turso token은 서버 전용으로 둔다.
  • 읽기 전용, 특정 조직, 특정 DB, 특정 bucket, 특정 branch 등 scope를 줄인다.
  • 공유 계정 키보다 개인별 또는 서비스별 키를 사용해 추적 가능하게 한다.
  • 키 회전 주기와 비상 회전 절차를 문서화한다.
  • AI 코딩 도구나 agent에게 production secret을 주지 않는다.

Copy Prompt

시크릿 감사 프롬프트

이 저장소에서 secret, API key, DB URL, service role key 노출 가능성을 감사해줘.

검사 범위:
- .env, .env.local, .env.example, README, docs, scripts, public, GitHub Actions
- NEXT_PUBLIC_에 붙은 값 중 secret으로 보이는 값
- Supabase service_role, Turso token, Cloudflare token, OpenAI/Anthropic/Stripe secret
- Dockerfile, build log, console.log, error logging에서 secret 출력 가능성

출력:
- 노출 확인 / 의심 / 판단 불가로 구분
- 원문 secret은 절대 출력하지 말고 마스킹
- 노출된 키는 "숨김"이 아니라 "폐기 및 재발급"으로 조치 제안

노출된 키는 숨기는 것이 아니라 폐기하는 것이다

이미 GitHub, 빌드 로그, 브라우저 번들, 커뮤니티 질문, 스크린샷에 노출된 키는 회수됐다고 볼 수 없습니다. 노출된 순간부터 누군가 복사했을 수 있으므로 새 키를 발급하고 기존 키를 폐기해야 합니다.

API 키는 “데이터 접근권”이면서 동시에 “청구서 발생 권한”입니다. 자동결제, 자동 리로드, 넓은 IAM 권한, 만료 없는 키가 겹치면 보안 사고가 곧 비용 폭탄이 됩니다. 키 보관·스코프·회전·결제 한도는 API 키 관리와 결제 폭탄 방지를 기준으로 함께 점검하세요.

13 · 인증과 세션

인증, 세션, 비밀번호 복구

로그인 기능은 보통 AI가 쉽게 만들어줍니다. 하지만 안전한 인증은 로그인 화면보다 훨씬 넓습니다. 세션 저장 위치, 토큰 만료, refresh token rotation, 로그아웃 무효화, 비밀번호 재설정, MFA, 계정 열거 방지, 관리자 세션 정책까지 같이 봐야 합니다.

세션과 토큰

  • 민감 토큰은 localStorage보다 HttpOnly, Secure, SameSite 쿠키를 우선 검토한다.
  • HttpOnly 쿠키가 XSS를 완전히 막는 것은 아니므로 CSP, 입력 검증, 출력 인코딩을 같이 둔다.
  • 세션 ID와 토큰은 URL query, fragment, referer, 로그에 남기지 않는다.
  • 로그인 직후, 권한 상승, MFA 통과, 관리자 전환 후에는 세션 ID를 재발급해 session fixation을 막는다.
  • JWT payload는 암호화가 아니라 인코딩이다. 비밀번호, 주민번호, 결제 정보, 내부 권한 구조를 넣지 않는다.
  • JWT 검증은 `alg` allowlist, issuer, audience, expiry, clock skew, `kid` 처리 정책을 고정하고 `alg=none`과 HS256/RS256 혼동을 차단한다.
  • access token은 짧게, refresh token은 rotation과 재사용 탐지를 적용한다.
  • refresh token은 원문 저장을 피하고 서버 저장 해시, token family, 재사용 탐지 시 전체 family 폐기를 검토한다.
  • 로그아웃, 비밀번호 변경, MFA 변경, 권한 변경, 탈퇴 후 기존 세션과 refresh token을 무효화한다.
  • 쿠키 Domain은 넓게 잡지 말고 Path, Max-Age, `__Host-` prefix, Clear-Site-Data 적용 가능성을 확인한다.
  • 토큰, OTP, reset code, webhook 서명 비교는 일반 문자열 비교가 아니라 timing-safe comparison을 검토한다.
  • 세션 ID, reset token, OTP secret은 CSPRNG로 만들고 `Math.random()` 같은 예측 가능한 난수는 쓰지 않는다.

비밀번호와 계정 복구

  • 비밀번호는 Argon2id, bcrypt, scrypt 같은 느린 KDF로 저장한다. SHA-256 단독 해시는 금지한다.
  • bcrypt는 72바이트 입력 제한을 알고 긴 passphrase 정책을 설계한다.
  • 재설정 token은 1회용, 짧은 만료, 재사용 불가, 서버 저장 해시로 관리한다.
  • 비밀번호 재설정 응답은 계정 존재 여부를 노출하지 않는다.
  • 재설정 링크는 Host 헤더로 만들지 말고 고정된 서비스 URL 기준으로 만든다.
  • 비밀번호 변경, 이메일 변경, MFA 해제, 계정 복구에는 최근 로그인 또는 재인증을 요구한다.
  • 재설정 token, 이메일 인증 token, magic link는 access log와 analytics URL에 남지 않게 한다.
  • 비밀번호 재설정, magic link, 이메일 인증 요청은 계정, IP, 기기, 세션 단위 rate limit과 resend cooldown을 둔다.
  • 비밀번호 재설정 성공 후 자동 로그인하지 말고, 기존 세션 정리와 보안 알림을 보낸다.

브루트포스와 자동화 방어

  • 로그인, OTP, MFA, 비밀번호 재설정, 이메일 인증 코드 검증은 시도 횟수 제한, 점진적 지연, 위험 기반 CAPTCHA를 둔다.
  • lockout은 계정 마비 공격으로 악용될 수 있으므로 짧은 임시 잠금, 단계적 지연, 사용자 알림, 관리자 해제 절차를 같이 설계한다.
  • credential stuffing 방어를 위해 유출 비밀번호 재사용 탐지, 의심 로그인 알림, 새 기기 추가 인증, MFA 권장을 적용한다.
  • OTP와 이메일/SMS 코드는 짧은 만료, 재전송 시 이전 코드 폐기, 검증 실패 횟수 제한, 서버 저장 해시를 적용한다.
  • 인증 실패 로그는 이메일 전체와 입력한 비밀번호를 남기지 말고, IP/ASN/device/user-agent 기반 이상 징후를 집계한다.

MFA와 관리자 계정

  • 관리자, 배포자, 결제 관리자, DB 운영자 계정에는 MFA를 필수로 둔다.
  • 가능하면 SMS보다 인증 앱, 더 가능하면 FIDO2/WebAuthn 같은 phishing-resistant 방식을 검토한다.
  • 관리자 세션은 일반 사용자보다 짧은 유휴 만료와 절대 만료를 둔다.
  • 관리자 로그인 성공, 새 기기 로그인, 권한 변경은 별도 알림을 보낸다.
  • super_admin 수를 줄이고 역할을 콘텐츠, 사용자, 시스템, 재무 등으로 나눈다.

이메일·SMS·알림 채널

  • 계정 복구와 인증 메일 발송 도메인은 SPF, DKIM, DMARC를 설정하고 서비스 도메인과 발송 도메인의 신뢰 경계를 문서화한다.
  • reset link, magic link, 초대 링크에 `next`, `returnTo`, `redirect`가 붙는다면 같은 origin 또는 서버 allowlist만 허용한다.
  • 알림 메일의 링크는 추적용 redirect를 거치더라도 최종 목적지를 검증하고, 피싱처럼 보이는 단축 URL을 피한다.
  • 이메일/SMS 발송 API는 남용되기 쉬우므로 발송량 quota, resend cooldown, 수신자별 제한, bounce/complaint 모니터링을 둔다.
  • 광고성 이메일, 문자, 카카오 알림은 정보성 메시지와 분리하고 수신 동의, 수신거부, 야간 전송 별도 동의 여부를 확인한다.

회원가입과 로그인을 직접 만드는 순간 책임도 직접 진다

bcrypt 한 줄과 JWT 발급만으로 인증이 끝나지 않습니다. 비밀번호 KDF 파라미터, bcrypt 72바이트 제한, JWT 저장 위치, refresh token rotation, OAuth state와 PKCE, 계정 열거 방지, 크리덴셜 스터핑, MFA/패스키, 비밀번호 재설정 토큰까지 전부 운영 책임입니다.

신규 서비스는 Auth.js만 붙이고 끝내기보다 Clerk, WorkOS, Supabase Auth, Firebase Auth, Auth0 같은 매니지드 인증을 우선 검토하세요. 자체 인증의 위험은 회원가입 직접 만들면 망하는 이유에서 별도 사례와 체크리스트로 이어집니다.

Copy Prompt

인증·세션 감사 프롬프트

인증, 세션, JWT, refresh token, 비밀번호 복구 플로우를 감사해줘.

확인할 것:
- 로그인 성공 후 세션 저장 위치와 만료 시간
- 로그인 직후/권한 상승/MFA 통과 후 세션 ID 재발급과 session fixation 방어
- JWT alg allowlist, alg=none 차단, HS256/RS256 혼동 방지, issuer, audience, expiry, kid 처리 검증
- refresh token rotation, 서버 저장 해시, token family, 재사용 탐지
- logout, 비밀번호 변경, 탈퇴, 권한 변경 후 기존 세션과 refresh token 무효화
- 쿠키 HttpOnly, Secure, SameSite, Domain, Path, Max-Age, __Host- prefix 적용 여부
- token/OTP/webhook signature 비교의 timing-safe comparison 적용 여부
- 세션 ID, reset token, OTP secret 생성에 CSPRNG를 쓰는지
- 비밀번호 저장 KDF, reset token 1회용/만료/재사용 방지
- 로그인, OTP, MFA, reset 요청의 계정/IP/기기/세션 단위 rate limit, 점진적 지연, CAPTCHA, 임시 lockout
- 계정 존재 여부 노출, 로그인 실패 제한, credential stuffing 방어, MFA 적용 여부
- 비밀번호/이메일/MFA 변경과 계정 복구의 재인증 요구
- 이메일/SMS 인증 코드의 resend cooldown, 실패 횟수 제한, 이전 코드 폐기
- SPF/DKIM/DMARC, reset link 피싱/open redirect, 발송 abuse 모니터링

공격 시나리오와 방어 근거를 표로 정리해줘.

14 · 권한

인증, 인가, RLS를 분리해서 봐라

인증은 “누구인가”이고 인가는 “무엇을 할 수 있는가”입니다. 로그인만 확인하고 모든 데이터를 열어 주는 앱은 보안 앱이 아닙니다. 바이브 코딩에서 가장 먼저 확인할 것은 모든 민감 API가 “이 사용자가 이 리소스에 접근할 수 있는가”를 서버에서 확인하는지입니다.

인증

세션, JWT, OAuth, 비밀번호, MFA, refresh token, 로그아웃 무효화, 계정 복구가 여기에 속합니다.

인가

owner, role, tenant_id, plan, feature flag, 관리자 권한, 조직 권한, 파일 소유권 검사가 여기에 속합니다.

RLS

DB 레벨에서 row별 접근을 제한합니다. PostgreSQL과 Supabase에서는 강력하지만 명시적으로 켜고 정책을 만들어야 합니다.

테스트

토큰 없음, 다른 유저 토큰, 탈퇴 유저 토큰, 만료 토큰, 일반 유저 토큰으로 같은 API를 반복 호출합니다.

RLS의 핵심

PostgreSQL은 기본적으로 테이블에 RLS 정책이 없습니다. `ENABLE ROW LEVEL SECURITY` 후 정책이 없으면 default deny가 되지만, table owner와 `BYPASSRLS` 권한은 우회할 수 있습니다. 그래서 app role, migration role, service role을 분리하고 실제 권한으로 테스트해야 합니다.

Copy Prompt

인가·RLS 감사 프롬프트

접근 통제, IDOR/BOLA, RLS를 집중 감사해줘.

확인할 것:
- 모든 민감 API에서 로그인 여부뿐 아니라 owner, role, tenant_id, plan을 서버에서 검증하는지
- URL/body의 userId, memoId, orderId, fileId를 바꿨을 때 다른 사용자 데이터 접근이 가능한지
- Supabase/Postgres RLS가 table별로 활성화되어 있는지
- policy가 anon/authenticated/service role에서 실제로 어떻게 동작하는지
- service role이 브라우저 또는 클라이언트 코드로 내려가는지

출력:
| API/table | 필요한 권한 | 현재 검증 위치 | 우회 시나리오 | 상태 | 수정 방향 | 테스트 방법 |

15 · 관리자

관리자 페이지는 별도 보안 제품처럼 다뤄라

관리자 페이지는 사용자 데이터, 결제 상태, 권한 변경, 사이트 설정이 모이는 고권한 구역입니다. 단순히 `/admin` 경로를 숨기거나 메뉴를 비활성화하는 것은 방어가 아닙니다. 관리자 기능은 일반 앱보다 더 짧은 세션, 더 강한 인증, 더 촘촘한 권한, 더 상세한 감사 로그가 필요합니다.

관리자 인증 계층

  • 관리자 라우트는 일반 사용자 라우트와 같은 guard 하나로 끝내지 말고 별도 middleware, 별도 세션 정책, 별도 audit log를 둔다.
  • 관리자 계정에는 MFA를 필수로 적용하고, 가능하면 FIDO2/WebAuthn 같은 phishing-resistant 인증을 우선한다.
  • JWT payload의 `role: admin`만 믿지 말고 서명, issuer, audience, 만료, 서버 DB의 현재 권한을 함께 확인한다.
  • 관리자 세션은 일반 세션보다 짧은 유휴 만료와 절대 만료를 두고 권한 변경, 비밀번호 변경, MFA 변경 후 재인증을 요구한다.
  • 관리자 로그인 실패, 새 기기 로그인, 새 관리자 생성, 권한 상승은 즉시 알림을 보낸다.

접근제어와 네트워크 경계

  • `/admin` 경로 숨김, robots 차단, 메뉴 숨김은 보안이 아니라 힌트 감소에 불과하다.
  • 관리자 API는 role뿐 아니라 대상 리소스, tenant, 조직, plan, 업무 범위를 서버에서 다시 검증한다.
  • 가능하면 Cloudflare Access, VPN, Tailscale, Zero Trust, IP allowlist 같은 접속 경로 보호를 겹친다.
  • IP allowlist는 보조 방어선이다. 재택, 모바일, VPN, 프록시 환경을 고려하되 인증과 인가를 대체하지 않는다.
  • 관리자 export, 사용자 조회, 결제 상태 변경, 권한 변경은 별도 role과 승인 흐름을 둔다.

관리자 행위 로그

  • 누가, 언제, 어떤 IP/기기에서, 어떤 관리자 기능으로, 어떤 대상 리소스를, 어떻게 바꿨는지 남긴다.
  • 대량 조회, 대량 export, 권한 변경, 결제 상태 변경, 설정 변경은 변경 전/후를 마스킹된 형태로 기록한다.
  • 감사 로그에는 비밀번호, 토큰, reset token, 카드번호 원문을 남기지 않는다.
  • 관리자 로그는 일반 앱 로그보다 변조 위험이 크므로 별도 저장소, 보존 기간, 접근 권한을 둔다.
  • 관리자 기능 배포 전에는 일반 사용자 계정, 탈퇴 계정, 권한 없는 관리자 계정으로 직접 접근 테스트를 한다.

Copy Prompt

관리자 페이지 보안 감사 프롬프트

관리자 페이지를 일반 사용자 기능과 분리된 고권한 보안 영역으로 감사해줘.

확인할 것:
- 관리자 route와 API가 별도 middleware/guard를 통과하는지
- role 값만 믿지 않고 서버 DB의 현재 권한, tenant, 업무 범위를 다시 확인하는지
- 관리자 MFA, 짧은 세션, 재인증, 로그아웃/권한 변경 후 세션 무효화
- CSRF token, Origin/Referer 검증, CORS 오해, 관리자 mutation 보호
- IP allowlist, Cloudflare Access, VPN, Zero Trust, 관리자 경로 노출
- 새 관리자 생성, 권한 변경, 대량 export, 결제 상태 변경 감사 로그
- 일반 사용자/권한 없는 관리자/탈퇴 계정으로 직접 접근 테스트

출력:
| 관리자 기능 | 필요한 권한 | 현재 방어 | 우회 시나리오 | 로그 여부 | 위험도 | 조치 |

관리자 페이지 보안의 핵심 문장

관리자는 “로그인한 사용자 중 role이 admin인 사람”이 아니라, 별도 신뢰 경계 안에서 MFA, 재인증, 권한 행렬, 네트워크 제한, 감사 로그를 모두 통과한 운영 주체입니다. 관리자 페이지 전 계층 방어는 관리자 페이지 보안 설정 풀가이드에서 더 자세히 이어집니다.

16 · DB와 플랫폼

Supabase, D1, Turso, VPS Postgres 보안선

DB마다 보안 모델이 다릅니다. Supabase는 RLS를 중심으로 브라우저 클라이언트와 직접 연결되는 사용성을 줍니다. Cloudflare D1은 Workers binding으로 서버 코드에서 접근하는 형태가 자연스럽습니다. Turso는 토큰 기반 접근이므로 scope와 노출 위치가 중요합니다. VPS Postgres는 직접 운영하는 만큼 방화벽, 계정, 백업, 패치까지 본인 책임입니다.

저장소안전한 사용선위험한 패턴
Supabaseanon key는 RLS 정책이 있을 때만 클라이언트에서 의미가 있다. service_role은 서버 전용이다.service_role key를 브라우저에 넣거나 RLS 없이 anon key로 테이블을 연다.
Cloudflare D1Workers/Pages Functions에서 binding으로 접근하고 API에서 인증, 인가, rate limit을 구현한다.D1 REST/API token을 클라이언트에 두거나 서버 API를 공개 write endpoint로 만든다.
TursoAPI token은 환경변수에 두고 organization/group/read-only scope로 줄인다.unrestricted token을 CI, 로그, GitHub, 브라우저 번들에 노출한다.
VPS Postgres방화벽, private network, least privilege role, RLS, backup encryption, patching을 직접 운영한다.postgres superuser로 앱을 붙이고 5432를 인터넷에 열어 둔다.

Supabase를 방문 카운트만 쓴다면

방문 카운트처럼 공개 통계에 가까운 데이터만 저장해도 write 남용, 비용 증가, 로그 노출은 남습니다. RLS 또는 서버 API rate limit을 두고, service_role은 서버에서만 써야 합니다.

D1은 RLS가 없는 대신

D1은 Worker binding으로 서버 코드 안에서 접근하는 모델에 맞습니다. 따라서 API handler가 tenant, owner, role, plan, rate limit을 직접 검증해야 합니다.

Turso는 토큰이 경계다

Turso는 토큰 없이는 접근할 수 없다는 점이 장점이지만, 그 토큰이 브라우저와 로그에 노출되면 경계가 사라집니다. scope와 회전이 핵심입니다.

VPS Postgres는 운영이 보안이다

직접 설치한 Postgres는 `.postgres` 데이터 경로, 백업, role, RLS, 방화벽, 패치, superuser 사용 여부까지 모두 운영자가 책임져야 합니다.

Copy Prompt

DB 플랫폼 감사 프롬프트

현재 DB 구성을 Supabase, Cloudflare D1, Turso, VPS Postgres 관점으로 감사해줘.

확인할 것:
- Supabase: RLS, service_role 위치, storage bucket public/private, anon policy
- D1: Worker binding 사용 여부, API handler의 인증/인가/rate limit
- Turso: token scope, read-only token, 브라우저/로그/CI 노출 여부
- VPS Postgres: 5432 인터넷 노출, app role least privilege, superuser 사용, backup encryption, RLS, patching
- 개발/preview/production DB 분리

각 저장소별 "안전한 경계"와 "현재 깨진 경계"를 구분해줘.

Part 04 · Attack Surface

입력, 파일, LLM, 공급망, 트래픽까지 공격면을 줄인다

기능이 늘수록 공격면도 늘어납니다. 업로드, 브라우저 노출, AI agent, 패키지, 클라우드, 결제, DDoS를 같은 운영 보안선 안에서 봅니다.

17 · 입출력

입력값, 출력값, 파일 업로드 방어

서버는 모든 입력을 적대적으로 봐야 합니다. 브라우저 검증은 UX이고, 보안 검증은 서버에서 합니다. 특히 파일 업로드와 외부 URL 입력은 작은 기능처럼 보이지만 XSS, path traversal, malware hosting, SSRF, 비용 폭탄으로 이어질 수 있습니다.

입력값

  • Content-Type, Content-Length, body size, field allowlist를 검증한다.
  • SQL은 parameter binding을 쓰고 column, order, table 이름처럼 binding 불가한 값은 allowlist로 제한한다.
  • JSON body 전체를 DB update에 넣지 않는다. role, plan, user_id 같은 서버 관리 필드는 무시한다.
  • 외부 URL, redirect URL, file path, command argument, template name, LLM tool argument는 각각 별도 allowlist를 둔다.
  • 로그인 후 이동, OAuth callback, 이메일 링크의 `next`, `returnTo`, `redirect`는 open redirect로 보고 상대 경로 또는 서버 매핑 ID만 허용한다.

CORS·CSRF·SSRF

  • CORS는 필요한 origin만 허용한다. CORS를 인증이나 권한 통제라고 착각하지 않는다.
  • 쿠키 인증을 쓰는 상태 변경 API는 CSRF token, Origin/Referer, SameSite, Fetch Metadata 중 최소 하나 이상을 서버에서 검증한다.
  • 서버가 URL을 fetch하는 기능은 SSRF로 본다. `localhost`, private IP, link-local, metadata IP, redirect, DNS rebinding을 차단한다.
  • 웹훅 endpoint는 CORS 대상이 아니다. raw body 서명, timestamp, event id, provider allowlist로 검증한다.

출력값

  • HTML, Markdown, rich text, LLM 출력은 렌더링 전 sanitizer와 escaping을 적용한다.
  • API 응답에는 화면에 필요한 필드만 내려준다.
  • 오류 응답에는 stack trace, DB 테이블명, 내부 경로, 라이브러리 버전을 노출하지 않는다.
  • redirect URL은 같은 origin 또는 allowlist만 허용하고, 허용 후에도 최종 URL을 canonicalize해서 검증한다.

파일

  • 파일명은 서버에서 새로 만든다. 사용자 파일명과 경로를 그대로 쓰지 않는다.
  • 크기 제한, 확장자 allowlist, MIME 검증, magic byte 검증, 이미지 재인코딩, EXIF 제거를 검토한다.
  • SVG, HTML, JS, 실행 파일은 public 업로드 경로에 두지 않는다.
  • 업로드 파일은 실행 불가 저장소에 두고 public 서빙 도메인과 앱 쿠키 도메인을 분리한다.
  • 다운로드 API에서 `../`, 절대경로, 숨김 파일 접근이 불가능한지 테스트한다.

Copy Prompt

입출력·Injection 감사 프롬프트

입력값, 출력값, injection 방어를 감사해줘.

source:
- query, path param, body, header, cookie, file, external API response, DB data, AI output

sink:
- SQL/NoSQL, OS command, HTML/Markdown, file path, redirect URL, external fetch, template, dynamic code, LLM prompt/tool call

요구:
- source에서 sink까지 경로를 표로 추적
- parameter binding, allowlist, escaping, sanitizer가 sink별로 맞는지 확인
- body 전체 update, mass assignment, role/plan/price 조작 가능성 확인
- CORS wildcard/credentials, origin reflection, 과도한 allow header 확인
- CSRF token, Origin/Referer, SameSite, Fetch Metadata가 상태 변경 요청에 적용되는지 확인
- SSRF 가능 external fetch는 scheme allowlist, redirect 재검증, DNS rebinding, private IP, metadata IP, IPv6 우회를 테스트
- 로그인 후 이동, OAuth callback, 이메일 링크의 next/returnTo/redirect/callbackUrl open redirect 테스트
- 정제가 일부 경로에만 있으면 취약으로 표시

18 · 프론트엔드

프론트엔드, Next.js, 브라우저 노출

프론트엔드는 사용자가 코드를 내려받는 공간입니다. 숨긴 버튼, 비활성화된 메뉴, 난독화된 JS, `NEXT_PUBLIC_` 환경변수는 모두 공격자가 볼 수 있다고 생각해야 합니다. 보안 판단은 프런트가 아니라 서버와 DB 정책에서 끝나야 합니다.

브라우저 노출

  • `NEXT_PUBLIC_`이 붙은 값은 공개 정보라고 본다. secret, service key, DB URL을 넣지 않는다.
  • 서버 컴포넌트에서 클라이언트 컴포넌트로 user 객체 전체를 넘기지 않는다.
  • Network 응답에 화면에서 쓰지 않는 이메일, role, internal id, 결제 정보, token이 내려오지 않는지 본다.
  • 프로덕션 source map, debug route, test fixture, sample JSON이 public 경로에 없는지 확인한다.
  • `robots.txt`로 `/admin`을 숨기는 것은 보안이 아니다. 오히려 경로 힌트가 될 수 있다.
  • 로그아웃 시 localStorage, sessionStorage, IndexedDB, Service Worker cache, in-memory store에 남은 개인정보와 토큰을 정리한다.
  • 공용 기기 시나리오에서는 뒤로가기, 자동완성, 브라우저 캐시, 다운로드 파일명에 민감 정보가 남지 않는지 확인한다.

XSS와 보안 헤더

  • `dangerouslySetInnerHTML`, `innerHTML`, Markdown renderer, rich editor, LLM output renderer를 XSS sink로 본다.
  • CSP는 nonce 또는 hash 기반으로 시작하고 `unsafe-inline`, `unsafe-eval`을 줄인다.
  • HSTS, X-Frame-Options 또는 frame-ancestors, X-Content-Type-Options, Referrer-Policy, Permissions-Policy를 점검한다.
  • 클릭재킹 방어가 필요한 관리자와 결제 화면에는 frame 제한을 명확히 둔다.
  • 오류 페이지와 500 응답에 stack trace, 내부 경로, DB 테이블명, 라이브러리 버전을 노출하지 않는다.

CORS와 CSRF

  • CORS는 브라우저 읽기 정책이고 인증/인가가 아니다. API는 CORS와 별개로 서버 권한 검사를 해야 한다.
  • `Access-Control-Allow-Origin: *`와 `Access-Control-Allow-Credentials: true` 조합, origin reflection, 과도한 allow header를 피한다.
  • 쿠키 기반 인증의 상태 변경 요청은 CSRF token, signed double-submit cookie, Origin/Referer 검증, Fetch Metadata를 조합한다.
  • GET 요청은 상태를 바꾸지 않게 하고, 관리자/결제/비밀번호 변경 요청은 재인증 또는 사용자 상호작용을 추가한다.
  • 웹훅과 외부 연동 endpoint는 브라우저 CORS가 아니라 서명 검증, replay 방지, 허용 event type으로 보호한다.

캐시와 클라이언트 저장소

  • 개인정보, 결제, 관리자, 인증 후 API 응답은 `Cache-Control: no-store` 또는 서비스 성격에 맞는 private cache 정책을 둔다.
  • CDN 캐시는 Authorization, Cookie, tenant, language, query를 캐시 키에 어떻게 반영하는지 확인하고 인증 응답이 public cache에 섞이지 않게 한다.
  • Service Worker는 API 응답을 무심코 cache-first로 저장하지 않게 하고, 로그아웃/계정 전환 시 관련 cache를 삭제한다.
  • 페이지 뒤로가기와 bfcache로 민감 화면이 복원되는 경우를 테스트하고, 필요하면 no-store와 클라이언트 상태 정리를 병행한다.
  • 공개 CDN에 HTML을 캐시할 때 사용자별 콘텐츠, A/B 테스트 쿠키, 관리자 preview가 cache poisoning으로 섞이지 않는지 확인한다.

iframe·embed·postMessage

  • 외부 iframe, embed, 광고, 위젯은 가능한 sandbox와 최소 allow 속성을 적용한다.
  • postMessage는 `targetOrigin: "*"`를 피하고, 수신 측은 exact origin, message schema, action allowlist를 검증한다.
  • YouTube, 지도, 결제, 댓글, 분석 스크립트는 어떤 쿠키와 개인정보를 제3자에게 보내는지 개인정보 처리방침과 일치시킨다.
  • iframe 안의 콘텐츠가 부모 창을 이동시키거나 새 탭을 열 수 있는 권한을 필요한 만큼만 준다.
  • 관리자와 결제 화면은 frame-ancestors 또는 X-Frame-Options로 원치 않는 embedding을 막는다.

CORS에 대한 흔한 오해

CORS는 브라우저가 다른 출처의 응답을 읽을 수 있는지에 대한 정책입니다. 서버 API 자체를 보호하는 인증/인가 기능이 아닙니다. `Access-Control-Allow-Origin: *`가 위험할 수는 있지만, CORS를 닫았다고 API 권한 검사가 끝난 것도 아닙니다.

Copy Prompt

프론트엔드 노출 감사 프롬프트

프론트엔드와 브라우저 노출을 감사해줘.

확인할 것:
- NEXT_PUBLIC_ 환경변수에 secret이 들어갔는지
- 서버 데이터가 클라이언트 컴포넌트 props로 과다 전달되는지
- Network 응답에 화면에서 안 쓰는 민감 필드가 있는지
- dangerouslySetInnerHTML, innerHTML, Markdown renderer, LLM output renderer
- CSP, HSTS, frame-ancestors/X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy
- production source map, debug route, public test data
- Cache-Control no-store/private, CDN cache key, 인증 응답 public cache 가능성
- localStorage, sessionStorage, IndexedDB, Service Worker cache, 로그아웃 후 클라이언트 저장소 정리
- 뒤로가기/bfcache에서 민감 화면이 남는지
- iframe sandbox/allow, postMessage targetOrigin과 수신 origin/schema 검증

결과는 파일/컴포넌트/응답 필드 기준으로 정리해줘.

19 · 파일

파일, 스토리지, 다운로드 보안

파일 업로드는 “이미지 하나 올리는 기능”처럼 보여도 공격면이 넓습니다. 파일명, 확장자, MIME, 경로, EXIF, public bucket, signed URL, 썸네일 생성기, 다운로드 API, 캐시와 백업이 모두 보안 범위입니다.

업로드

  • 파일 크기 제한은 개별 파일과 전체 요청 모두에 둔다.
  • 파일명은 서버에서 새로 만들고 원본 파일명은 표시용 메타데이터로만 저장한다.
  • 확장자와 MIME type은 allowlist로 검증하고, 이미지라면 가능하면 재인코딩한다.
  • MIME만 믿지 말고 magic byte, 실제 디코딩 가능 여부, 이중 확장자, 대소문자 우회, null byte를 점검한다.
  • SVG, HTML, JS, 실행 파일은 public bucket에 두지 않는다.
  • 업로드 저장소는 실행 권한을 제거하고 앱 서버와 업로드 서빙 도메인을 가능하면 분리한다.
  • 이미지 리사이징, PDF 변환, 압축 해제 라이브러리는 sandbox, resource limit, 최신 패치, zip bomb/압축 해제 경로 우회를 확인한다.
  • 이미지 EXIF에는 위치, 시간, 기기 정보가 있을 수 있으므로 제거를 검토한다.

다운로드와 스토리지

  • 다운로드 API는 파일 소유권 또는 권한을 서버에서 확인한다.
  • `?file=../../.env` 같은 path traversal을 테스트한다.
  • public bucket URL을 로그아웃 상태와 다른 사용자 계정으로 열어 본다.
  • 삭제 요청 시 원본, 썸네일, 변환 파일, 캐시, 백업의 처리 범위를 문서화한다.
  • signed URL은 짧은 만료와 최소 권한으로 발급한다.

Copy Prompt

파일·스토리지 감사 프롬프트

파일 업로드, 다운로드, storage bucket을 감사해줘.

확인할 것:
- 파일 크기 제한, 전체 요청 크기 제한
- 서버 생성 파일명 사용 여부
- MIME/확장자 allowlist, magic byte, 이중 확장자, 대소문자, null byte 우회
- SVG/HTML/JS/실행 파일 차단, 업로드 저장소 실행 권한 제거
- 이미지 재인코딩, EXIF 제거, 이미지/PDF 변환 라이브러리 sandbox와 패치 상태
- zip bomb, archive traversal, 대용량 압축 해제, 썸네일 생성 resource limit
- 앱 쿠키 도메인과 업로드 파일 서빙 도메인 분리 여부
- public bucket URL을 로그아웃/다른 계정으로 열 수 있는지
- signed URL 만료와 권한 범위
- 다운로드 API path traversal: ../, 절대경로, encoded path
- 삭제 요청 시 원본/썸네일/cache/backup 처리 범위

공격 시나리오와 수동 테스트 절차를 같이 써줘.

20 · LLM

LLM과 에이전트 보안

LLM 기능은 검색창이 아닙니다. 요약, 추천, 분류, 코드 실행, 파일 읽기, 이메일 발송, DB 조회, 브라우저 자동화가 붙으면 LLM은 도구를 가진 실행 주체가 됩니다. 그래서 사용자의 입력만이 아니라 웹페이지, 문서, 검색 결과, 파일 내용, 이전 대화까지 모두 공격면입니다.

프롬프트 인젝션

“이전 지시 무시”보다 더 현실적인 공격은 외부 문서 안에 도구 호출 유도, 데이터 exfiltration, 시스템 프롬프트 요청을 심는 것입니다.

민감 정보 노출

시스템 프롬프트, RAG 문서, 다른 사용자 데이터, API 응답, 로그가 모델 답변으로 흘러나올 수 있습니다.

과도한 자율성

에이전트가 삭제, 결제, 메일 발송, 배포, DB migration을 자동 실행하면 작은 프롬프트가 실제 피해가 됩니다.

출력 처리

LLM 답변을 HTML, SQL, shell, 코드 실행기, API call에 그대로 넣으면 기존 인젝션이 LLM을 통해 다시 살아납니다.

RAG 권한 경계

검색 결과와 벡터 문서는 사용자별 ACL을 유지해야 합니다. 검색된 chunk가 곧 답변 가능 데이터라는 뜻은 아닙니다.

도구 호출 정책

모델이 도구 이름과 인자를 골라도 서버가 schema, 권한, quota, 승인 단계, 대상 리소스를 다시 검증해야 합니다.

LLM 보안의 기본선

모델에게 비밀을 맡기지 말고, 도구 권한을 줄이고, 검색 결과와 파일을 신뢰하지 말고, 실행 전 검증하고, 비용과 호출량을 제한하고, 중요한 행동에는 사람 승인을 둡니다.

Copy Prompt

LLM·AI Agent 감사 프롬프트

LLM, RAG, AI agent 기능을 OWASP LLM Top 10 관점으로 감사해줘.

확인할 것:
- Prompt Injection, Sensitive Information Disclosure, Supply Chain, Data/Model Poisoning
- Improper Output Handling, Excessive Agency, System Prompt Leakage
- Vector/Embedding Weaknesses, Misinformation, Unbounded Consumption
- 시스템 프롬프트를 비밀 저장소처럼 취급하지 않는지, 유출돼도 권한 우회가 안 되는지
- agent가 파일 삭제, DB write, 배포, 이메일, 결제 같은 실제 행동을 수행하는지
- tool call 전 schema 검증, 권한 범위, quota, 승인 단계, 대상 리소스 검증
- RAG 문서와 chunk별 ACL, tenant 경계, 다른 사용자 데이터 노출 가능성
- 모델이 제안한 URL fetch, shell command, SQL, HTML, API call을 서버가 다시 검증하는지
- 비용 quota, rate limit, abuse logging

출력:
위험도, 공격 시나리오, 방어 확인 근거, 사람 승인 필요 지점을 표로 정리해줘.

21 · 공급망

공급망, 패키지, CI/CD

2025 Top 10에서 공급망 실패가 별도 항목으로 올라온 이유는 명확합니다. 지금의 앱은 직접 쓴 코드보다 가져온 코드가 많습니다. 패키지, Docker image, GitHub Actions, AI 모델, 플러그인, 브라우저 확장, CDN script, 분석 도구가 모두 공급망입니다.

  1. 1새 패키지는 이름 오타, 소유자, 최근 배포, 다운로드 수, issue, license, postinstall script를 확인한다.
  2. 2lockfile을 커밋하고 production build는 lockfile 기준으로 설치한다.
  3. 3`npm install` 대신 CI에서는 `npm ci`를 쓰고, 필요 없는 lifecycle script는 `--ignore-scripts` 또는 별도 승인 절차를 검토한다.
  4. 4타이포스쿼팅, dependency confusion, maintainer takeover, 갑작스러운 major 변경, 의심스러운 obfuscation을 새 패키지 도입 시 확인한다.
  5. 5GitHub Actions permissions는 최소화하고 외부 PR에서 secret 접근이 안 되게 한다.
  6. 6dependency audit, secret scan, SBOM, license scan을 CI에 넣는다.
  7. 7Dependabot, npm audit, OSV/Snyk 같은 SCA 결과는 “있음”으로 끝내지 말고 exploitability와 배포 영향 기준으로 SLA를 둔다.
  8. 8서드파티 스크립트는 수집 데이터, 쿠키, 개인정보 전송, CSP, SRI 적용 가능성을 확인한다.

Copy Prompt

공급망·CI/CD 감사 프롬프트

소프트웨어 공급망과 CI/CD를 감사해줘.

확인할 것:
- package.json, lockfile, postinstall script, 의심스러운 dependency 이름
- npm ci 사용, lockfile drift, lifecycle script 실행 정책, --ignore-scripts 가능성
- npm audit, Dependabot, OSV/Snyk 같은 dependency scan 결과와 수정 SLA
- typosquatting, dependency confusion, maintainer takeover, obfuscation, 최근 owner 변경
- GitHub Actions permissions, pull_request_target, secret 접근 범위
- CI 로그에 secret 출력 가능성
- Docker image에 .env 또는 key가 레이어로 남는지
- SBOM, provenance/signature, release artifact, 외부 CDN script, 분석 SDK의 데이터 수집 범위

Critical/High 우선으로 수정 방향을 제안해줘.

22 · 인프라

클라우드, VPS, 컨테이너, DNS

웹앱 보안은 코드만이 아닙니다. Cloudflare, Supabase, Turso, VPS, Docker, GitHub Actions, DNS, 도메인, TLS, 백업, billing 계정까지 서비스의 일부입니다. 특히 직접 VPS를 운영한다면 패치, 방화벽, SSH, DB 포트, 백업 복구를 “플랫폼이 해주겠지”라고 생각하면 안 됩니다.

클라우드와 네트워크

  • 클라우드 보안은 shared responsibility다. 제공자가 지켜주는 영역과 내가 설정해야 하는 영역을 나눈다.
  • AWS, Cloudflare, Supabase, VPS 계정은 MFA와 최소 권한 IAM을 적용한다.
  • VPS Postgres 5432, Redis, admin panel을 인터넷에 직접 열지 않는다.
  • SSRF 방어를 위해 metadata IP, private IP, localhost, link-local 주소 접근을 차단한다.
  • 사용하지 않는 subdomain, DNS record, bucket, preview deployment를 정리해 subdomain takeover를 막는다.
  • 서버가 외부 URL을 가져오는 기능은 `http/https` allowlist, redirect 재검증, DNS rebinding 방어, private IP/metadata IP 차단을 적용한다.
  • SSRF 방어는 코드 allowlist와 네트워크 egress 제한을 같이 둔다. 코드 검증이 뚫려도 내부망 접근이 막혀야 한다.

컨테이너와 백업

  • Docker image에는 secret, `.env`, SSH key, 빌드 캐시가 레이어로 남지 않게 한다.
  • 컨테이너는 rootless, read-only filesystem, 최소 base image, image scan을 검토한다.
  • 백업은 암호화하고 복구 테스트를 한다. 백업이 있다는 말은 복구가 된다는 뜻이 아니다.
  • RTO/RPO, 비상 연락망, 키 회전, 점검 순서를 사고 대응 문서에 둔다.
  • 도메인 만료일, TLS 인증서 만료일, billing 실패 알림을 모니터링한다.

원본 서버 IP와 비용 한도도 보안 설정이다

공격자가 앱 코드를 뚫지 못해도 원본 IP를 때리거나 AI API, 이미지 생성, 이메일 발송, DB write를 반복 호출하면 서비스가 멈추거나 청구서가 터질 수 있습니다. Cloudflare/WAF, 원본 방화벽, 사용량 한도, 예산 알림은 코드 보안과 같은 레벨의 운영 보안입니다.

Copy Prompt

클라우드·VPS·DNS 감사 프롬프트

클라우드, VPS, 컨테이너, DNS, 백업 구성을 감사해줘.

확인할 것:
- Cloudflare/Supabase/Turso/GitHub/VPS 계정 MFA와 최소 권한
- VPS SSH, Postgres 5432, Redis, admin panel의 인터넷 노출
- 방화벽, private network, Cloudflare Tunnel/ZTNA, SSH key 관리
- Docker image에 .env, SSH key, build cache, secret layer가 남는지
- DNS record, 사용하지 않는 subdomain, preview deployment, subdomain takeover
- TLS 인증서/도메인 만료, billing 실패 알림
- 백업 암호화, 복구 테스트, RTO/RPO, 랜섬웨어 대비

출력:
| 영역 | 현재 상태 | 위험 | 확인 명령/화면 | 우선순위 | 조치 |

23 · 남용 방지

결제, 과금, 봇, 비즈니스 로직

안전하지 않은 설계는 SQL injection처럼 화려하게 보이지 않습니다. 정상 기능을 정상 요청으로 악용합니다. 무료 체험을 무한 생성하거나, 쿠폰을 동시에 여러 번 쓰거나, 결제 금액을 프런트에서 바꾸거나, AI API를 반복 호출해 비용을 터뜨리는 식입니다.

결제와 과금

  • 결제 금액, 상품 가격, 할인율, 포인트, 쿠폰, plan은 프런트 값이 아니라 서버 DB 기준으로 다시 계산한다.
  • PG/Stripe/국내 결제 웹훅은 서명을 검증하고 idempotency key 또는 event id로 중복 처리를 막는다.
  • 웹훅 서명은 raw body 기준으로 검증하고 timestamp tolerance, replay 방지, event type allowlist를 적용한다.
  • 결제 성공 페이지, 클라이언트 callback, 프런트 상태값을 paid 근거로 쓰지 말고 provider API와 서버 주문 상태를 대조한다.
  • 수량, 가격, 할인율, 포인트는 정수/Decimal, min/max, 통화 단위, 반올림 규칙을 서버에서 검증하고 음수/0/초과값을 테스트한다.
  • 환불, 취소, 실패, 부분 결제, 중복 결제, chargeback도 정상 결제만큼 서명 검증과 상태 전이를 점검한다.
  • 무료 체험, 쿠폰, 추천 보상, 포인트 적립은 race condition과 반복 요청을 테스트한다.
  • AI API, 이미지 생성, 이메일, SMS, 크롤링, 파일 변환에는 사용자별/조직별 quota와 rate limit을 둔다.
  • 사용량 폭증 알림과 결제 한도 알림을 provider 대시보드에서 켠다.

봇과 비즈니스 로직

  • 티켓 구매, 댓글, 가입, 초대 링크, 투표, 다운로드 같은 흐름은 자동화 남용을 가정한다.
  • rate limit은 IP만이 아니라 계정, 기기, 세션, 결제수단, 조직 단위도 고려한다.
  • 동일 요청 두 번 보내기, 순서 바꾸기, 중간 단계 건너뛰기, 음수/0/큰 값 입력을 테스트한다.
  • GraphQL은 depth, complexity, batching, introspection 노출을 점검한다.
  • WebSocket은 연결 시 인증뿐 아니라 메시지마다 권한, Origin, token 만료를 고려한다.

Copy Prompt

결제·과금·봇 남용 감사 프롬프트

결제, 과금, 봇, 비즈니스 로직 남용을 감사해줘.

확인할 것:
- 결제 금액, 상품 가격, 쿠폰, 포인트, plan을 서버 DB 기준으로 재계산하는지
- PG/Stripe/국내 결제 웹훅 raw body 서명 검증, timestamp tolerance, replay 방지, event type allowlist
- idempotency key, event id, 주문 상태 전이, provider API 재조회, paid 상태 서버 확정
- 수량/가격/할인/포인트의 음수, 0, 초과값, 통화 단위, Decimal/반올림 검증
- 환불, 취소, 실패, 부분 결제, chargeback 이벤트 처리
- 무료 체험, 추천 보상, 쿠폰, 포인트의 race condition
- AI API, 이미지 생성, 이메일, SMS, 파일 변환의 quota/rate limit
- 이메일/SMS 인증 코드 brute force, resend cooldown, 발송 abuse, 광고성 메시지 동의/수신거부
- 봇 가입, 댓글, 다운로드, 초대 링크, 투표, 크롤링 남용
- 같은 요청 반복, 순서 바꾸기, 중간 단계 건너뛰기, 음수/큰 값 입력

출력:
공격 시나리오 10개와 각 방어 방법, 수동 테스트 방법을 표로 정리해줘.

24 · 트래픽 방어

DDoS, 악성 트래픽, 비용 폭탄 방어

보안은 데이터 유출만 막는 일이 아닙니다. DDoS, 봇, 크롤러, 과도한 API 호출은 서비스를 멈추고 비용을 태웁니다. 1인 서비스도 부터, IP 스트레서, 자동화 봇, 랜섬 DDoS의 표적이 될 수 있으므로 Edge, 원본 서버, 애플리케이션, 결제 한도를 함께 설계해야 합니다.

Edge와 원본 서버 보호

  • 도메인은 Cloudflare 같은 CDN/WAF 뒤에 두고 원본 서버 IP는 직접 노출되지 않게 한다.
  • 원본 방화벽은 CDN IP 대역, private network, tunnel 등 필요한 경로만 허용한다.
  • DNS record, 과거 서브도메인, MX/SPF, preview deployment, 로그와 에러 페이지에서 원본 IP가 새는지 확인한다.
  • Under Attack Mode, Managed Rules, Bot Fight, rate limiting, challenge rule을 언제 켤지 운영 절차에 적는다.
  • 정적 자산은 cache를 활용하고, 동적 API는 인증/인가와 별개로 요청량 제한을 둔다.

비용 폭탄 방어

  • AI API, 이미지 생성, 이메일, SMS, 크롤링, 파일 변환, DB write에는 사용자/조직/일 단위 quota를 둔다.
  • AWS Budgets, Google Cloud Budget, OpenAI Usage Limits, Anthropic workspace limit, Cloudflare 알림을 켠다.
  • 자동결제와 자동 리로드는 필요한 경우에만 켜고, 개인 프로젝트는 선불 크레딧, 가상카드, 체크카드로 물리적 상한을 만든다.
  • 갑작스러운 429, 5xx, 특정 endpoint 호출 급증, AI token 사용량 급증, 트래픽 전송량 급증에 경보를 둔다.
  • 무료 체험, 익명 기능, 공개 API는 계정 단위뿐 아니라 IP, device, 세션, 결제수단, user agent 단위 남용을 같이 본다.

공격 중 대응

  • 첫 1시간에는 트래픽 차단, CDN 방어 모드, 원본 firewall, provider 지원 요청, 로그 보존을 동시에 진행한다.
  • 한국 운영자는 KISA 118, 호스팅사 보안팀, 경찰청 사이버수사대 신고 경로를 미리 적어둔다.
  • 랜섬 DDoS 협박은 결제하지 않고 증거를 보존한다. 결제는 재공격과 추가 협박을 부를 수 있다.
  • 공격이 SQLi나 계정 탈취 시도를 가리는 시선 분산일 수 있으므로 로그인 실패, 관리자 접근, DB 오류도 함께 본다.
  • 사후에는 공격 시점, 벡터, 트래픽 규모, 비용 영향, 적용한 룰, 누락된 경보를 post-mortem으로 남긴다.

Copy Prompt

DDoS·악성 트래픽·비용 폭탄 감사 프롬프트

DDoS, 악성 트래픽, 봇, 비용 폭탄 방어 상태를 감사해줘.

확인할 것:
- Cloudflare/CDN/WAF 사용 여부와 원본 서버 IP 직접 노출 여부
- 원본 방화벽이 CDN IP, private network, tunnel 등 필요한 경로만 허용하는지
- Under Attack Mode, WAF Managed Rules, Bot Fight, challenge rule, rate limiting 운영 기준
- AI API, 이미지 생성, 이메일, SMS, 크롤링, 파일 변환, DB write quota
- AWS/GCP/OpenAI/Anthropic/Cloudflare/VPS 비용 알림과 자동결제/자동 리로드 상태
- 403/404/429/5xx 급증, 트래픽 전송량, token 사용량, endpoint 호출량 경보
- 공격 중 1시간 대응 순서, KISA 118/호스팅사/경찰 신고 경로, 로그 보존

출력:
| 공격/남용 시나리오 | 현재 방어 | 누락 | 비용 영향 | 즉시 조치 | 장기 조치 |

공격 중에는 성능 개선보다 필터링이 먼저다

DDoS는 “트래픽이 많으니 서버를 키우자”가 아니라 “악성 요청을 최대한 앞단에서 버리자”로 대응해야 합니다. CDN/Anycast, WAF, origin IP 격리, rate limit, 로그 보존, KISA 118 신고 절차는 DDoS·악성 트래픽 공격 방어 가이드에서 세부 운영 흐름까지 확인할 수 있습니다.

25 · 운영

로그, 경보, 사고 대응

보안은 막는 것만이 아닙니다. 뚫렸을 때 알아야 하고, 알았을 때 줄여야 하고, 줄인 뒤 설명할 수 있어야 합니다. 로그가 없으면 침해 범위를 말할 수 없고, 로그에 개인정보가 많으면 로그 자체가 또 다른 유출 데이터가 됩니다.

남길 것

로그인 실패, 권한 거부, 관리자 변경, 대량 export, 결제 웹훅, 비밀번호 재설정, API 호출 급증, rate limit hit.

남기지 말 것

비밀번호, 토큰, Authorization 헤더, reset token, 카드번호, 주민번호, 이메일 전체, 원문 AI 대화 전체.

경보

403/404 급증, 429 급증, 에러율 급증, 특정 IP 과다 요청, 비용 스파이크, 관리자 로그인 실패, 새 관리자 생성.

사고 대응

차단, 증거 보존, 영향 범위 산정, 키 교체, 취약점 보완, 통지와 신고, 공지, 재발 방지 문서화.

Copy Prompt

로그·경보·사고 대응 감사 프롬프트

로그, 경보, 관리자 감사 로그, 사고 대응 준비 상태를 감사해줘.

확인할 것:
- 로그인 실패, 권한 거부, 관리자 변경, 대량 export, 결제 웹훅, 비밀번호 재설정 로그
- 비밀번호, 토큰, Authorization 헤더, reset token, 카드번호, 이메일 전체가 로그에 찍히는지
- 403/404/429 급증, 에러율 급증, 비용 스파이크, 관리자 로그인 실패, 새 관리자 생성 경보
- OTP/MFA/reset 실패 급증, 인증 코드 재전송 급증, 이메일/SMS 발송 실패와 complaint 급증
- 로그 변조 방지, 관리자 감사 로그 별도 저장, 보존 기간
- 사고 발생 시 차단, 증거 보존, 영향 범위 산정, 키 교체, 통지/신고, 재발 방지 문서화

출력:
탐지 가능한 사고 / 현재 로그로 판단 불가한 사고 / 바로 추가할 경보를 나눠줘.

Part 05 · Audit Pack

읽은 내용을 배포 전 점검과 복사 프롬프트로 고정한다

보안은 읽고 끝나면 사라집니다. 체크리스트, 수동 테스트, 감사 보고서, AI 프롬프트, 회귀 테스트로 반복 가능한 운영 루틴을 만듭니다.

26 · 운영 체계

Secure SDLC와 운영 체계

보안을 한 번 검사하고 끝내면 다음 기능에서 다시 무너집니다. 바이브 코딩은 기능 추가 속도가 빠르기 때문에 더더욱 “매번 확인하는 구조”가 필요합니다. NIST SSDF와 OWASP SAMM은 보안을 개발 수명주기에 넣는 기준으로 볼 수 있습니다.

준비

  • 자산 목록, 데이터 분류, 신뢰 경계, 외부 연동, 관리자 권한, 규제 요구사항을 적는다.
  • 기능 요구사항 옆에 보안 요구사항을 붙인다. 예: “메모 생성” 옆에 “소유자만 읽기/수정/삭제”.
  • L1/L2/L3 위험 레벨을 정한다. 개인정보, 결제, 인증 코어, 관리자 기능은 L2 이상으로 본다.

설계

  • DFD를 텍스트로라도 작성한다. browser, API, DB, storage, queue, AI provider, admin을 나눈다.
  • STRIDE로 spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege를 훑는다.
  • 권한 행렬을 만든다. actor, resource, action, condition, expected result를 표로 적는다.

구현

  • PR 템플릿에 인증, 인가, 입력 검증, 로그 마스킹, secret, migration, rate limit 체크 항목을 넣는다.
  • AI가 만든 코드는 기능 PR과 보안 리뷰 PR을 분리해서 본다.
  • 새 패키지와 새 외부 API를 도입하면 공급망과 개인정보 전송 여부를 같이 검토한다.

검증과 운영

  • SAST, SCA, secret scan, DAST, 수동 악용 테스트를 위험도에 맞춰 적용한다.
  • 발견한 취약점은 수정 후 재현 테스트를 회귀 테스트로 고정한다. 같은 실수가 다음 배포에서 되살아나면 안 된다.
  • 배포 전 체크리스트와 배포 후 로그 확인 시간을 정한다.
  • 분기별로 30분짜리 tabletop 훈련을 해본다. “키 유출”, “관리자 계정 탈취”, “결제 웹훅 위조”, “DDoS 비용 폭탄” 시나리오를 말로라도 끝까지 굴린다.
  • 사고 대응 플레이북과 보안 제보 채널, security.txt, 비공개 취약점 처리 절차를 준비한다.

작은 팀의 현실적인 운영선

모든 표준을 한 번에 적용하지 않아도 됩니다. 대신 새 기능마다 데이터 흐름, 권한, 입력 검증, secret, 로그, rate limit, 사고 시 영향 범위를 PR 또는 배포 체크리스트에 남기세요. 기록이 쌓이면 보안은 감이 아니라 운영 자산이 됩니다.

Copy Prompt

Secure SDLC 적용 프롬프트

이 프로젝트에 현실적인 Secure SDLC 운영 체계를 설계해줘.

요구:
- 1인 개발자 또는 작은 팀 기준으로 과하지 않게 설계
- PR 체크리스트, 배포 전 체크리스트, 배포 후 로그 확인, 월간 보안 점검으로 나누기
- 데이터 흐름, 권한, 입력 검증, secret, 로그, rate limit, 사고 대응 항목 포함
- AI가 기능을 만든 뒤 별도 보안 감사 단계를 넣기
- Critical/High 발견 시 배포 중지 기준을 정하기
- 취약점 수정 후 같은 시나리오를 회귀 테스트로 고정하기
- 분기별 침해 시뮬레이션 또는 tabletop 훈련을 30분짜리로 설계하기

출력:
1. 오늘 추가할 PR 체크리스트
2. 배포 전 체크리스트
3. 월간 점검표
4. 사고 발생 시 30분 대응 순서
5. 회귀 테스트로 고정할 보안 케이스
6. AI agent에게 넣을 보안 룰

27 · 빠른 점검

초보자 30분 점검

처음부터 ASVS 전체를 다 할 수 없다면 아래부터 하세요. 이 정도만 해도 “AI가 기능만 만들고 보안은 빠뜨린” 가장 흔한 사고를 많이 줄일 수 있습니다.

공개 전 30분

  • 로그인 없이 `/api`, `/admin`, `/dashboard`, `/settings`를 직접 열어 본다.
  • 다른 사용자 ID, 주문 ID, 메모 ID, 파일 ID로 바꿔 호출해 401, 403, 404가 나오는지 확인한다.
  • 브라우저 개발자 도구 Network 응답에 이메일, 토큰, 내부 ID, role, 결제 정보가 과하게 내려오지 않는지 본다.
  • `.env`, service key, DB URL, JWT secret, Cloudflare token, Turso token이 Git 히스토리와 배포 로그에 없는지 검색한다.
  • 관리자 계정, 이메일 계정, GitHub, Cloudflare, Supabase, VPS 계정에 2FA를 켠다.

개인정보 최소화

  • 정말 필요한 정보만 수집한다. 이메일이 필요 없으면 받지 않는다.
  • 개인정보처리방침, 수집 항목, 보존 기간, 삭제 방법을 서비스 화면에서 확인 가능하게 둔다.
  • 로그에 이메일 전체, 전화번호, Authorization 헤더, reset token, 결제 정보를 남기지 않는다.
  • 테스트 DB와 production DB를 분리하고 실제 유저 데이터를 테스트용으로 복사하지 않는다.
  • 삭제 요청이 들어오면 DB, 파일, 로그, 백업에서 어디까지 삭제할지 문서화한다.

AI 코딩 도구

  • AI에게 production 데이터, 유저 이메일 목록, 결제 내역, 실제 API 키를 붙여넣지 않는다.
  • AI가 추천한 패키지는 설치 전 실제 존재 여부, 다운로드 수, 관리자 변경, license, postinstall script를 확인한다.
  • AI에게 “이 기능을 악용할 방법을 찾아라”, “인증 없이 접근 가능한 엔드포인트를 찾아라”라고 별도 검토를 시킨다.
  • 에이전트에게 전체 DB, 전체 파일시스템, 배포 권한을 한 번에 주지 않는다.
  • MCP 서버, 자동 배포, 브라우저 자동화는 최소 권한과 승인 단계를 둔다.

Copy Prompt

초보자 30분 점검 프롬프트

내 프로젝트를 초보자도 따라 할 수 있는 30분 보안 점검표로 바꿔줘.

조건:
- 브라우저, DevTools, 터미널 기본 명령만 사용
- 실제 공격 코드는 위험하지 않은 개념 수준으로 제한
- 계정 2개를 만들어 IDOR, 권한, 로그아웃 후 접근을 확인
- secret, RLS, API, 파일 업로드, 로그 개인정보, 관리자 페이지를 포함

출력:
| 순서 | 할 일 | 어디서 확인 | 정상 결과 | 위험하면 보이는 증상 | 다음 조치 |

28 · 심화 점검

전문가용 심화 점검

유저가 늘거나 결제, 팀 기능, 파일 업로드, AI 에이전트, 관리자 페이지, 개인정보 처리량이 커진다면 점검 깊이를 올려야 합니다.

설계와 요구사항

  • 기능별 데이터 흐름도와 권한 행렬을 만든다. actor, resource, action, condition을 표로 적는다.
  • OWASP ASVS를 기준으로 인증, 세션, 접근 통제, 입력 검증, 암호화, 오류 처리, API 요구사항을 체크한다.
  • NIST SSDF 방식으로 보안 요구사항, 설계 결정, 위험, 검증 결과를 개발 수명주기에 남긴다.
  • CISA Secure by Design 관점으로 기본 보안값, 고객 보안 결과, 투명한 취약점 처리, 리더십 책임을 문서화한다.
  • 데이터 분류표를 만든다. 공개 데이터, 내부 데이터, 개인정보, 민감정보, 결제 정보, 비밀키를 분리한다.

구현 검증

  • SAST, dependency audit, secret scan, license scan을 CI에 넣고 실패 기준을 정한다.
  • DAST 또는 OWASP ZAP으로 공개 경로, API, 인증 우회, 보안 헤더, CORS, XSS, redirect를 점검한다.
  • API에는 객체 수준 권한, 속성 수준 권한, 함수 수준 권한, rate limit, pagination limit, body size limit을 둔다.
  • DB는 least privilege 계정, migration 계정, app 계정, read-only 계정을 분리한다.
  • PostgreSQL RLS를 쓴다면 `ENABLE ROW LEVEL SECURITY`, policy, `FORCE ROW LEVEL SECURITY`, owner bypass, `BYPASSRLS` 역할을 함께 확인한다.

관리자 페이지

  • 관리자 라우트는 일반 사용자 라우트와 다른 미들웨어 체인, 더 짧은 세션, MFA, audit log를 적용한다.
  • 관리자 경로 숨김, robots 차단, IP allowlist만으로 보안이 완성된다고 보지 않는다.
  • 관리자 mutation에는 CSRF token, Origin/Referer 검증, role 검증, resource ownership 검증, 변경 전후 감사 로그를 둔다.
  • super_admin 수를 최소화하고 콘텐츠, 사용자, 시스템, 재무 관리자 역할을 분리한다.
  • 대량 사용자 조회, export, 권한 변경, 새 관리자 생성, 비정상 시간대 로그인에 경보를 둔다.

고급 공격면

  • OAuth/OIDC/SAML은 issuer, audience, redirect URI allowlist, state, nonce, token validation을 명확히 검증한다.
  • SSRF 가능 URL 입력은 DNS rebinding, redirect, private IP, metadata IP, IPv6, encoded URL을 테스트한다.
  • GraphQL은 introspection, depth, complexity, batching, field-level authorization을 점검한다.
  • WebSocket은 연결 시점뿐 아니라 메시지 단위 인증, 인가, Origin, token 만료, rate limit을 점검한다.
  • 캐시, 큐, 비동기 작업, 이메일 발송 작업에도 tenant_id와 권한 경계를 유지한다.

운영과 사고 대응

  • 로그 마스킹, 감사 로그, 관리자 작업 로그, 대량 export 로그, 권한 변경 로그를 분리한다.
  • 로그인 실패 급증, 403/404 급증, 429 급증, 비용 스파이크, AI API 사용량 스파이크에 경보를 둔다.
  • 백업 암호화, 복구 테스트, RTO/RPO, 키 회전, 비상 연락망, 침해 공지 초안을 준비한다.
  • 유출 판단 시 어떤 데이터가 언제부터 얼마나 누구에게 노출됐는지 재구성 가능한 로그를 남긴다.
  • 외부 취약점 제보 채널과 보안 이슈 비공개 처리 절차를 마련한다.

Copy Prompt

전문가 심화 감사 프롬프트

내 프로젝트를 전문가용 심화 보안 감사 기준으로 점검해줘.

기준:
- OWASP Top 10 2025, API Security 2023, LLM Top 10 2025, ASVS, NIST SSDF 관점
- source-sink 추적, 권한 행렬, 데이터 흐름도, 신뢰 경계, STRIDE 포함
- 인증/인가/RLS, DB role, 관리자 페이지, OAuth/OIDC, WebSocket, GraphQL, SSRF, 파일, 결제, CI/CD 포함
- 결과는 취약 확인 / 방어 확인 / 판단 불가 / 해당 없음으로만 분류

출력:
Critical/High 우선 상세 보고서와 수정 후 재감사 테스트 목록을 만들어줘.

29 · 수동 테스트

수동 10분 보안 테스트

자동 도구가 없어도 할 수 있는 테스트가 많습니다. 오히려 바이브 코딩 앱의 큰 사고는 브라우저 개발자 도구, URL 숫자 바꾸기, 로그아웃 상태 접근, body 필드 추가 같은 낮은 난이도 테스트에서 바로 드러납니다.

계정과 권한

  • 로그인하지 않고 `/api`, `/admin`, `/dashboard`, `/settings`를 연다.
  • 일반 사용자로 관리자 URL에 직접 접근한다.
  • 사용자 A로 로그인한 뒤 URL의 userId, memoId, orderId, fileId를 사용자 B의 값으로 바꾼다.
  • Authorization 헤더를 제거하고 같은 API를 호출한다.
  • 로그아웃 뒤 뒤로가기와 이전 URL 직접 접근을 테스트한다.

입력과 상태 변경

  • 요청 body에 `role`, `isAdmin`, `plan`, `price`, `balance`, `owner_id`를 추가한다.
  • 검색창, 제목, 메모, 댓글에 XSS와 SQL injection 기본 payload를 넣어본다.
  • 비밀번호 재설정 링크를 두 번 사용한다.
  • 동일 결제/쿠폰/포인트 요청을 빠르게 두 번 보낸다.
  • 큰 파일, 확장자를 속인 파일, SVG 파일, `../` 경로가 섞인 다운로드 요청을 테스트한다.

노출과 운영

  • Network 응답에 화면에서 안 쓰는 민감 필드가 있는지 본다.
  • `/.git`, `/debug`, `/health`, `/status`, `/robots.txt`, `/sitemap.xml`, source map을 열어본다.
  • 파일 URL을 로그아웃 상태와 다른 계정으로 열어본다.
  • 로그에 비밀번호, token, Authorization header, 이메일 전체가 찍히는지 본다.
  • AI API와 결제 provider 사용량 알림이 켜져 있는지 확인한다.

Copy Prompt

수동 테스트 실행 프롬프트

내가 직접 브라우저와 DevTools로 10분 보안 테스트를 할 수 있게 순서표를 만들어줘.

포함할 테스트:
- 로그인 없음 / 일반 사용자 / 다른 사용자 / 관리자 계정으로 각각 접근
- URL ID 바꾸기, Authorization 제거, logout 후 직접 URL 접근
- body에 role/isAdmin/plan/price/balance/owner_id 추가
- XSS/SQLi 기본 payload, 파일 업로드, path traversal
- 로그인/OTP/reset 코드 반복 실패, next/returnTo open redirect, 로그아웃 후 localStorage/IndexedDB/Service Worker cache 확인
- iframe embed와 postMessage origin 검증, 민감 API Cache-Control 확인
- 결제/쿠폰/포인트 동일 요청 두 번 보내기
- Network 응답 민감 필드, public 파일 URL, /debug /health /.git /source map 확인

각 테스트마다 기대 결과, 실패 시 위험도, 캡처해야 할 증거를 써줘.

30 · 복사팩

복사용 감사 스크립트와 프롬프트

아래 블록은 그대로 복사해서 Codex, Cursor, Claude, ChatGPT 등에 붙여넣는 용도입니다. 실제 키, 실제 사용자 이메일, 결제 내역 원문은 넣지 말고 마스킹된 로그와 코드 위치만 전달하세요.

Copy Prompt

전체 보안 감사 마스터 프롬프트

내 프로젝트를 보안 감사해줘.

목표:
- "안전해 보임"이 아니라 실제로 어떻게 뚫릴 수 있는지 찾고, 막힌다면 근거로 증명한다.
- 결과는 취약 확인 / 방어 확인 / 판단 불가 / 해당 없음 네 가지 상태로만 분류한다.
- 실제 secret, token, 개인정보가 발견되면 원문을 출력하지 말고 앞뒤 일부만 마스킹한다.

프로젝트 정보:
- 서비스 설명: [서비스 목적 작성]
- 기술 스택: [Next.js/Astro/Cloudflare/Supabase/Turso/D1/VPS Postgres 등]
- 인증 방식: [세션/JWT/OAuth/Supabase Auth/없음]
- 저장소: [DB, Storage, R2, S3, 파일시스템 등]
- 개인정보: [이메일, 닉네임, IP, 로그, 결제, AI 대화, 파일 등]
- 결제/AI/파일 업로드/관리자 기능 여부: [작성]

감사 범위:
1. 인증 없는 공개 API와 관리자 route
2. IDOR/BOLA, 권한 검사 누락, mass assignment
3. Supabase RLS, Postgres RLS, D1/Turso/VPS DB 접근 경계
4. secret, env, service key, Git 히스토리, 로그 노출
5. JWT, session, refresh token, logout invalidation, MFA, session fixation, cookie attributes, JWT alg confusion, timing-safe compare, CSPRNG
6. 자체 인증 위험: 비밀번호 KDF, JWT 저장, OAuth state/PKCE, reset token, 계정 열거, credential stuffing, brute force, OTP/MFA rate limit
7. 관리자 페이지: 별도 guard, MFA, 짧은 세션, CSRF, RBAC/ABAC, IP/Zero Trust, audit log
8. SQL/NoSQL/command/template/prompt injection
9. XSS, Markdown/HTML/LLM output rendering, CSP
10. CORS wildcard/credentials, CSRF token/Origin/Fetch Metadata, SSRF, open redirect, OAuth returnTo/next, WebSocket, GraphQL
11. 파일 업로드/다운로드, public bucket, path traversal, magic byte, 실행 권한, EXIF, zip bomb
12. 결제 웹훅 raw body 서명, replay 방지, 금액 서버 검증, 상태 전이, 쿠폰/포인트/race condition
13. API key scope, 키 회전, secret manager, OIDC keyless, 자동결제/사용량 한도
14. DDoS/악성 트래픽: CDN/WAF, origin IP 격리, rate limit, bot 방어, 비용 폭탄 경보
15. AI agent 권한, prompt injection, RAG 데이터 노출, 비용 폭탄, tool approval, RAG ACL
16. 공급망, lockfile, npm audit, package typo, dependency confusion, postinstall, CI/CD secret
17. 캐시/클라이언트 잔존: Cache-Control, CDN cache key, Service Worker, localStorage/IndexedDB, bfcache
18. 이메일/SMS/알림: SPF/DKIM/DMARC, 인증 코드 brute force, 발송 abuse, 광고성 메시지 동의
19. iframe/embed/postMessage: sandbox, targetOrigin, origin/schema 검증, frame-ancestors
20. 국내 운영 의무: 만 14세 미만, 주민등록번호 수집 제한, 광고성 정보와 야간 전송
21. 로그 마스킹, 보안 경보, 관리자 감사 로그, 사고 대응

출력 형식:
| 번호 | 상태 | 위험도 | 항목 | 위치 | 공격 시나리오 | 영향 | 근거 | 수정 방향 | 검증 방법 |

규칙:
- 추정이면 추정이라고 표시한다.
- 코드로 확인할 수 없으면 판단 불가로 둔다.
- Critical/High를 먼저 정렬한다.
- 마지막에 "오늘 바로 할 10개", "이번 주 할 10개", "전문가 검토 필요 항목"을 따로 요약한다.

Copy Prompt

감사 스크립트 작성 프롬프트

이 저장소에 맞는 로컬 보안 감사 스크립트를 작성해줘.

요구사항:
- Node.js 단일 파일 scripts/security-audit.mjs 로 작성한다.
- 외부 네트워크 호출 없이 로컬 파일만 검사한다.
- 실제 secret 값은 절대 출력하지 말고 마스킹한다.
- 검사 결과는 콘솔 표와 JSON 리포트 security-audit-report.json 으로 저장한다.
- 파괴적 작업, 자동 수정, 파일 삭제, git reset은 하지 않는다.

검사 항목:
1. .env, .env.local, service_role, private key, JWT secret, DB URL 패턴
2. NEXT_PUBLIC_에 secret으로 보이는 값이 붙었는지
3. src/app, src/pages, functions, workers, api route 목록
4. 인증 미들웨어 없이 민감해 보이는 route: admin, dashboard, settings, export, billing, webhook, upload
5. dangerouslySetInnerHTML, innerHTML, eval, Function, dynamic import, child_process 사용
6. raw SQL 문자열 결합, order by/column whitelist 누락 가능성
7. CORS wildcard, credentials 조합, permissive headers
8. public 폴더의 .env, .map, test fixture, json dump, backup 파일
9. package.json scripts, postinstall, 의심스러운 dependency 이름
10. GitHub Actions permissions, secret echo, pull_request_target 사용
11. Supabase service role 사용 위치, RLS 관련 SQL/migration 존재 여부
12. Cloudflare D1/Turso token이 client bundle로 들어갈 가능성
13. 관리자 route/API, export, billing, role 변경 기능의 별도 guard와 audit log 흔적
14. 사용량 한도, rate limit, quota, budget alert, auto recharge 관련 설정 문서/코드 존재 여부
15. Cloudflare/WAF/origin IP 보호, 보안 헤더, bot 방어 설정 파일 또는 문서 존재 여부
16. JWT alg/issuer/audience 검증, cookie 옵션, logout invalidation, refresh token rotation 키워드
17. 결제 webhook raw body, signature verification, timestamp tolerance, idempotency, provider API 대조 코드
18. 업로드 magic byte, 확장자 allowlist, no-execute storage, 이미지 변환 sandbox, zip bomb 제한 코드
19. CORS credentials/wildcard, CSRF token, Origin/Referer, Sec-Fetch-* 검증 코드
20. 로그인/OTP/MFA/reset 요청 rate limit, lockout, CAPTCHA, resend cooldown 관련 코드
21. open redirect 위험 파라미터: next, returnTo, redirect, url, callbackUrl
22. Cache-Control no-store, CDN cache key, Service Worker cache, localStorage/IndexedDB 정리 코드
23. postMessage targetOrigin, iframe sandbox/allow, frame-ancestors 설정
24. SPF/DKIM/DMARC 문서, 광고성 메시지 수신동의/수신거부/야간 전송 처리 코드

출력:
- Critical/High/Medium/Low
- 파일 경로와 라인 번호
- 왜 위험한지
- 안전한 수정 방향
- 수동 확인이 필요한 항목

추가:
- npm script로 "security:audit": "node scripts/security-audit.mjs" 추가하는 패치도 제안해줘.
- 단, 먼저 코드만 보여주고 바로 수정하지 말고 내가 승인하면 적용해줘.

Copy Prompt

로컬 감사 스크립트 초안

// scripts/security-audit.mjs
// 목적: 로컬 저장소에서 secret, 위험 API, 브라우저 노출, 보안 냄새를 빠르게 찾는 초안.
// 주의: 이 스크립트는 보안 보증이 아니라 1차 탐색 도구다. 결과는 사람이 재검증해야 한다.

import fs from 'node:fs';
import path from 'node:path';

const root = process.cwd();
const ignoreDirs = new Set(['.git', 'node_modules', 'dist', '.next', '.astro', 'coverage', '.turbo']);
const findings = [];

const patterns = [
  ['CRITICAL', 'Potential private key', /-----BEGIN (RSA |EC |OPENSSH |)?PRIVATE KEY-----/i],
  ['CRITICAL', 'Service role or admin key keyword', /(service[_-]?role|SUPABASE_SERVICE_ROLE|admin[_-]?secret)/i],
  ['HIGH', 'JWT or session secret keyword', /(JWT_SECRET|SESSION_SECRET|AUTH_SECRET|NEXTAUTH_SECRET)/i],
  ['HIGH', 'Database URL keyword', /(DATABASE_URL|POSTGRES_URL|TURSO_AUTH_TOKEN|LIBSQL_AUTH_TOKEN)/i],
  ['HIGH', 'Cloud/API token keyword', /(CLOUDFLARE_API_TOKEN|OPENAI_API_KEY|ANTHROPIC_API_KEY|STRIPE_SECRET_KEY)/i],
  ['HIGH', 'Dangerous HTML sink', /(dangerouslySetInnerHTML|innerHTML\s*=)/],
  ['HIGH', 'Dynamic code execution', /\b(eval|Function)\s*\(/],
  ['HIGH', 'Shell execution', /(child_process|execSync|spawnSync|\bexec\s*\()/],
  ['MEDIUM', 'Wildcard CORS', /Access-Control-Allow-Origin['"]?\s*[:,]\s*['"]\*/i],
  ['MEDIUM', 'Credentialed CORS hint', /(Access-Control-Allow-Credentials|credentials\s*:\s*['"]include['"])/i],
  ['MEDIUM', 'Webhook route keyword', /\b(webhook|stripe|payment|checkout|billing)\b/i],
  ['MEDIUM', 'Possible external fetch or SSRF sink', /\b(fetch|axios|got|request)\s*\(/i],
  ['MEDIUM', 'Possible open redirect parameter', /\b(next|returnTo|redirect|callbackUrl|url)\b/i],
  ['MEDIUM', 'Possible upload handling', /\b(upload|multer|formData|multipart|sharp|imagemagick|magick|fileType|mime)\b/i],
  ['MEDIUM', 'Possible JWT decode without verify', /\b(jwt\.decode|decodeJwt)\b/i],
  ['MEDIUM', 'Cookie option keyword', /(httpOnly|sameSite|secure|__Host-)/i],
  ['MEDIUM', 'Predictable randomness hint', /\bMath\.random\s*\(/],
  ['MEDIUM', 'Client storage or service worker', /\b(localStorage|sessionStorage|indexedDB|serviceWorker|caches\.)\b/i],
  ['MEDIUM', 'Cache control keyword', /(Cache-Control|no-store|s-maxage|revalidate)/i],
  ['MEDIUM', 'postMessage or iframe keyword', /(postMessage|targetOrigin|<iframe|sandbox=|frame-ancestors)/i],
  ['MEDIUM', 'Package lifecycle script', /\b(preinstall|install|postinstall|prepare)\b/i],
  ['MEDIUM', 'Possible source map in public', /\.map$/i],
  ['MEDIUM', 'Debug route keyword', /\b(debug|internal|admin|dashboard|export|webhook|upload)\b/i],
];

function mask(line) {
  return line.replace(/[A-Za-z0-9_\-]{24,}/g, (value) => value.slice(0, 6) + '...' + value.slice(-4));
}

function walk(dir) {
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    if (ignoreDirs.has(entry.name)) continue;
    const full = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      walk(full);
      continue;
    }
    const rel = path.relative(root, full).replaceAll('\\', '/');
    if (!/\.(js|jsx|ts|tsx|mjs|cjs|json|yml|yaml|env|toml|sql|md|txt|astro)$/i.test(entry.name) && !entry.name.startsWith('.env')) continue;
    let text = '';
    try {
      text = fs.readFileSync(full, 'utf8');
    } catch {
      continue;
    }
    const lines = text.split(/\r?\n/);
    lines.forEach((line, index) => {
      for (const [severity, title, pattern] of patterns) {
        if (pattern.test(line)) {
          findings.push({ severity, title, file: rel, line: index + 1, sample: mask(line.trim()).slice(0, 220) });
        }
      }
    });
  }
}

walk(root);

const order = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
findings.sort((a, b) => order[a.severity] - order[b.severity] || a.file.localeCompare(b.file));

console.table(findings.slice(0, 200));
fs.writeFileSync(path.join(root, 'security-audit-report.json'), JSON.stringify({ generatedAt: new Date().toISOString(), count: findings.length, findings }, null, 2));
console.log(`security-audit-report.json written. findings=${findings.length}`);

Copy Prompt

AI 감사 보고서 작성 프롬프트

아래 보안 감사 결과를 보고서로 정리해줘.

입력:
- 보안 감사 스크립트 결과: [붙여넣기]
- 수동 테스트 결과: [붙여넣기]
- 빌드/타입체크/테스트 결과: [붙여넣기]

보고서 규칙:
- 상태는 취약 확인 / 방어 확인 / 판단 불가 / 해당 없음으로만 표기한다.
- 실제 secret, 이메일, 토큰, IP는 마스킹한다.
- Critical/High를 먼저 배치한다.
- 각 항목은 파일, 라인, API, DB table, 설정 위치처럼 재검증 가능한 근거를 포함한다.
- 판단 불가는 안전으로 쓰지 말고 필요한 추가 검증을 적는다.

보고서 형식:
1. 한눈에 보는 요약 표
2. Critical/High 상세
3. Medium/Low 상세
4. 개인정보/법 리스크
5. DB/RLS 리스크
6. 관리자 페이지 리스크
7. API 키/과금/결제 폭탄 리스크
8. DDoS/악성 트래픽/원본 서버 노출 리스크
9. AI/LLM/agent 리스크
10. 공급망/CI/CD 리스크
11. 로그/사고 대응 리스크
12. 오늘 바로 조치할 항목
13. 이번 주 조치할 항목
14. 재감사 체크리스트

31 · 프롬프트

AI에게 시킬 보안 프롬프트

AI는 보안 실수를 만들기도 하지만, 잘 시키면 1차 리뷰어로도 쓸 수 있습니다. 단, 실제 키와 production 데이터는 붙여넣지 말고 코드와 정책만 검토하게 해야 합니다.

Copy Prompt

악용 관점 리뷰

이 기능을 공격자 관점에서 악용할 수 있는 경로를 찾아줘. 인증 우회, IDOR, mass assignment, rate limit 부재, 비용 폭탄, 개인정보 노출을 우선순위로 보고 파일과 함수명을 근거로 정리해줘.

Copy Prompt

API 노출 점검

현재 프로젝트에서 인증 없이 호출 가능한 API route, server action, endpoint를 전부 찾아줘. 각 endpoint마다 필요한 인증, 필요한 인가, 현재 코드의 검증 위치, 우회 가능성을 표로 써줘.

Copy Prompt

RLS 정책 리뷰

Supabase 또는 Postgres 테이블별 RLS 활성화 여부, policy, app role, service role 사용 위치를 점검해줘. anon/authenticated/service role로 각각 어떤 row를 읽고 쓸 수 있는지 테스트 SQL도 제안해줘.

Copy Prompt

개인정보 최소화

이 서비스가 수집하는 개인정보, 로그, 쿠키, 파일, AI 대화, 결제 관련 데이터를 목록화하고 꼭 필요한 항목과 삭제 가능한 항목을 나눠줘. 보존 기간과 삭제 요청 처리 범위도 제안해줘.

Copy Prompt

source-sink 추적

HTTP parameter, header, cookie, body, 파일, 외부 API 응답, DB 데이터, queue 메시지, 환경변수를 source로 보고 SQL, HTML 출력, 파일 경로, redirect URL, 외부 HTTP 요청, OS command, 동적 코드 실행을 sink로 봐줘. source에서 sink까지 경로를 표로 추적하고 정제가 누락된 경로를 취약으로 표시해줘.

Copy Prompt

인증·세션 심화 감사

JWT, session cookie, refresh token, logout, password reset, MFA 흐름을 감사해줘. session fixation, JWT alg=none/HS256-RS256 혼동, kid 처리, cookie Domain/Path/SameSite/Secure/HttpOnly, refresh token rotation과 재사용 탐지, 로그아웃 후 서버측 무효화를 우선순위로 표로 정리해줘.

Copy Prompt

로그인 자동화 방어 감사

로그인, OTP, MFA 검증, 비밀번호 재설정, 이메일 인증, magic link 요청의 brute force와 credential stuffing 방어를 감사해줘. 계정/IP/기기/세션 단위 rate limit, 점진적 지연, 임시 lockout, CAPTCHA, 재전송 cooldown, 실패 로그와 알림을 표로 정리해줘.

Copy Prompt

CORS·CSRF·SSRF 감사

CORS wildcard/credentials, origin reflection, CSRF token/Origin/Referer/Fetch Metadata, SameSite cookie, SSRF 가능한 external fetch/redirect URL/file URL을 감사해줘. private IP, localhost, link-local, metadata IP, DNS rebinding, redirect 우회 테스트 케이스도 제안해줘.

Copy Prompt

Open Redirect 감사

로그인 후 이동, OAuth callback, 초대 링크, 이메일 링크, 결제 완료 redirect의 next/returnTo/redirect/url 파라미터를 감사해줘. 외부 도메인 이동, protocol-relative URL, encoded URL, 이중 redirect, allowlist 우회, 토큰 leakage 가능성을 찾아줘.

Copy Prompt

캐시와 클라이언트 잔존 감사

민감 API 응답의 Cache-Control, CDN cache key, Authorization/Cookie가 있는 응답의 public cache 가능성, Service Worker cache, localStorage/sessionStorage/IndexedDB, 로그아웃 후 저장소 정리, 뒤로가기/bfcache 민감 화면 잔존을 감사해줘.

Copy Prompt

이메일·알림 채널 감사

SPF/DKIM/DMARC, reset link/magic link/open redirect, 이메일/SMS 인증 코드 brute force, 발송량 quota, resend cooldown, bounce/complaint, 광고성 메시지 수신동의·수신거부·야간 전송 별도 동의 여부를 감사해줘.

Copy Prompt

파일 업로드 심화 감사

파일 업로드와 다운로드를 magic byte, MIME/확장자 allowlist, 이중 확장자, SVG/HTML/JS 차단, 업로드 저장소 실행 권한, 앱 쿠키 도메인과 파일 서빙 도메인 분리, 이미지/PDF 변환 sandbox, zip bomb, path traversal 기준으로 감사해줘.

Copy Prompt

iframe·postMessage 감사

외부 iframe, YouTube/embed, 광고, 위젯, 결제창, popup postMessage를 감사해줘. sandbox/allow 속성, targetOrigin "*", 수신 origin 검증, message schema 검증, frame-ancestors, 제3자 쿠키와 개인정보 처리방침 반영 여부를 확인해줘.

Copy Prompt

공급망 패키지 감사

package.json과 lockfile을 보고 typosquatting, dependency confusion, postinstall/lifecycle script, maintainer takeover, 최근 owner 변경, obfuscated 코드, npm audit/OSV/Snyk 결과, GitHub Actions secret 접근 범위를 감사해줘. 새 패키지를 유지/교체/제거로 분류해줘.

Copy Prompt

결제 웹훅 무결성 감사

결제/구독/포인트/쿠폰 흐름을 raw body webhook signature, timestamp tolerance, replay 방지, idempotency, provider API 재조회, 주문 상태 전이, 환불/취소/실패/chargeback, 음수 수량과 race condition 기준으로 감사해줘.

Copy Prompt

관리자 페이지 감사

관리자 라우트, 관리자 API, 관리자 세션, MFA, CSRF, audit log, export 기능, 권한 변경 기능을 감사해줘. 일반 사용자로 직접 접근 가능한 경로, role 검증 누락, 관리자 행위 로그 누락, 대량 조회 경보 부재를 우선순위로 찾아줘.

Copy Prompt

API 키와 결제 한도 감사

API key, service token, cloud credential, AI provider key가 어디에 저장되고 어떤 scope와 사용량 한도를 갖는지 감사해줘. 자동결제, 자동 리로드, 예산 알림, OIDC 키리스 인증, 키 회전 주기, 노출 시 폐기 절차까지 표로 정리해줘.

Copy Prompt

DDoS와 악성 트래픽 감사

Cloudflare/CDN/WAF, 원본 서버 IP 노출, rate limit, bot 방어, AI API/이메일/SMS quota, 트래픽·비용 경보, 공격 중 1시간 대응 절차를 감사해줘. 작은 개인 사이트 기준으로 오늘 바로 켤 설정과 장기 개선을 나눠줘.

Copy Prompt

판정 불가 분리

보안 감사 결과를 취약 확인, 방어 확인, 판단 불가, 해당 없음으로만 분류해줘. 방어 확인에는 코드 위치와 방어 근거를 요구하고, 판단 불가는 안전으로 간주하지 말고 필요한 추가 테스트를 써줘.

32 · 감사 보고서

감사 보고서 형식

보안 점검 결과는 “괜찮아 보임”이 아니라 증거로 남겨야 합니다. 특히 AI에게 감사를 시킬 때는 발견한 취약점보다 “판단할 수 없는데 안전하다고 말한 항목”이 더 위험합니다. 판단 불가는 안전이 아니라 추가 검증 필요입니다.

항목기록 방법
상태`발견됨`, `방어 확인`, `판단 불가`, `해당 없음` 네 가지로만 쓴다. “문제 없어 보임”은 금지한다.
위치파일, 함수, API route, DB table, policy, 배포 설정처럼 재현 가능한 위치를 적는다.
공격 시나리오개념 수준 재현 조건, 필요한 권한, 조작한 파라미터, 예상 영향 범위를 쓴다.
근거source, 경유 함수, sink, 적용된 정제, 권한 검사 위치, 로그 확인 결과를 남긴다.
위험도Critical, High, Medium, Low와 함께 개인정보, 결제, 관리자, 서비스 중단 영향을 구분한다.
수정 방향최소 변경, 부작용, 회귀 테스트, 배포 후 확인 로그를 포함한다.
재감사수정 후 `해결됨`, `미해결`, `신규 발견`을 비교한다.

AI 감사의 결론 형식

AI 감사 결과는 `취약 확인`, `방어 확인`, `판단 불가`로 나누세요. `방어 확인`에는 코드 위치와 차단 근거가 있어야 하고, `판단 불가`는 사람 검토나 실제 테스트로 넘겨야 합니다.

33 · 키워드

위험성 키워드 사전

보안 용어는 줄임말이 많아 처음 보면 벽처럼 느껴집니다. 아래 키워드는 이 칼럼과 실제 점검에서 자주 만나는 단어들입니다. 뜻을 외우기보다 “어디에서 사고가 나는지”와 연결해서 보면 됩니다.

Access Control

사용자가 어떤 리소스와 기능에 접근할 수 있는지 통제하는 것.

Authentication

사용자가 누구인지 확인하는 것. 로그인, MFA, 세션이 여기에 속한다.

Authorization

확인된 사용자가 무엇을 할 수 있는지 판단하는 것.

IDOR/BOLA

ID를 바꿔 다른 사람의 객체를 읽거나 수정하는 접근 통제 취약점.

Mass Assignment

요청 body 전체를 모델에 넣어 role, plan 같은 서버 관리 필드가 바뀌는 문제.

CSRF

로그인된 브라우저를 이용해 사용자가 의도하지 않은 상태 변경 요청을 보내는 공격.

XSS

공격자가 브라우저에서 실행될 스크립트를 주입하는 공격.

SSRF

서버가 공격자가 지정한 내부/외부 URL로 요청하게 만드는 공격.

CORS

브라우저의 교차 출처 요청 정책. 서버 권한 검사의 대체물이 아니다.

CSP

스크립트 실행 출처를 제한해 XSS 피해를 줄이는 보안 헤더.

RLS

DB row 단위 접근 정책. Supabase와 PostgreSQL에서 특히 중요하다.

Service Role

RLS를 우회할 수 있는 강한 서버 키. 브라우저 노출 금지.

SBOM

소프트웨어 구성요소 목록. 공급망과 취약점 관리를 위해 필요하다.

SAST/SCA/DAST

정적 분석, 의존성 분석, 동적 보안 테스트.

WAF

웹 공격 차단 계층. 앱 내부 권한 검사의 대체재는 아니다.

RTO/RPO

복구 시간 목표와 복구 시점 목표. 백업과 사고 대응 계획의 기준이다.

Prompt Injection

LLM 지시 흐름에 악성 지시를 섞어 모델이나 agent를 조종하는 공격.

Excessive Agency

AI agent가 필요 이상 권한으로 실제 변경, 삭제, 결제, 배포를 수행하는 위험.

Credential Stuffing

다른 사이트에서 유출된 이메일/비밀번호 조합을 자동으로 대입하는 계정 탈취 공격.

Session Fixation

공격자가 정한 세션 ID를 피해자가 로그인 후에도 쓰게 만들어 계정을 가로채는 공격. 로그인 후 세션 재발급이 핵심 방어다.

JWT Algorithm Confusion

JWT 검증 로직이 alg나 키 종류를 잘못 처리해 서명 검증을 우회하는 문제. 알고리즘 allowlist와 키 정책 고정이 필요하다.

Webhook Signature

결제사나 외부 서비스가 보낸 이벤트가 진짜인지 raw body와 secret으로 검증하는 서명. paid 이벤트를 무조건 믿으면 안 된다.

Magic Byte

파일 내용 시작 부분의 실제 형식 표시. 확장자와 MIME을 속인 파일을 걸러내는 보조 검증이다.

Dependency Confusion

내부 패키지와 같은 이름의 공개 패키지를 설치하게 만들어 악성 코드를 끼워 넣는 공급망 공격.

Typosquatting

유명 패키지와 비슷한 오타 이름으로 악성 패키지를 설치하게 유도하는 공격.

RAG ACL

검색된 문서 조각도 원본 문서의 사용자, 조직, 권한 경계를 유지해야 한다는 RAG 접근 통제 원칙.

Passkey/WebAuthn

비밀번호보다 피싱에 강한 공개키 기반 인증 방식. 직접 구현보다 검증된 인증 서비스를 쓰는 편이 안전하다.

DDoS

다수의 출처에서 트래픽을 몰아 서버, 회선, 애플리케이션, 과금 체계를 고갈시키는 공격.

Origin IP

CDN 뒤에 숨어야 하는 실제 서버 IP. 노출되면 CDN/WAF를 우회해 원본을 직접 공격할 수 있다.

API Key Scope

키가 접근할 수 있는 서비스, 리소스, 동작, IP, 만료 기간을 제한하는 범위 설정.

OIDC Keyless

CI/CD가 장기 액세스 키 대신 짧게 만료되는 OIDC 토큰으로 클라우드 권한을 얻는 방식.

Budget Alert

클라우드나 AI API 사용량이 임계치를 넘을 때 알려주는 비용 경보. 알림만으로는 차단이 아닐 수 있다.

Brute Force

로그인, OTP, reset token, 인증 코드에 가능한 값을 반복 대입하는 공격. rate limit, 점진적 지연, 실패 횟수 제한이 필요하다.

Open Redirect

신뢰된 도메인의 redirect 파라미터로 사용자를 악성 사이트로 보내는 취약점. OAuth와 로그인 후 이동에서 자주 발생한다.

Timing-safe Comparison

토큰이나 서명을 비교할 때 처리 시간 차이로 값이 추측되지 않게 하는 비교 방식.

CSPRNG

보안 토큰, 세션 ID, reset code에 써야 하는 암호학적으로 안전한 난수 생성기.

DMARC

SPF와 DKIM 결과를 바탕으로 도메인 위조 메일을 어떻게 처리할지 수신 서버에 알려주는 이메일 인증 정책.

Cache Poisoning

캐시 키나 헤더 처리가 잘못되어 공격자가 만든 응답이 다른 사용자에게 캐시되어 전달되는 문제.

bfcache

브라우저가 뒤로가기 성능을 위해 페이지 상태를 보존하는 기능. 민감 화면은 no-store와 상태 정리가 필요할 수 있다.

postMessage Origin

iframe이나 popup 메시지를 받을 때 정확한 origin과 메시지 schema를 검증해야 하는 브라우저 보안 경계.

Fail Closed

검증 실패 시 허용하지 않고 차단하는 설계. 보안 판단은 이쪽이 기본이다.

Least Privilege

필요한 최소 권한만 부여하는 원칙.

34 · FAQ

FAQ

이 칼럼만 보면 바이브 코딩 보안은 끝인가요?

이 칼럼은 1인 개발자와 초보자가 빠뜨리기 쉬운 보안 영역을 한 번에 훑는 기준 문서입니다. 인증, 세션, 권한, RLS, 시크릿, CORS/CSRF, SSRF, 파일, 결제, 공급망, LLM, 운영 대응까지 기본선은 잡을 수 있습니다. 다만 실제 서비스의 법률 판단, 침투테스트, 클라우드 계정 포렌식, 고위험 결제/의료/금융 심사는 전문가 검토가 필요합니다.

바이브 코딩 초보자는 OWASP Top 10만 보면 되나요?

Top 10은 출발점입니다. 실제 개발에는 ASVS, Cheat Sheet, API Security Top 10, LLM Top 10, 의존성 점검, 시크릿 점검, 로그와 사고 대응까지 같이 봐야 합니다.

Supabase anon key는 공개돼도 괜찮나요?

anon 또는 publishable key 자체는 클라이언트 사용을 전제로 하지만, 테이블 RLS와 정책이 제대로 있어야 안전합니다. service_role key는 RLS를 우회하므로 브라우저에 절대 들어가면 안 됩니다.

Cloudflare D1은 RLS가 없으니 위험한가요?

D1은 Workers binding으로 서버 코드에서 접근하는 구조에 맞습니다. 브라우저가 D1에 직접 붙는 구조가 아니라 서버 API에서 인증, 인가, 입력 검증, rate limit을 직접 구현해야 합니다.

Turso는 서비스키가 있어야 접근하니 괜찮나요?

토큰이 서버에만 있고 scope가 최소화되어 있으면 출발점은 좋습니다. 그러나 토큰이 브라우저, 저장소, 로그, CI에 노출되면 DB 접근권이 노출됩니다. 조직, 그룹, 읽기 전용 범위로 줄이고 주기적으로 회전해야 합니다.

개인정보를 조금만 수집해도 법적 리스크가 있나요?

이메일 하나도 개인정보가 될 수 있습니다. 이 글은 법률 자문이 아니지만, 수집 목적, 안전조치, 처리방침, 유출 통지와 신고, 삭제 요청 처리 범위를 미리 갖추는 것이 안전합니다.

회원가입과 로그인을 직접 만들면 안 되나요?

학습용이면 괜찮지만 운영 서비스에서는 위험합니다. 비밀번호 KDF, JWT 저장, OAuth state와 PKCE, refresh token rotation, MFA, 패스키, 계정 열거 방지, 크리덴셜 스터핑 대응까지 모두 운영 책임이 되기 때문입니다. 신규 서비스는 매니지드 인증을 우선 검토하는 편이 안전합니다.

로그인 rate limit은 비용 폭탄 방어와 다른가요?

예. 로그인, OTP, MFA, 비밀번호 재설정은 비용보다 계정 탈취가 핵심 위험입니다. 계정, IP, 기기, 세션 단위 제한과 점진적 지연, 임시 잠금, 재전송 cooldown, 위험 기반 CAPTCHA를 따로 설계해야 합니다.

Open Redirect가 왜 보안 취약점인가요?

신뢰된 도메인 URL처럼 보이는데 실제로는 공격자 사이트로 보내 피싱 신뢰도를 높입니다. OAuth callback, 로그인 후 이동, 이메일 인증 링크의 next, returnTo, redirect 파라미터는 상대 경로나 서버 allowlist로 제한해야 합니다.

캐시는 성능 기능 아닌가요?

성능 기능이지만 보안 경계이기도 합니다. 인증된 API 응답이 CDN public cache에 섞이거나 Service Worker cache, IndexedDB, bfcache에 민감 화면이 남으면 다른 사용자나 공용 기기에서 노출될 수 있습니다.

API 키가 서버 환경변수에만 있으면 충분한가요?

서버 전용 보관은 출발점일 뿐입니다. 키 scope, 만료, 회전, 사용량 한도, 예산 알림, 자동결제/자동 리로드 설정, CI/CD OIDC 키리스 인증, 로그 마스킹까지 같이 봐야 합니다. 키 유출은 데이터 유출과 청구서 폭탄을 동시에 만들 수 있습니다.

작은 개인 사이트도 DDoS와 악성 트래픽을 신경 써야 하나요?

예. 공격자가 꼭 대기업만 노리는 것은 아닙니다. 봇이나 자동화 공격은 비용이 낮고, 작은 사이트는 오히려 방어가 약합니다. CDN/WAF, 원본 IP 격리, rate limit, bot 방어, 사용량 경보, KISA 118 신고 절차 정도는 개인 프로젝트도 기본선으로 두는 것이 좋습니다.

CORS를 닫으면 API가 안전해지나요?

아닙니다. CORS는 브라우저의 교차 출처 응답 읽기 정책입니다. curl, 서버 요청, 같은 출처 요청, 탈취된 세션 악용을 막는 권한 검사가 아니므로 API는 서버에서 인증과 인가를 반드시 해야 합니다.

JWT를 쓰면 세션보다 안전한가요?

JWT 자체가 안전을 보장하지 않습니다. 서명 알고리즘 고정, issuer/audience/expiry 검증, 짧은 만료, refresh token rotation, logout invalidation, 민감정보 payload 금지가 함께 있어야 합니다.

AI에게 보안 감사까지 시키면 충분한가요?

AI는 1차 점검과 코드 흐름 정리에 유용하지만 완전한 보증은 아닙니다. 실제 런타임 설정, TLS, 배포 로그, secret leak, 인프라 권한, race condition, 결제 웹훅은 도구와 수동 테스트가 필요합니다.

파일 업로드는 이미지 확장자만 제한하면 되나요?

부족합니다. 크기 제한, MIME 검증, 서버 생성 파일명, public 접근 권한, SVG/HTML 차단, 이미지 재인코딩, EXIF 제거, 다운로드 권한 검사, path traversal 테스트가 필요합니다.

관리자 페이지는 URL을 어렵게 만들면 괜찮나요?

숨긴 경로는 보조 수단일 뿐입니다. 관리자 인증, MFA, 짧은 세션, CSRF 방어, 관리자 role 검증, audit log, 접근 경보, 가능하면 ZTNA/VPN 같은 다층 방어가 필요합니다.

35 · 마무리

보안은 겁주려고 있는 게 아니라 계속 만들기 위해 있다

바이브 코딩의 장점은 속도입니다. 하지만 속도는 책임을 없애지 않습니다. 오히려 더 많은 사람이 더 빨리 서비스를 만들 수 있게 되었기 때문에, 기본 보안선은 더 중요해졌습니다.

먼저 덜 모으고, 서버에서 권한을 확인하고, 키를 숨기고, RLS를 테스트하고, 입력과 출력을 검증하고, 로그를 남기되 개인정보는 남기지 않고, 사고 대응 순서를 준비하세요. 그러면 보안은 개발을 막는 브레이크가 아니라 오래 달리게 해주는 안전장치가 됩니다.

공식 참고 자료

OWASP Top 10 20252025년 최신 웹 애플리케이션 Top 10과 변경점OWASP Top Ten ProjectOWASP Top 10의 성격, 최신판, 이전판 안내OWASP API Security ProjectAPI Security Top 10 2019, 2023과 프로젝트 타임라인OWASP Mobile Top 10모바일 Top 10 2024 공식 프로젝트OWASP Top 10 for LLM ApplicationsLLM 애플리케이션 보안 위험 공식 프로젝트OWASP ASVS웹 애플리케이션 보안 검증 요구사항 표준OWASP Cheat Sheet Series인증, 세션, 시크릿, XSS, SSRF 등 실무 방어 지침OWASP Authentication Cheat Sheet로그인, MFA, 자동화 공격 방어, 계정 보안 기본선OWASP Forgot Password Cheat Sheet비밀번호 재설정, 계정 열거 방지, reset token과 brute force 방어OWASP Session Management Cheat Sheet세션 ID, 쿠키 속성, 세션 수명주기, 세션 고정과 만료 정책OWASP CSRF Prevention Cheat SheetCSRF token, signed double-submit, Origin/Referer, Fetch Metadata 방어OWASP SSRF Prevention Cheat Sheet서버가 외부 URL을 요청하는 기능의 private IP, metadata IP, redirect 방어OWASP File Upload Cheat Sheet확장자, MIME, signature, 파일명, 저장 위치, 다운로드 제한OWASP Unvalidated Redirects and Forwards Cheat Sheet로그인 후 이동, OAuth returnTo, 이메일 링크 open redirect 방어OWASP HTML5 Security Cheat SheetpostMessage origin 검증, iframe sandbox, localStorage와 브라우저 저장소 주의점OWASP Cryptographic Storage Cheat SheetCSPRNG와 암호학적 키/토큰 생성 기준OWASP NPM Security Cheat Sheetnpm audit, lockfile, lifecycle script, 의존성 공급망 점검OWASP SAMM보안 개발 수명주기와 조직 성숙도 모델NIST SSDF SP 800-218보안 소프트웨어 개발 프레임워크CISA Secure by Design기본값 보안, 고객 보안 결과, 제조자 책임 중심의 보안 설계 원칙개인정보 보호법안전조치의무, 유출 통지와 신고 등 법령 원문개인정보 보호법 제22조의2만 14세 미만 아동의 개인정보 처리와 법정대리인 동의 확인정보통신망법 제50조영리목적 광고성 정보 전송, 수신동의, 수신거부, 야간 전송 별도 동의KISA 불법스팸대응센터 FAQ영리목적 광고성 정보와 불법스팸 실무 안내Cloudflare Workers BindingsD1 등 Cloudflare 리소스를 토큰 없이 binding으로 접근하는 구조Turso AuthenticationTurso API token scope, Bearer 인증, 공개 금지 원칙PostgreSQL Row Security PoliciesPostgreSQL RLS의 기본 동작, default deny, owner bypass, BYPASSRLS