클라이언트 측 JavaScript에 노출된 API 키
브라우저로 전달되는 것 — 인라인 스크립트, 번들된 JS, source map — 은 무엇이든 누구나 읽을 수 있습니다. 프런트엔드 코드에 포함된 시크릿 키(OpenAI, Stripe 시크릿, AWS, 데이터베이스 URL)는 사실상 공개된 것입니다.
무엇인가요
빌드 도구는 컴파일 시점에 환경 변수를 인라인합니다. 클라이언트 코드에서 시크릿을 참조하면, 모든 방문자가 다운로드하는 JavaScript 번들에 그 값이 들어가게 됩니다.
중요한 구분이 있습니다: publishable/anon 키(Stripe pk_live, Firebase web config)는 공개되도록 설계되었지만, 시크릿 키(sk_live, service-role 키, 제공업체 API 키)는 그렇지 않으며 절대 브라우저에 도달해서는 안 됩니다.
왜 중요한가요
유출된 제공업체 키는 누구나 여러분의 계정으로 사용량을 쌓게 합니다 — LLM 요금, SMS 요금, 클라우드 비용 — 또는 키가 허용하는 데이터에 접근하게 합니다.
공격자는 키 패턴을 찾으려 대규모로 JavaScript 번들을 수집합니다. 커밋된 시크릿은 보통 배포된 지 몇 분 안에 악용됩니다.
고치는 방법
서드파티 API를 브라우저가 아니라 서버 route나 백엔드에서 호출하세요. 브라우저는 여러분의 endpoint와 통신하고, endpoint가 키를 보유합니다.
// app/api/summarize/route.ts (server-only)
export async function POST(req: Request) {
const { text } = await req.json();
const r = await fetch("https://api.openai.com/v1/responses", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: JSON.stringify({ model: "gpt-4o-mini", input: text }),
});
return Response.json(await r.json());
}Next.js에서는 NEXT_PUBLIC_ 접두사가 붙은 변수만 브라우저에 노출됩니다. 그 접두사 뒤에 시크릿을 절대 두지 말고, 공개해도 안전한 값에만 사용하세요.
시크릿이 브라우저로 전달됐다면 이를 폐기하고 재발급하세요. 다음 빌드에서 제거해도 이미 수집된 사본은 무효화되지 않습니다.
자주 묻는 질문
프런트엔드의 Stripe publishable 키(pk_live)가 문제인가요?
아니요 — publishable 키는 공개되도록 만들어졌습니다. 위험한 것은 서버 측에 있어야 하는 시크릿 키(sk_live)입니다.
키를 그냥 난독화하면 안 되나요?
안 됩니다. 난독화는 손쉽게 되돌릴 수 있습니다. 유일한 해결책은 시크릿을 클라이언트에서 완전히 배제하는 것입니다.
블로그 글
가짜 AI 크롤러가 .env 파일을 노리고 있습니다. 내 앱을 확인하는 방법
자격 증명 스캐너가 AI 크롤러의 이름을 빌려 허용 목록을 통과하고, 특정 파일 하나를 요청하고 있습니다. 바로 여러분의 .env입니다. 내 파일에 접근할 수 있는지 확인하는 방법과 막는 방법을 알아봅니다.
Railway 침해 사고: 다운타임 없이 앱 시크릿을 교체하는 방법
공격자들이 AI 및 플랫폼 API 키를 노리자 Railway는 모든 사용자에게 환경 변수를 교체하라고 안내했습니다. 내 노출 여부를 확인하는 방법, 앱을 멈추지 않고 모든 것을 교체하는 방법, 다음 침해의 타격을 줄이는 방법을 정리했습니다.
AI로 만든 앱을 출시하시나요? 출시 전에 이 7가지를 확인하세요
AI 코딩 도구는 ‘출시해도 안전한지’가 아니라 ‘작동하는지’에 최적화되어 있습니다. 갓 출시된 앱에서 저희가 가장 먼저 점검하는 7가지 문제와 각각의 해결책입니다.
관련 가이드
.env 파일 노출: 공격자가 시크릿을 찾아내는 방법
접근 가능한 .env 하나가 전체 스택을 넘겨줄 수 있습니다.
Supabase Row Level Security(RLS): 테이블을 확실하게 잠그기
anon 키는 공개되어 있습니다. 그것과 데이터 사이에 있는 것은 RLS뿐입니다.
Firebase Security Rules: 데이터베이스를 열어 두지 마세요
Firebase config는 원래 공개됩니다. 누가 데이터를 볼지는 규칙이 결정합니다.
프로덕션의 source map은 소스 코드를 유출합니다
배포된 .map 파일은 원본 소스를 넘겨줍니다.