Deep Link Friendly Redirect Validation을 구현하며 배운 보안 체크리스트

김민석·2025년 10월 9일
0

Tech Deep Dive

목록 보기
25/58

Intro

  • 저는 인증 콜백을 띄울 때마다 마음 한구석에서 "혹시나" 하는 불안을 느꼈어요.
  • 모바일 딥링크와 웹 브라우저를 동시에 지원해야 했고, return_url을 잘못 열어주면 순식간에 오픈 리다이렉트가 될 수 있다는 걸 알았죠.
  • 그래서 Express 미들웨어 앞단에 방어막을 치기 시작했고, 그 과정을 정리해봤습니다.

핵심 아이디어 요약

  • URL을 무턱대고 믿지 말고, 프로토콜·호스트·패턴을 순차적으로 검증합니다.
  • 모바일 딥링크는 화이트리스트 스킴으로, 웹은 도메인 화이트리스트로 필터링합니다.
  • 정규식으로 의심스러운 문자열을 한 번 더 걸러내며, 환경 변수로 운영/개발 조건을 분리합니다.

준비와 선택

  • 우선 .env에서 ALLOWED_RETURN_DOMAINS를 관리해 팀원과 공유 가능한 단일 소스를 만든다고 결정했습니다.
  • 모바일 앱 팀과 협의해 허용할 스킴 목록을 정했고, 급하게 늘릴 수 있도록 배열에 선언해두었습니다.
  • 프로덕션에서는 localhost를 차단해야 했기에 NODE_ENV를 함께 확인하도록 설계했습니다.

구현 여정

  • Step 1: URL 파싱으로 예외 케이스 잡기
    new URL(returnUrl)이 실패하면 바로 차단하도록 두었습니다. 여기서 예외가 던져지는 덕분에 엉뚱한 문자열도 잡아냅니다.
  • Step 2: 모바일 딥링크 화이트리스트
    아래처럼 모바일 스킴 배열을 만들고, 해당 스킴으로 시작하면 웹 규칙을 건너뛰고 바로 허용합니다. React Native, Expo, Capacitor처럼 커스텀 스킴이 흔하기 때문에 필수였어요.
const mobileSchemes = ['schoolmeets', 'myapp', 'yourapp']; // 앱 팀과 합의한 스킴만 허용
if (mobileSchemes.some(scheme => returnUrl.startsWith(`${scheme}://`))) {
  return true;
}
  • Step 3: 프로토콜과 환경 별 필터
    http/https만 허용하고, 프로덕션에서는 localhost가 들어오면 즉시 경고를 남깁니다. 수동 테스트하다가 깜빡하고 실서버로 던지는 위험을 막아주더군요.
  • Step 4: 의심 패턴 정규식
    배포 직전, javascript:data: 스킴을 편법으로 사용하는 공격 시나리오를 발견했습니다. 아래 정규식 배열로 간단히 막았습니다.
const suspiciousPatterns = [
  /\.(exe|bat|sh|cmd)$/i,      // 실행 파일을 노린 다운로드 유도 차단
  /javascript:/i,              // 스킴 기반 XSS 공격 방지
  /data:/i,                    // data URI로 인한 인젝션 차단
  /file:/i,
  /[<>"']/                     // HTML/JS 인젝션 문자 필터
];
  • Step 5: 도메인 화이트리스트
    마지막으로 allowedReturnDomains 배열과 일치하는지 검사하고, 실패하면 로그에 허용 목록을 함께 남깁니다. 덕분에 프런트 팀이 에러 로그만 봐도 원인을 바로 파악하더라고요.
  • 예상치 못한 이슈는 React Native 환경이 origin을 비워서 보내는 경우였습니다. 덕분에 CORS와 return_url 검증을 분리해야 한다는 교훈을 얻었습니다.
  • 정규식을 너무 빡빡하게 짠 건 아닌지 확인하려고 GPT에게 몇 가지 URL 샘플을 물어보기도 했습니다. 의심 스킴을 더 찾아주는 데 꽤 도움이 됐어요.

결과와 회고

  • 오픈 리다이렉트를 걱정하던 밤샘은 줄었고, 로그에는 차단된 URL과 원인이 깔끔히 남았습니다.
  • 모바일과 웹이 같은 API를 공유하면서도 서로 다른 규칙을 적용할 수 있게 된 게 가장 큰 수확입니다.
  • 다음에는 정규식 대신 URL 스캐너 라이브러리를 붙여보고, 허용 스킴을 관리자 페이지에서 수정할 수 있도록 자동화해볼 생각이에요.
  • 여러분은 하이브리드 앱에서 redirect 검증을 어떻게 하고 계신가요? 댓글로 팁을 공유해주시면 저도 따라 해보고 싶습니다.

Reference

profile
동업자와 함께 창업 3년차입니다. Nextjs 위주의 프로젝트를 주로 하며, React Native, Supabase, Nestjs를 주로 사용합니다. 인공지능 야간 대학원을 다니고 있습니다.

0개의 댓글