1. 기본적으로 안전한 설계 (Safe by Default)
대규모 환경에서는 개발자가 의식하지 않아도 보안이 유지되는 구조를 만드는 것이 중요합니다.
- 위험한 메서드의 재정의: Rails의
html_safe는 문자열을 안전하게 만드는 것이 아니라 이스케이프를 생략하게 하여 XSS(Cross-Site Scripting) 취약점을 유발할 수 있습니다. Shopify는 이를 방지하기 위해dangerously_output_as_html로 이름을 변경하여 개발자가 위험성을 인지하게 하고, RuboCop을 통해html_safe사용을 엄격히 제한합니다. - 자동화된 검사 도구:
erb-lint를 사용하여 JavaScript 컨텍스트 내의 안전하지 않은 데이터 삽입을 감지합니다. 또한CautionTapeBot을 활용하여 PR(Pull Request)에서 위험한 패턴이 발견되면 자동으로 보안 리뷰어를 할당하고 가이드를 제공합니다. - CSRF 방어:
skip_before_action :verify_authenticity_token과 같이 보안 설정을 해제하는 패턴을 봇으로 감시하고, 표준적인protect_from_forgery사용을 권장합니다.
2. 실수를 치명적이지 않게 만들기 (Fail-Safe Systems)
개발자의 실수가 곧바로 대규모 데이터 유출로 이어지지 않도록 보호 계층을 구축해야 합니다.
- IDOR 방어: IDOR(Insecure Direct Object Reference)는 사용자가 권한 없는 객체 ID에 접근할 때 발생합니다. Shopify는
activerecord-firewall이라는 오픈소스 젬을 개발하여 모델 수준에서 현재 사용자의 소유권을 강제로 확인합니다. 이를 통해 권한 없는 접근 시 시스템이 자동으로 차단하며, 이는 테스트 코드의 정확성을 높이는 부수적인 효과도 가져옵니다. - Watchtower 스캔: GraphQL, Sidekiq, Graphical 등 외부에 실수로 노출되기 쉬운 엔드포인트를 주기적으로 스캔하여 200 OK 응답이 발생하는지 모니터링합니다.
- 버그 바운티 프로그램: 아무리 완벽한 시스템도 취약점이 있을 수 있습니다. HackerOne을 통해 외부 보안 연구원들에게 보상을 제공함으로써 SSRF(Server-Side Request Forgery)와 같은 복잡한 취약점을 사전에 발견하고 수정합니다.
3. 보안 문화와 교육 (Making Security Cool)
보안은 강요되는 것이 아니라 개발자가 스스로 실천하고 싶은 흥미로운 분야가 되어야 합니다.
- Learn to Hack 워크숍: 지루한 규정 교육 대신 실제 취약점을 공격해보는 워크숍을 운영합니다. Google의 ‘Gruyere’나 ‘Rails Goat’와 같은 취약한 애플리케이션을 활용하여 개발자들이 직접 해커의 관점에서 시스템을 바라보게 합니다.
- CTF (Capture The Flag) 대회: 할로윈 해커페스트와 같은 이벤트를 통해 보안 문제를 풀고 깃발을 찾는 게임화된 교육을 실시합니다. 이는 개발자들의 참여도를 극적으로 높이며, 실제 서비스에서 발생했던 취약점을 문제로 만들어 교육 효과를 극대화합니다.
- 공동 책임 의식: Shopify의 모든 개발자는 자신의 코드가 80만 명 이상의 상인들의 생계에 영향을 미친다는 책임감을 공유합니다. 보안 팀은 개발자를 감시하는 경찰이 아니라 그들이 안전하게 목표를 달성하도록 돕는 파트너 역할을 수행합니다.