
AI로 만든 Stripe 구독 결제, 보안 감사를 진행했더니 High 등급 취약점이 6건 발견된 이야기
요약
Claude Code를 활용해 빠르게 구현한 Stripe 결제 시스템에서 보안 감사 결과 6건의 High 등급 취약점이 발견된 사례를 다룹니다. AI가 '정상 동작(Happy Path)'은 잘 구현하지만, 결제 실패나 설정 누락 등 '예외 상황'에 대한 설계에는 취약할 수 있음을 경고합니다.
핵심 포인트
- AI는 정상 동작 구현에는 뛰어나나 예외 상황 설계에는 한계가 있음
- 결제 실패, Webhook 서명 검증 누락 등 심각한 보안 결함 발견
- 테스트 통과(Green)가 반드시 코드의 안전성을 보장하지 않음
- 엣지 케이스와 실패 시나리오에 대한 철저한 검증 공정 필수
Laravel + Blade로 구독형 SaaS를 Claude Code와 함께 거의 하루 만에 만들었다는 글을 얼마 전에 썼습니다. 동작하는 단계까지는 순조로웠습니다.
그 후, 출시를 전제로 보안 감사(Security Audit)를 실시했더니 High 등급 취약점이 6건 나왔습니다.
무엇이 나왔는가
가장 심각했던 것은 2가지입니다.
카드 결제가 실패해도 유료 기능을 계속 사용할 수 있었다.
플랜 판정 로직이 계약 상태를 확인하지 않고, plan_id만으로 판단하고 있었습니다. 카드가 정지되어도, 트라이얼(Trial) 기간이 끝나 결제가 한 번도 성립되지 않은 상태에서도 유료 기능은 열려 있는 상태였습니다.
Webhook의 서명 검증(Signature Verification)이 키 설정을 잊으면 무효화되는 구조였다.
환경 변수가 비어 있어도 앱은 정상적으로 실행되며, 그 상태에서는 빈 문자열끼리 대조하게 되어 검증이 의미를 갖지 못하게 됩니다. 누구나 가짜 결제 완료 통지를 보내 임의의 계정을 무상으로 유료 플랜으로 승격시킬 수 있는 상태였습니다. 인증조차 필요하지 않았습니다.
이 외에도, Stripe의 최신 API 버전에서는 이벤트 구조가 바뀌어 결제 실패 통지가 사실상 무시되게 되어 있었던 점, 해지했을 사용자가 나중에 늦게 도착한 오래된 통지로 인해 유료 플랜으로 돌아가 버리는 점, 탈퇴해도 Stripe 측의 계약이 해지되지 않고 청구만 계속 남는 점 등 총 6건이 High로 판정되었습니다.
왜 이렇게까지 깨닫지 못했는가
일반적으로 사용하는 범위 내에서는 아무것도 고장 나지 않은 것처럼 보입니다. 카드 정보를 등록하고, 결제하고, 기능을 사용할 수 있다. 여기까지는 전부 AI가 올바르게 구현했습니다.
무너지는 것은 그 이후입니다. 카드가 도중에 만료된다. 사용자가 해지한다. Webhook이 늦게 도착한다. 설정 파일의 한 줄이 빠진 채로 운영 환경에 올라간다. '잘 풀리지 않았을 때 어떻게 동작하는가'라는 부분에 허점이 집중되어 있었습니다.
테스트는 통과했습니다. 다만 정상계(Happy Path)뿐이었습니다. 결제가 중단된 후에 어떻게 되는지를 검증하는 테스트는 단 한 건도 없었습니다. 초록색 테스트 결과가 결함을 숨기고 있었던 셈입니다.
수정한 후의 이야기
지적 사항을 하나씩 수정하고, 테스트를 추가하고, 확인한다. 이것을 6번 반복했습니다. 결제 로직을 다시 쓸 때마다 테스트가 늘어나, 감사 시작 시점에 54건이었던 테스트가 86건이 되었습니다.
수정하는 도중에 기존 테스트 중 하나가 사실은 아무것도 보장하지 않고 있었다는 사실도 깨달았습니다. "부정 서명이라면 거부된다"라는 테스트가 개발 환경의 .env에 우연히 값이 들어있었기 때문에 통과했을 뿐, 값이 비어 있는 환경에서는 애초에 성립하지 않는 방식으로 작성되어 있었던 것입니다. 테스트가 초록색이라는 것을 너무 신뢰하면 이렇게 된다는 실례가 하나 더 늘었습니다.
이 경험을 통해 말할 수 있는 것
AI에게 구현을 맡기면 동작하는 코드는 빠르게 얻을 수 있습니다. 하지만 '동작한다'와 '고장 났을 때 안전하게 멈춘다'는 별개의 능력입니다. 이번 사례로 말하자면, 해피 패스(Happy Path) 구현은 AI가 처음부터 올바르게 작성했습니다. 빠져 있었던 것은 결제가 중단되거나, 통지가 늦어지거나, 탈퇴하는 등의 '잘 풀리지 않았을 때'의 설계였습니다.
결제와 같이 실수하면 금전이 얽히는 영역에서는 이 부분을 확인하는 공정을 생략할 수 없다고 생각합니다.
이 앱의 개발과 감사는 이전에 쓴 Laravel 책과 같은 방식으로 진행하고 있습니다.
AI의 생성물에 숨겨진 판단을 어떻게 찾아낼지, 인가(Authorization)나 테스트에서 무엇을 확인할지는 그쪽에 자세히 적어 두었습니다.
『코드를 한 글자도 쓰지 않는 Laravel 개발』(Zenn・¥1,200)
이 프로젝트 자체도 Gumroad에서 공개하고 있습니다. 감사에서 발견된 6건이 어떻게 수정되었는지 코드와 테스트로 확인할 수 있습니다.
Laravel Stripe Subscription Starter — Audited & Fixed
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기