Vibe Coder를 위한 출시 전 보안 체크리스트: Cursor, Lovable, Bolt, Replit 앱을 위한 25가지 점검 사항
요약
Cursor, Lovable, Bolt 등 AI 코딩 도구로 제작된 앱들의 보안 취약점을 분석하고, 이를 방지하기 위한 25가지 보안 체크리스트를 제공합니다. AI는 기능 구현에 최적화되어 있어 보안 결함이 발생하기 쉬우므로 출시 전 반드시 점검이 필요합니다.
핵심 포인트
- AI 코딩 도구는 작동(Happy path)에 최적화되어 보안에는 취약함
- API 키 노출, RLS 비활성화 등 반복적인 보안 결함 발생
- 학습 데이터의 한계와 컨텍스트 부재가 보안 취약점의 원인
- 출시 전 비밀 정보, 인증, 데이터, API 보안 등 8개 영역 점검 필수
저는 2026년 초에 62개의 Lovable 앱을 스캔했습니다.
63%에서 심각하거나 높은 수준의 취약점이 발견되었습니다. 평균적으로 앱당 10개의 결함이 있었습니다.
이것들은 모호한 예외적인 버그가 아니었습니다. 노출된 API 키, 비활성화된 행 수준 보안 (Row-level security), 경로(Route)에서의 인증 누락, 로그인 엔드포인트의 속도 제한 (Rate limiting) 부재 등 동일한 실수들이 반복되고 있었습니다.
앱들은 훌륭해 보였고, 완벽하게 작동했습니다. 하지만 어디를 찾아봐야 할지 아는 사람이라면 누구에게나 완전히 열려 있었습니다.
이것이 바이브 코딩 (Vibe coding) 보안 문제의 핵심입니다: AI 도구는 '작동'하는 것에 최적화되어 있지, '안전'에 최적화되어 있지 않습니다. 이 둘은 같은 것이 아닙니다.
만약 여러분이 Cursor, Lovable, Bolt, Replit 또는 기타 AI 코딩 도구로 앱을 만들었다면 — 이 체크리스트는 여러분을 위한 것입니다. 보안 배경 지식은 필요하지 않습니다. 모든 항목은 구체적이고 실행 가능한 해결책과 함께 쉬운 영어로 작성되었습니다.
링크를 공유하기 전에 이 과정을 거치십시오.
AI로 구축된 앱이 계속 해킹당하는 이유
AI 코딩 어시스턴트는 기능적인 코드를 빠르게 생성합니다. 그것이 목적이죠. 하지만 AI가 지속적으로 보안에 취약한 코드를 생성하는 데에는 세 가지 구조적인 이유가 있습니다:
1. 그들은 해피 패스 (Happy path)에 최적화되어 있습니다. 여러분이 "로그인 시스템을 만들어줘"라고 프롬프트를 입력하면, AI는 정당한 사용자가 사용할 수 있는 작동하는 무언가를 만듭니다. 공격자가 무엇을 할지에 대해서는 자동으로 생각하지 않습니다.
2. 튜토리얼과 데모를 통해 학습되었습니다. 대부분의 학습 데이터는 문서 예제와 초보자용 튜토리얼에서 옵니다. 이러한 콘텐츠는 프로덕션 환경의 보안이 아니라, 단순하고 읽기 쉽게 작성된 것들입니다.
3. 그들은 여러분의 전체 컨텍스트 (Context)를 알지 못합니다. AI는 여러분의 /api/admin 경로가 공개되어서는 안 된다는 사실을 모릅니다. 여러분의 Supabase 테이블에 결제 데이터가 포함되어 있다는 것도 모릅니다. AI는 여러분이 실제로 필요로 하는 것이 아니라, 여러분이 요청한 것을 만듭니다.
그 결과, 거의 모든 바이브 코딩 (Vibe-coded) 앱에서 나타나는 일관된 취약점 세트가 발생합니다. 이 체크리스트는 가장 흔한 25가지를 다룹니다.
8가지 카테고리
취약점은 거의 매번 동일한 8가지 영역에 집중됩니다:
- 🔑 Secrets & Keys (비밀 정보 및 키) — API 키, 자격 증명 (credentials), 환경 변수 (environment variables)
- 🔐 Auth & Access (인증 및 액세스) — 경로 보호 (Route protection), RLS (Row Level Security), 관리자 액세스, 세션 관리 (session management)
- 🗄️ Data & Database (데이터 및 데이터베이스) — SQL 인젝션 (SQL injection), IDOR (Insecure Direct Object Reference), 데이터 노출 (data exposure)
- 🌐 API Security (API 보안) — 속도 제한 (Rate limiting), CORS (Cross-Origin Resource Sharing), 입력값 검증 (input validation), 파일 업로드
- 🚀 Deployment (배포) — 프로덕션 설정 (Production config), HTTPS, 보안 헤더 (security headers), 소스 맵 (source maps)
- 🖥️ Frontend (프론트엔드) — XSS (Cross-Site Scripting), localStorage 오용, 클라이언트 측 비밀 정보 노출
- 📦 Third-Party (제3자 서비스) — 의존성 CVE (Dependency CVEs), 스크립트 무결성 (script integrity), 웹훅 검증 (webhook verification)
- 📊 Monitoring (모니터링) — 로깅 (Logging), 알림 (alerting), 사고 대응 준비 (incident readiness)
체크리스트 — 처음 10개 항목은 무료
여기에서 처음 10개 항목을 전체 공개합니다. 전체 25개 항목의 체크리스트(Cursor나 Claude에 바로 붙여넣을 수 있는 2개의 전체 AI 감사 프롬프트 포함)는 이 글의 마지막 부분에서 무료로 다운로드할 수 있습니다.
🔑 SECRETS & KEYS (비밀 정보 및 키)
01 — 클라이언트 측 코드에 API 키 포함 금지 HIGH
전체 리포지토리(repo)에서 sk-, pk-, AIza, Bearer, 또는 _KEY=와 일치하는 문자열을 검색하세요. 브라우저의 개발자 도구(DevTools) 네트워크(Network) 탭이나 JavaScript 번들(bundle)에서 보이는 모든 키는 이미 노출된 상태입니다. 누구나 이를 훔쳐서 귀하의 비용을 발생시킬 수 있습니다.
해결 방법: 모든 API 키를 서버 측(server-side)으로 이동하세요. Next.js에서는 비밀 키에 NEXT_PUBLIC_ 접두사를 절대 사용하지 마세요. Vite에서는 민감한 정보에 VITE_ 접두사를 절대 사용하지 마세요. 이러한 접두사로 시작하는 키는 모든 사용자가 다운로드하는 JavaScript에 번들링됩니다.
02 — .env 파일이 gitignored 되어 있으며 git 히스토리에 존재하지 않음 HIGH
현재 .env 파일이 gitignored 되어 있을 수도 있지만, 항상 그랬나요? 터미널에서 다음 명령어를 실행하세요:
git log --all --full-history -- .env
만약 해당 명령어가 결과를 반환한다면, 귀하의 비밀 정보가 어느 시점에 git 히스토리에 커밋된 것입니다. 나중에 파일을 삭제했더라도, 비밀 정보는 여전히 히스토리에 남아 있으며 리포지토리에 접근할 수 있는 누구에게나 보입니다.
해결 방법: .env에 있었던 모든 비밀 정보를 교체(Rotate)하세요. 그런 다음 git filter-branch를 실행하거나 BFG Repo Cleaner를 사용하여 히스토리에서 해당 파일을 완전히 제거하세요.
03 — AI 생성 코드 내 하드코딩된 자격 증명(Credentials) 금지 HIGH
AI 도구들은 데모용 자격 증명(Credentials)을 코드 내에 직접 작성(inline)하는 경우가 빈번합니다. 코드베이스에서 다음 문자열들을 검색하세요:
password=
secret=
token=
...
특히 컴포넌트 파일, API 라우트 핸들러(API route handlers), 그리고 모든 설정 파일(config files) 내부를 살펴보세요. 제가 경험하기로는 바이브 코딩(vibe-coded)된 코드베이스의 약 3개 중 1개꼴로 하드코딩된 자격 증명이 발견됩니다.
해결책: 모든 자격 증명은 .env 파일에 저장해야 합니다. 코드 내에서는 process.env.YOUR_SECRET와 같이 참조하세요. 코드 자체에 절대 포함하지 마세요.
🔐 인증 및 액세스 (AUTH & ACCESS)
04 — 모든 라우트가 데이터를 제공하기 전에 인증(Authentication)을 확인하는지 여부 HIGH
이는 가장 흔히 누락되는 점검 사항입니다. 브라우저의 개발자 도구(DevTools)를 열어 인증 쿠키(authentication cookie)를 삭제한 뒤, 동일한 요청을 다시 보내는 방식으로 모든 API 엔드포인트(endpoint)를 수동으로 테스트하세요.
만약 여전히 데이터가 반환된다면, 인증이 누락되었거나 우회(bypass)가 가능하다는 뜻입니다.
Next.js App Router를 사용하는 경우, 사용자 데이터를 반환하는 모든 route.ts 파일 상단에서 getServerSession() 또는 그에 상응하는 함수를 호출하는지 확인하세요. Supabase Edge Functions를 사용하는 경우, 모든 함수가 JWT를 확인하는지 검증하세요.
해결책: 모든 보호된 라우트 핸들러(protected route handler)의 가장 첫 번째 단계로 인증 확인 로직을 추가하세요. 유효한 세션(session)이 없다면, 데이터베이스 쿼리가 실행되기 전에 즉시 401을 반환해야 합니다.
05 — 모든 Supabase 테이블에 행 수준 보안(Row-Level Security, RLS)이 활성화되어 있는지 여부 HIGH
이는 170개의 프로덕션 앱과 수만 개의 사용자 기록을 노출시킨 Lovable 침해 사고인 CVE-2025-48757의 배후에 있는 취약점입니다.
Supabase에서 RLS는 기본적으로 꺼져(off by default) 있습니다. 이는 프론트엔드 코드에 노출된 공개 API 키(public API key)를 사용하여, 로그인한 사용자라면 누구나 다른 사용자의 데이터를 포함하여 모든 테이블의 모든 행을 읽을 수 있음을 의미합니다.
Supabase 대시보드로 이동 → Table Editor → 각 테이블 선택 → RLS 토글을 확인하세요. 사용자 데이터를 포함하는 모든 테이블은 반드시 ON 상태여야 합니다.
해결책:
-- 테이블에 RLS 활성화
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
...
06 — 관리자 라우트(Admin routes)에 일반 사용자가 접근할 수 없는지 여부 MEDIUM
06 — 관리자 라우트(Admin routes)에 일반 사용자가 접근할 수 없는지 여부 MEDIUM
수동 테스트 방법: 일반 사용자 계정으로 로그인한 다음, /admin, /dashboard/admin, /api/admin 또는 권한이 필요한 엔드포인트(endpoint)에 접근을 시도해 보세요. 403 오류나 리다이렉트(redirect) 대신 데이터가 출력된다면, 권한 상승(privilege escalation) 취약점이 존재하는 것입니다.
가장 흔한 원인: 관리자 확인 절차가 클라이언트 사이드(client-side)에서만 실행되어 UI에서 버튼을 숨길 뿐, API 엔드포인트 자체에는 서버 사이드(server-side) 권한 확인이 없는 경우입니다.
해결 방법: 모든 관리자 API 라우트에는 사용자가 요청 본문(request body)이나 수정 가능한 JWT 클레임(claims)을 통해 전달하는 값이 아닌, 신뢰할 수 있는 소스(데이터베이스)로부터 사용자의 역할(role)을 검증하는 서버 사이드 확인 절차가 반드시 필요합니다.
🗄️ 데이터 및 데이터베이스 (DATA & DATABASE)
07 — 사용자 입력값이 쿼리(queries)에 직접 삽입되지 않는지 여부 HIGH
AI가 생성한 데이터베이스 코드는 쿼리를 구축할 때 문자열 연결(string concatenation)을 사용하는 경우가 많습니다. 이는 SQL 인젝션 (SQL injection)으로, 웹 애플리케이션에서 가장 오래되고 위험한 취약점 중 하나입니다.
절대 하지 말아야 할 방식:
// 위험함 — 사용자 입력값이 쿼리에 직접 들어감
const result = await db.query(`SELECT * FROM users WHERE id = ${userId}`)
권장하는 방식:
// 안전함 — 매개변수화된 쿼리 (parameterised query)
const result = await db.query('SELECT * FROM users WHERE id = $1', [userId])
.eq(), .filter() 및 유사한 메서드를 사용하는 Supabase의 JavaScript 클라이언트를 사용 중이라면 이미 매개변수화된 쿼리를 사용하고 있는 것입니다. 하지만 어디에서든 생 SQL (raw SQL)을 실행하고 있다면 모든 쿼리를 점검하십시오.
08 — 사용자가 자신의 데이터에만 접근할 수 있는지 여부 HIGH
이는 부적절한 직접 객체 참조 (Insecure Direct Object Reference, IDOR)라고 불리며, Vibe-coded 앱에서 가장 많이 놓치는 취약점 1위입니다.
직접 테스트해 보세요: 사용자 A로 로그인합니다. 본인이 소유한 리소스(게시물, 문서, 주문, 프로필 등)의 URL이나 ID를 복사합니다. 로그아웃합니다. 사용자 B로 로그인합니다. 해당 ID를 사용하여 그 리소스에 접근을 시도합니다.
만약 사용자 B가 사용자 A의 데이터를 볼 수 있다면, IDOR 취약점이 있는 것입니다.
해결 방법: ID로 리소스를 가져오는 모든 데이터베이스 쿼리는 반드시 현재 사용자의 ID로도 필터링해야 합니다:
// 잘못된 예 — 소유자와 관계없이 문서가 존재하기만 하면 가져옵니다
const doc = await supabase.from('documents').select('*').eq('id', docId)
...
09 — 민감한 데이터가 로그에 남지 않음 MEDIUM
AI 디버깅 코드는 흔히 전체 요청 본문(request bodies), 인증 토큰(authentication tokens), 사용자 이메일 등을 서버 로그에 출력하는 console.log 문을 추가합니다. 프로덕션(production) 환경에서 이러한 로그는 종종 Sentry, Datadog 또는 LogRocket과 같은 제3자 서비스로 전송됩니다.
코드베이스 내의 프로덕션 코드 경로(단순히 개발용 파일만이 아님)에서 console.log를 검색하세요. 특히 req.body, req.headers, JWT 토큰, 또는 사용자 이메일이나 이름이 포함된 로그를 중점적으로 확인하십시오.
해결 방법: 배포하기 전에 디버그 로그를 제거하세요. 로그 기록이 필요한 경우, 포함할 필드를 명시적으로 화이트리스트(allow-lists)로 관리하는 구조화된 로거(structured logger)를 사용하십시오.
10 — 인증 및 결제 엔드포인트의 속도 제한(Rate limiting) HIGH
속도 제한(rate limiting)이 없으면 로그인 엔드포인트가 무차별 대입 공격(brute-forced, 공격자가 분당 수천 개의 비밀번호를 시도함)을 받을 수 있습니다. AI API 엔드포인트는 막대한 비용을 발생시키는 데 악용될 수 있으며, 이메일/OTP 엔드포인트는 사용자에게 스팸을 보내는 데 사용될 수 있습니다.
/api/login, /api/register, /api/reset-password 및 모든 AI 또는 결제 엔드포인트에 속도 제한이 적용되어 있는지 확인하십시오.
해결 방법: Vercel을 사용하는 Next.js 환경에서는 @upstash/ratelimit를 사용하세요. Express 환경에서는 express-rate-limit를 사용하세요. 최소 기준: 인증 엔드포인트에 대해 IP당 분당 10회 요청.
import { Ratelimit } from "@upstash/ratelimit"
const ratelimit = new Ratelimit({
...
나머지 15가지 점검 사항
11~25번 항목은 다음 내용을 다룹니다:
- CORS 설정 오류 (와일드카드
*를 사용하면 어떤 웹사이트든 로그인된 사용자를 대신하여 요청을 보낼 수 있습니다) - 파일 업로드 검증 (프론트엔드 전용 검증은 몇 초 만에 우회됩니다)
- 프로덕션 환경 (Production) 설정 (개발 모드(dev mode)는 스택 트레이스(stack traces)를 누구에게나 노출합니다)
- HTTPS 강제 적용 및 쿠키 보안 플래그 (cookie security flags)
- 보안 헤더 (Security headers) (AI로 구축된 대부분의 앱은 securityheaders.com에서 F 등급을 받습니다)
- 소스 맵 (Source map) 노출 (누구든 코드를 역공학(reverse-engineer)할 수 있게 합니다)
dangerouslySetInnerHTML를 통한 XSS (Cross-Site Scripting)localStorage내 민감한 데이터 저장- 제3자 스크립트 무결성 (Third-party script integrity)
- 의존성 CVE (Dependency CVEs) (
배포 전 매번npm audit` 실행) - 웹훅 서명 검증 (Webhook signature verification)
- 로그인 실패 시도 로깅 (Failed login attempt logging)
- API 사용량 급증 알림 (API usage spike alerting)
- 침해 사고 대응 준비 상태 (Incident response readiness)
2가지 AI 감사 프롬프트 (AI audit prompts)
무료 체크리스트에는 2가지 전체 AI 감사 프롬프트가 포함되어 있습니다. 하나는 전체 코드베이스 스캔용이며, 다른 하나는 Supabase/데이터베이스 액세스 전용입니다. 코드베이스를 연 상태에서 Cursor, Claude 또는 ChatGPT에 둘 중 하나를 복사하여 출시 전에 실행하세요.
프롬프트 01은 다음을 제공합니다: 발견된 모든 취약점에 대한 심각도 등급(severity rating), 정확한 파일 및 줄 번호, 쉬운 영어 설명, 그리고 실제 수정된 코드를 제공합니다.
프롬프트 02는 다음을 제공합니다: 데이터베이스 계층에 대한 전체 RLS(Row Level Security) 정책 감사, SQL 인젝션(SQL injection) 체크, 그리고 서비스 역할 키(service role key) 노출 체크를 제공합니다.
전체 체크리스트 받기 — 무료
25가지 항목이 담긴 전체 체크리스트를 무료 PDF 다운로드로 이용할 수 있습니다.
위험 수준, 정확한 점검 사항, 한 줄 해결책이 포함된 25개 항목 전체와 2가지 전체 AI 감사 프롬프트가 포함되어 있습니다.
→ store.dodopayments.com/hack-safe 에서 무료 다운로드
이메일 등록은 필요하지 않습니다.
전체 감사 시스템을 원하시나요?
HackSafe Audit Kit ($3.99)는 이 체크리스트를 라이브 Notion 워크스페이스로 바꿔줍니다. 모든 수정 사항을 추적하고, 25가지 타겟형 AI 감사 프롬프트(공격 카테고리당 하나씩)를 실행하며, 위험 수준별로 필터링하고, 출시 전 게이트를 최종 승인하세요.
클릭 한 번으로 Notion 복제 가능. 20분 안에 설정 완료.
제가 놓친 취약점 유형을 발견하셨나요? 댓글로 남겨주세요 — 실제 Vibe-coded 앱 감사(Audit)에서 발견된 새로운 내용을 바탕으로 60일마다 이 기사를 업데이트합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기