ChatGPT에 프롬프트를 보내기 전, 브라우저에서 55가지가 읽힌다
보안 연구자가 Cloudflare Turnstile 프로그램 377개를 복호화하여 ChatGPT가 GPU 정보, React 내부 상태, 키스트로크 타이밍까지 수집하는 과정을 밝혔습니다. 28개 옵코드의 커스텀 VM이 매 요청마다 변하는 암호화 바이트코드를 실행합니다.
ChatGPT에서 메시지를 입력하기 전, 당신의 브라우저에서는 보이지 않는 프로그램이 실행됩니다. GPU 모델을 읽고, 화면 크기를 측정하고, 설치된 폰트를 탐색하고, ChatGPT의 React 내부 상태까지 접근합니다. 총 55가지 속성 을 수집합니다. 이것이 끝나야 비로소 프롬프트를 전송할 수 있습니다.
보안 연구자 buchodi가 Cloudflare의 Turnstile 프로그램 377개 를 복호화하여 이 과정을 낱낱이 분석했습니다. Hacker News에서 282포인트와 208개 댓글을 기록하며 개발자 커뮤니티의 뜨거운 논쟁을 촉발한 이 분석이 밝혀낸 것들을 살펴보겠습니다.
세 겹의 수집, 브라우저에서 애플리케이션 레이어까지
Turnstile이 수집하는 55가지 속성은 세 개의 레이어에 걸쳐 있습니다.
Turnstile이 수집하는 55가지 속성
첫 번째 레이어(38개) 는 전통적인 브라우저 핑거프린팅입니다. WebGL API를 통해 GPU 벤더와 렌더러 정보를 추출하고, 화면 해상도와 색 깊이를 읽고, CPU 코어 수와 메모리 용량을 확인합니다. 여기까지는 많은 봇 감지 서비스가 하는 일입니다. 흥미로운 것은 폰트 핑거프린팅입니다. 프로그램이 숨겨진 DOM 요소를 생성하고, 특정 폰트를 적용한 뒤, getBoundingClientRect로 렌더링된 텍스트의 정확한 크기를 측정합니다. 같은 폰트라도 OS와 렌더링 엔진에 따라 미세하게 다른 크기를 반환하므로, 이것이 고유한 핑거프린트가 됩니다. 수집된 핑거프린트는 localStorage에 6f376b6560133c2c라는 키로 저장되어 세션 간에 영속화 됩니다.
두 번째 레이어(5개) 는 Cloudflare의 네트워크 컨텍스트입니다. 접속 도시, 위도, 경도, IP 주소, 지역 정보가 서버 사이드 엣지 헤더로 주입됩니다. 이 정보는 요청이 Cloudflare 네트워크를 통과할 때만 존재합니다.
세 번째 레이어(3개) 가 이 분석의 핵심입니다. Turnstile은 ChatGPT의 React 내부 상태 에 접근합니다. __reactRouterContext(React Router v6+의 내부 DOM 마운트), loaderData(라우트 로더 결과), clientBootstrap(서버 사이드 렌더링 하이드레이션 마커) — 이 세 가지 속성은 ChatGPT의 React 앱이 완전히 렌더링되고 하이드레이션된 경우에만 존재합니다.
이것은 단순한 봇 감지가 아닙니다. 연구자의 표현을 빌리면, "봇 감지가 브라우저 레이어가 아닌 애플리케이션 레이어에서 작동한다" 는 것입니다. Headless 브라우저나 봇 프레임워크가 브라우저 API를 스터빙해도, 실제 ChatGPT React 번들을 실행하지 않으면 이 체크를 통과할 수 없습니다.
28개 옵코드의 커스텀 가상 머신
이 모든 수집이 어떻게 이루어지는지가 기술적으로 가장 흥미로운 부분입니다.
Cloudflare는 Turnstile의 prepare 응답에 turnstile.dx라는 필드를 포함시킵니다. 28,000자의 base64 인코딩된 데이터 로, 매 요청마다 내용이 바뀝니다. 이 데이터는 4단계의 복호화를 거쳐야 실제 핑거프린팅 프로그램이 됩니다.
첫 번째 단계에서 prepare 요청의 p 토큰으로 XOR 복호화하면 89개의 VM 명령어가 나옵니다. 이 명령어 안에 19KB의 암호화된 핑거프린팅 프로그램이 들어 있습니다. 복호화 키는 5인자 명령어의 마지막 인자에 float 리터럴(예: 97.35)로 숨겨져 있습니다. 연구자는 50개 요청에서 이 패턴을 검증했습니다. "매번 명령어의 float가 내부 blob을 유효한 JSON으로 복호화했습니다. 50번 중 50번."
복호화된 프로그램은 28개 옵코드를 가진 커스텀 가상 머신 에서 실행됩니다. ADD, XOR, CALL, BTOA, RESOLVE, BIND_METHOD, JSON_STRINGIFY 등의 명령어를 지원하며, 레지스터 주소는 매 요청마다 랜덤화된 float로 변경됩니다.
이것이 의미하는 바는, 정적 분석이 불가능 하다는 것입니다. 프로그램의 구조가 매 요청마다 바뀌므로, 특정 패턴을 찾아 차단하는 방식으로는 대응할 수 없습니다. 연구자는 377개의 프로그램을 분석하고 41개의 서로 다른 XOR 키를 확인했습니다.
키스트로크 타이밍과 마우스 속도까지
핑거프린팅만이 아닙니다. Turnstile은 행동 분석(behavioral analysis) 도 수행합니다.
- 키스트로크 타이밍 (keydown 이벤트)
- 마우스 이동 속도 (pointermove)
- 클릭/스크롤 패턴
- 붙여넣기 이벤트 감지
- 36개
_oai_so*속성 모니터링 - 유휴 시간 측정
- 25필드 핑거프린트 + SHA-256
- 난이도: 400K-500K 반복
- 72%가 5ms 이내 해결
- 7개 바이너리 감지 플래그
- 결과: OpenAI-Sentinel-Turnstile-Token
- 모든 대화 요청에 첨부
271개 명령어로 구성된 "Signal Orchestrator"는 사용자의 입력 행동을 실시간으로 추적합니다. keydown 이벤트로 키 입력 간격을 측정하고, pointermove로 마우스 이동 속도를 추적하고, 클릭과 스크롤 패턴을 기록합니다. 텍스트를 붙여넣는 이벤트도 감지합니다. window.__oai_so_*라는 이름의 36개 속성이 유휴 시간과 행동 패턴을 모니터링합니다.
이 모든 데이터는 Proof of Work와 결합됩니다. 25필드 핑거프린트에 SHA-256 해싱을 적용하며, 400K-500K 반복의 난이도를 가집니다. 72%의 챌린지가 5밀리초 이내에 풀리므로 사용자 경험에 미치는 영향은 최소이지만, 대규모 봇 공격의 비용을 높이는 역할을 합니다.
최종 결과물은 OpenAI-Sentinel-Turnstile-Token 헤더입니다. 55개 속성의 JSON이 XOR 암호화되어 이 토큰에 담기며, ChatGPT에 보내는 모든 대화 요청 에 첨부됩니다.
OpenAI는 왜 이렇게까지 해야 하는가
이 복잡한 시스템이 존재하는 이유를 이해하려면 ChatGPT의 경제학을 봐야 합니다.
ChatGPT는 세계에서 가장 많은 사용자를 가진 AI 서비스입니다. a16z의 최근 리포트에 따르면 월간 방문자가 9억 명에 달합니다. 각 프롬프트는 GPU 추론 비용을 발생시킵니다. 봇이 대량으로 API 호출을 시뮬레이션하면, GPU 리소스가 실제 사용자가 아닌 봇에게 소모됩니다.
OpenAI 측의 입장은 단순합니다. "우리 팀의 목표는 제한된 GPU 리소스가 실제 사용자에게 전달되도록 하는 것"이라며, "페이지 로드 타임, 첫 토큰까지의 시간, 페이로드 크기를 모니터링하면서 보호 조치의 오버헤드를 줄이는 데 초점을 맞추고 있다"고 밝혔습니다.
이것은 합리적인 비즈니스 로직입니다. 하지만 연구자가 지적하듯, "프라이버시 경계는 암호학적 결정이 아니라 정책적 결정" 입니다. Turnstile의 암호화는 사용자의 데이터를 보호하기 위한 것이 아니라, 수집 과정을 봇이 우회하지 못하게 하기 위한 것입니다. turnstile.dx를 생성한 측(Cloudflare)은 복호화 키를 알고 있으므로, 수집된 모든 데이터에 접근할 수 있습니다.
난독화는 "캐주얼한 검사는 방지하지만, 분석은 방지하지 못한다"는 것이 연구자의 결론입니다.
커뮤니티 반응, 합리적 보안인가 과잉 감시인가
Hacker News에서 282포인트와 208개 댓글을 기록한 이 분석에 대한 반응은 크게 세 갈래입니다.
"합리적 보안" 쪽에서는 GPU 리소스 보호가 정당한 비즈니스 필요라고 봅니다. 브라우저 핑거프린팅과 행동 분석은 reCAPTCHA 시절부터 존재하던 것이고, Turnstile은 이를 더 정교하게 구현한 것일 뿐이라는 시각입니다. React 상태 접근도 결국 "실제 ChatGPT 앱을 사용하고 있는가"를 확인하는 것이므로, 사용자에게 해가 되지 않는다는 주장입니다.
"과잉 감시" 쪽에서는 사용자 동의 없는 55가지 속성 수집의 투명성 부재를 지적합니다. 키스트로크 타이밍과 마우스 이동 속도 추적은 "봇 감지"를 넘어선 행동 프로파일링에 가깝다는 것입니다. 특히 localStorage에 핑거프린트를 영속화하는 것은 세션 간 추적(cross-session tracking)을 가능하게 한다는 우려가 있습니다.
"기술적 감탄" 쪽에서는 28개 옵코드의 커스텀 VM, 매 요청마다 변하는 암호화 바이트코드, 4단계 복호화 체인이라는 엔지니어링에 주목합니다. 이 정도 수준의 봇 방어 시스템이 실시간으로 작동하면서도 사용자 경험에 거의 영향을 미치지 않는다는 점을 높이 평가합니다.
세 입장 모두에서 합의되는 것은, 이 수준의 분석이 공개된 것 자체가 의미 있다 는 것입니다. 사용자가 자신의 데이터가 어떻게 수집되는지 알 권리가 있고, 이런 투명성이 AI 서비스 생태계의 신뢰를 높인다는 점에서 연구자의 작업은 환영받고 있습니다.
개발자에게 의미하는 것
이 분석이 개발자 실무에 미치는 영향은 두 가지입니다.
첫째, AI 서비스의 숨겨진 인프라 비용 에 대한 이해입니다. ChatGPT를 사용할 때 우리가 지불하는 것은 월 $20의 구독료(Plus)나 API 토큰 비용만이 아닙니다. 브라우저에서 커스텀 VM이 실행되고, 55가지 속성이 수집되고, Proof of Work가 수행되는 것은 모두 GPU 리소스를 보호하기 위한 인프라 오버헤드입니다. AI 서비스를 직접 구축하는 개발자라면, 이런 봇 방어 레이어의 필요성과 복잡도를 사전에 고려해야 합니다.
둘째, 프라이버시-보안 트레이드오프 의 설계 결정입니다. Turnstile의 접근법은 사용자 프라이버시를 일부 양보하는 대신 서비스 안정성을 확보합니다. 이 트레이드오프를 어느 선에서 설정하는가는 순수하게 정책적 결정이며, 기술적으로 "올바른" 답은 없습니다. 자체 AI 서비스를 운영한다면, 같은 결정을 내려야 합니다.
전망, AI 서비스의 프라이버시 투명성은 어디로
이 분석이 드러내는 더 큰 그림은, AI 서비스의 프라이버시 관행이 아직 표준화되지 않았다 는 것입니다.
ChatGPT는 세계에서 가장 많이 사용되는 AI 서비스이지만, 사용자 대부분은 프롬프트를 입력하기 전에 55가지 속성이 수집되고 있다는 사실을 모릅니다. Cloudflare Turnstile에는 전용 프라이버시 정책이 있지만, 대부분의 사용자가 이를 읽지 않습니다. 어떤 속성이 수집되는지, 얼마나 오래 보관되는지, 누가 접근할 수 있는지에 대한 명확한 공시는 부족합니다.
EU의 GDPR은 이런 데이터 수집에 명시적 동의를 요구하지만, 미국에는 동등한 연방 법률이 없습니다. 최근 발표된 백악관 AI 정책 프레임워크에도 데이터 수집 최소화나 투명성 의무는 포함되지 않았습니다.
buchodi의 분석은 AI 서비스의 "보이지 않는 레이어"를 가시화했습니다. 28,000자의 암호화된 바이트코드 뒤에서 일어나는 일을 377개 프로그램의 복호화로 밝혀낸 것입니다. 이런 종류의 독립적 보안 연구가 계속되는 것이 AI 서비스 생태계의 건강에 필수적입니다. AI가 일상의 인프라가 되어갈수록, "AI가 나에 대해 무엇을 알고 있는가"라는 질문의 답은 점점 더 복잡해지고 있습니다.