데이터베이스 테이블이 누구나 읽을 수 있다는 걸 빌더에게 알려줬더니: "어떻게 알았어? 비공개 프로젝트인데."
Told a builder his database table was readable by anyone. His reply: "how do you know? it's a private project."
핵심 요약
AI 도구로 개발 시 Supabase의 RLS 설정을 간과해 데이터베이스가 외부에 노출되는 보안 위험을 경고합니다.
- 보안 오해 — 비공개 저장소라고 해서 앱 데이터까지 비공개인 것은 아님
- Supabase 취약점 — RLS 설정 없이 anon key만 있으면 누구나 데이터 조회 가능
- 간편한 확인법 — 두 개의 테스트 계정을 만들어 브라우저 콘솔에서 데이터 접근 시도
- AI 도구의 한계 — AI가 생성한 코드는 보안 정책을 제대로 적용하지 않을 수 있음
이 답변 때문에 이 글을 쓴다. Claude Code / Cursor / Lovable / Bolt로 개발하는 많은 사람들이 비공개 저장소(private repo)가 곧 비공개 앱(private app)을 의미한다고 진심으로 믿고 있기 때문이다.
그렇지 않다. Supabase anon key는 앱 내부에 포함되어 배포된다. 누구나 개발자 도구를 열어 키를 탈취하고, 테이블을 직접 쿼리할 수 있다. 코드는 금고에 있을지 몰라도, 데이터베이스는 여전히 현관문을 활짝 열어두고 있는 셈이다. 낯선 사람과 사용자 데이터 사이를 막아주는 유일한 장치는 Row-Level Security(RLS)뿐인데, AI 도구들은 이를 계속 건너뛰거나, 대시보드에서는 초록색으로 표시되지만 실제로는 아무것도 보호하지 못하는 USING (true) 정책으로 '활성화'해버린다.
5분이면 직접 확인할 수 있다. 도구도 필요 없다:
- Supabase 대시보드 → Database → Tables → RLS 열을 확인한다. 사용자 데이터 테이블에 "disabled"라고 되어 있으면 열려 있는 것이다.
- 각 정책을 열어본다. 조건문에
auth.uid()가 언급되지 않는다면, 아무것도 제한하고 있지 않은 것이다. - 진실 확인: 테스트 계정 두 개를 만들고, 사용자 A로 행을 작성한 뒤 브라우저 콘솔에서 사용자 B로 읽기를 시도해 본다. 데이터가 불러와진다면, 누구든 그렇게 할 수 있다는 뜻이다.
불편한 진실은, 이런 문제는 데모에서는 나타나지 않는다는 것이다. 낯선 사람들이 들이닥칠 때 나타난다. 혼란스러운 정책을 읽는 데 도움이 필요하면 댓글로 올려달라.


