// docs / security guides / pre-ship checklist
바이브 코딩 보안 체크리스트: 출시 전 44가지 항목
Cursor, Claude Code, Lovable, Bolt, v0, Replit 및 Windsurf로 구축된 앱을 위한 실용적이고 단계별로 구성된 체크리스트입니다. 각 항목은 5분 이내에 실행 가능합니다. 프로덕션으로 진행하기 전에 이를 검토한 다음 각 주요 릴리스 전에 다시 한번 살펴보십시오. 항목은 비밀, 데이터베이스, 인증, 헤더, 타사, 배포, 모니터링 등 7가지 범주로 그룹화되며 적용되는 배포 단계 태그가 지정됩니다.
PRE = 사전 배포(소스 감사). DEPLOY = 배포 시. POST = 배포 후 확인. 항목 참조 FixVibe 해당되는 경우 category.check-id 형식의 ID를 확인하세요.
비밀 및 API 키(8개 항목)
하드코딩된 키는 바이브 코딩된 앱에서 가장 일반적으로 발견되는 것입니다. 그들을 막기 위한 8가지 항목:
- PRE — Audit
NEXT_PUBLIC_env vars.NEXT_PUBLIC_접두사가 붙은 모든 항목은 클라이언트 번들로 제공됩니다. 하나가 Supabaseservice_role키("role":"service_role"을 사용하여 JWT로 디코딩)인 경우 이를 삭제하고 서버 전용 클라이언트(src/lib/supabase/service.ts,import 'server-only')를 통해 라우팅합니다. - PRE — Grep for hardcoded provider keys.
sk_live_,pk_live_,STRIPE_SECRET,sk-ant-,sk-,AIza,AKIA및 JWT-찾는 문자열(eyJ)에 대한 소스를 검색합니다. 모든 히트를.env.local으로 이동하고 서버측에서만process.env.*을 통해서만 참조합니다. - PRE — Verify
.gitignore. 확인.env*.local,.npmrc,.yarnrc및 모든 공급자별 자격 증명 파일은 무시됩니다. 이미 커밋된 항목을 찾으려면 공급자 패턴을 통해git ls-files을 실행하세요. - PRE — Scan the built bundle.
npm run build을 실행한 다음 동일한 패턴에 대해.next/static및dist/출력을 grep합니다. 키가 번들에 도달하면 개발자는 환경을 완전히 분리한 적이 없습니다. - DEPLOY — Set secrets per environment. Vercel: 설정 → 환경 변수, 각각 Production / 미리보기 / 개발로 범위를 지정합니다.
sk_live_*을 미리보기 환경과 공유하지 마세요. 인라인 워크플로 비밀이 아닌 Vercel의 암호화된 env-var 저장소를 사용하세요. - DEPLOY — Disable build-log secret echo. 빌드 중 일부 CI 구성
echo환경 변수. 공개 빌드 로그에 값을 푸시하는echo $SECRET에 대한vercel.json, GitHub 작업 워크플로 또는 Cloudflare 페이지 설정을 감사하세요. - POST — Run a passive scan. FixVibe의 Free 계층에서는 배포된 URL을 붙여넣고 20초 정도 기다린 후
secrets.*결과를 찾습니다. secrets.browser-storage 검사는 SDK의 오용을 통해localStorage또는sessionStorage에 도착한 키를 포착합니다. - POST — Rotate any key that ever shipped. 키가 몇 분 동안 공개 번들에 있었다면 손상된 것으로 간주합니다. 대시보드를 통해 Supabase 서비스 역할 키를 순환하고, Stripe 제한된 키를 재생성하고, 콘솔을 통해 Anthropic/OpenAI/Google 키를 취소합니다.
데이터베이스 접근 제어: RLS 및 Firestore 규칙(6개 항목)
BaaS 기본값은 의도적으로 허용되므로 첫 번째 튜토리얼이 작동합니다. Production에는 명시적인 정책이 필요합니다.
- PRE — Force RLS on every
public.*table. Supabase: 각 테이블에는ALTER TABLE ... ENABLE ROW LEVEL SECURITY및FORCE ROW LEVEL SECURITY이 있어야 합니다. Force 중요: 이것이 없으면 Postgres는 테이블 소유자에 대해 RLS을 우회합니다. - PRE — Write a policy per (table, role, action). 최소:
auth.uid()에 조인하는 SELECT 정책. 더 나은 방법: INSERT / UPDATE / DELETE 정책을 분리하여 UPDATE이 소유권을 다시 지정하는user_id변경 사항을 밀수입할 수 없도록 합니다. - PRE — Replace default Firebase rules. 기본 테스트 모드 규칙은
allow read, write: if true;입니다. 컬렉션당 인증 바인딩된 규칙으로 대체:match /users/{userId}를allow read, write: if request.auth.uid == userId;로 - PRE — Lint migrations in CI. 병합하기 전에
supabase db lint또는 이에 상응하는 기능을 실행하세요.CREATE TABLE public.*에 일치하는 RLS 정책이 없으면 CI 빌드가 실패해야 합니다. - DEPLOY — Confirm RLS survived deploy. 배포 후 Supabase Studio에서 다시 확인: 테이블 → 각 행 → RLS 토글은 ON입니다. Production 데이터베이스 마이그레이션이 정책 파일보다 앞서는 경우가 있습니다. 정책이 적용되었는지 확인하세요.
- POST — Run an active scan against a verified domain. baas.supabase-rls 활성 검사는 anon 키를 사용하여 작은 시드 행에 쓰고 쓰기가 성공하면 다시 보고합니다(i.e). RLS은 실제로 시행되지 않습니다.
인증 및 세션(7항목)
AI- 코딩된 앱의 인증 버그는 미묘한 경향이 있습니다. 토큰 확인 시 하나씩 누락, HttpOnly 플래그 누락, getUser()이 있어야 하는 getSession() 등이 있습니다.
- PRE — Replace
getSession()withgetUser().getSession()은 쿠키를 읽고 신뢰합니다.getUser()은 Supabase 백엔드로 확인합니다. 서버 경로에서는 항상getUser()을 사용합니다. - PRE — Confirm token expiry. 매직 링크, 비밀번호 재설정 및 이메일 확인 토큰은 서버 강제 만료가 필요합니다. 기본 Supabase 매직 링크는 1시간 후에 만료됩니다. 실제 이유 없이 더 높은 숫자로 재정의하지 마세요.
- PRE — Verify JWT
audandexp. 어디서나 수동으로 토큰을 디코딩하는 경우 두 클레임을 모두 확인하세요. 더 나은 방법은 SDK의getUser()을 사용하는 것입니다. - PRE — Audit cookie flags. 사용자 정의 세션 쿠키는
Secure; HttpOnly; SameSite=Lax(또는 OAuth 흐름이 아닌 경우Strict)이어야 합니다.localStorage에 세션 자료가 없습니다. - PRE — Validate the
nextredirect param. 로그인 후next쿼리 매개변수는//이 아닌/으로 시작해야 합니다(attacker.example으로 공개 리디렉션). 서버 측의 다른 모든 것을 거부하십시오. - POST — Test logout. 로그인, 로그아웃하고 쿠키를 검사합니다(DevTools → 애플리케이션 → 쿠키). 세션 쿠키는 동일한 응답에서 지워져야 합니다. 지속되면 로그아웃 핸들러가 실제로 서버측 상태를 파괴하지 않는 것입니다.
- POST — Active probe. active.auth-flow 및 active.account-enumeration은 손상된 인증 경계를 확인합니다. "사용자 존재"와 "잘못된 비밀번호"에 대한 서로 다른 응답, 로그인 시 속도 제한 누락, 서명되지 않은 재설정 토큰.
HTTP 보안 헤더 및 콘텐츠 보안 정책(6개 항목)
헤더는 전체 파이프라인에서 가장 저렴한 강화이며 codegen에서 가장 일관되게 건너뜁니다.
- PRE — Ship a real CSP. 최소:
script-src 'nonce-{NONCE}' 'strict-dynamic'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'.script-src에는'unsafe-inline'이 없습니다. Next.js은 미들웨어가x-nonce요청 헤더를 설정할 때 Nonce를 자동 적용합니다. - PRE — Add the legacy three.
X-Content-Type-Options: nosniff,X-Frame-Options: DENY(또는 CSPframe-ancestors단독으로 사용),Strict-Transport-Security: max-age=31536000; includeSubDomains. - PRE — Tighten
Referrer-Policy. 기본값strict-origin-when-cross-origin은 대부분의 앱에 적합합니다.unsafe-url을 발송하지 않거나 헤더를 전혀 발송하지 마십시오. - PRE — Replace
Access-Control-Allow-Origin: *. 그렙입니다. 명시적인 원본 허용 목록으로 교체하세요.credentials: include과 함께*이 있는 경우 브라우저는 요청을 거부합니다. 하지만 이는 잘못 구성된 백엔드에 대한 방어 수단이 아닙니다. - DEPLOY — Verify headers post-deploy. DevTools 열기 → 네트워크 → 루트 문서 클릭 → 헤더 탭을 클릭합니다. CSP, HSTS, X-Frame-Options, X-Content-Type-Options가 있어야 합니다. CSP은
script-src에'unsafe-inline'이 있어서는 안 됩니다. - POST — Run headers.security-headers. 패시브 헤더 검사는 배포 플랫폼 수정 지침(Vercel
vercel.json, Cloudflare 페이지_headers, Netlify_headers, Next.js 미들웨어)과 함께 누락된 각 헤더를 보고합니다.
타사 통합 및 APIs(5개 항목)
포함하는 모든 스크립트는 CSP 예외이며 잠재적인 공급망 표면입니다. 제3자를 신뢰 경계의 일부로 취급하십시오.
- PRE — Reverse-proxy analytics where possible. PostHog, Plausible, Umami는 모두 자신의 도메인(e.g.
/api/posthog)을 통한 프록싱을 지원합니다. 이는connect-src을 동일한 출처로 유지하고 광고 차단기에서도 살아남습니다. - PRE — CSP-allowlist the rest. Google Analytics, Stripe.js, Sentry, Intercom, GTM 등의 경우 일치하는 CSP 지시문에 각 공급업체의 원본을 추가합니다(로더의 경우
script-src, 원격 측정의 경우connect-src, iframe의 경우frame-src, 픽셀의 경우img-src). - PRE — Use Stripe Checkout, not raw card forms. Stripe Checkout은 최상위 리디렉션입니다. 스크립트에는 CSP 항목이 필요하지 않습니다. 호스팅되는 PCI 표면은 전적으로 Stripe의 도메인에 있습니다. 확실한 이유가 있는 경우에만 직접 굴려보세요.
- PRE — Lock
package-lock.jsonin CI. 프로덕션 빌드에서npm ci(npm install아님)을 실행합니다. 각 릴리스 전에npm audit또는 Snyk를 사용하여 종속성을 감사하세요. - POST — Watch discovery.tech-fingerprint. 수동적 기술 스택 검색은 크롤러가 볼 수 있는 라이브러리 버전을 표시합니다. EOL React, jQuery 또는 Bootstrap을 제공하는 경우 FixVibe은 이에 플래그를 지정하고 알려진 CVE에 연결합니다.
배포 위생 및 인프라(8개 항목)
배포 방법은 배포 내용만큼 중요합니다. AI- 코딩된 앱은 특히 명시적 배포 강화의 이점을 누릴 수 있습니다.
- PRE — Disable
x-powered-by.next.config.js에서:poweredByHeader: false. 무료 버전 공개 신호를 제거합니다. - PRE — Confirm middleware lives at
src/middleware.ts.src/디렉터리 레이아웃을 사용하면 Next.js은 루트 수준middleware.ts을 무시합니다. 잘못 배치된 미들웨어는 CSP / 인증 헤더 / 속도 제한을 자동으로 설정하지 못합니다. - PRE — Sanity-check Vercel deployment protection. Production은 공개되어야 합니다. 미리보기는 비밀번호로 보호되거나 조직 구성원에게만 제공되어야 합니다. discovery.platform-vercel은 표면을 보고합니다.
- PRE — Block dotfile and config probes at the edge.
/.env,/.git/*,/.aws/*,/.next/trace패턴에 대한 다시 쓰기 또는 거부 규칙을 추가합니다. Vercel은 기본적으로 이들 중 다수에 대해 403을 반환합니다. 정확도 검토. - DEPLOY — Separate environments. Production, 미리보기, 개발. 각각은 고유한 비밀 세트를 갖습니다. 라이브 키는 미리보기에 도달하지 않으며, Stripe 테스트 모드에는 Production에 도달하지 않습니다.
- DEPLOY — Enable Vercel Web Application Firewall. Pro 및 Enterprise 요금제에는 관리형 규칙과 함께 WAF이 포함됩니다. Cloudflare 페이지에는 봇 전투 모드가 있습니다. 둘 다 자동 스캐너 남용과 비밀번호 스프레이 부하를 줄입니다.
- 프로덕션 도메인에 대한 POST — Verify TLS configuration. SSL 연구소 또는 testssl.sh. TLS 최소 1.2, TLS 1.3 선호, 약한 암호 없음, HSTS 사전 로드 가능.
- POST — Confirm health-check endpoints are minimal.
/api/health은 본문 없이200 OK을 반환해야 합니다. 인증 없이 환경을 에코하거나, 해시를 빌드하거나, 타임스탬프를 배포하지 마세요.
지속적인 모니터링 및 재검사(4개 항목)
보안은 일회성 배송 전 감사가 아닙니다. 배포할 때마다 드리프트가 발생합니다.
- Verify your production domain in FixVibe. Dashboard → Domains → DNS TXT 또는 HTTP 파일 확인. 이를 통해 예약된 재검색, 활성 프로브 및 실시간 위협 모니터링이 잠금 해제됩니다.
- Schedule passive re-scans. Pro 계획은 3시간 케이던스를 지원합니다. Unlimited은 6시간 케이던스를 지원합니다. 새로운 결과를 표시하는 모든 예약된 스캔은 이메일(및 연결한 경우 웹후크)을 트리거합니다.
- Wire outbound webhooks. Account → Webhooks → HTTPS 엔드포인트를 추가하고
scan.completed+finding.created+scan.active_api.first_used을 구독합니다. Slack / Discord / PagerDuty로 라우팅하세요. - Enable live threat monitoring on Unlimited. 인증서 투명성 로그 차이, DNS 변경 사항, JS 번들 비밀 유출, 위협 정보 목록 — 다음 예정된 검색이 아니라 감지되는 순간 시작됩니다.
다음 단계
이러한 항목이 왜 중요한지에 대한 교육적 배경을 원하십니까? AI-generated code security scanning을 읽어보세요. 각 강화 단계에 대한 구체적인 코드 조각을 원하시나요? How to secure an app built with AI coding tools을 참조하세요.
