GN⁺: 쿠키 처리는 지뢰밭임
(grayduck.mn)- HTTP 쿠키: 웹의 상태를 유지하기 위해 사용되는 작은 데이터 조각으로, 브라우저가 설정한 후 만료될 때까지 모든 HTTP 요청에 포함됨.
- 문제 발생: 특정 자바스크립트 코드가 Go 표준 라이브러리에서 쿠키를 파싱하지 못해 오류 발생.
명세
- RFC 2109, 2965, 6265: 쿠키의 초기 정의 및 업데이트. 쿠키 값에 대한 명세가 서버와 브라우저 간에 일치하지 않음.
-
문제점:
- 서버가 보내야 하는 것과 브라우저가 수락해야 하는 것이 일치하지 않음.
- 브라우저가 서버로 보내는 쿠키 값에 대한 제한이 없음.
- 표준 라이브러리가 쿠키 헤더를 처리하는 방식에 대한 명확한 지침이 없음.
웹 브라우저
- Firefox: RFC에서 권장하지 않는 몇 가지 문자를 허용함.
- Chromium: Firefox보다 약간 더 제한적이지만, 여전히 많은 문자를 허용함.
- Safari: 허용되지 않는 문자를 만나면 쿠키 처리를 중단하지 않고 해당 문자까지의 값을 수락함.
표준 라이브러리
- Golang: RFC와 유사하게 동작하지만, 공백과 쉼표를 허용함.
- PHP: 특정 제어 문자에서 오류 발생.
- Python: 이해하지 못하는 쿠키를 무시하고 추가 쿠키 로딩을 중단함.
- Ruby: 모든 문자를 수락하고 퍼센트 인코딩함.
- Rust: UTF-8 문자열을 모두 수락함.
웹의 중요성
- 실제 문제: 명세의 모호성으로 인해 많은 웹사이트가 쉽게 오류를 일으킬 수 있음.
- 해결책: IETF HTTP Working Group이 쿠키 명세를 업데이트하고, 브라우저와 프로그래밍 언어가 쿠키를 처리하는 방법을 명확히 해야 함.
요약 표
- 브라우저 및 언어의 쿠키 처리: 각 브라우저와 언어가 쿠키를 처리하는 방식이 다름. RFC와의 일치 여부가 다름.
Hacker News 의견
-
쿠키는 예상치 못한 문제와 불편한 동작을 포함하며, 99.95%의 경우에 작동함. 쿠키 섀도잉은 동일한 이름이지만 다른 키 속성(도메인, 경로 등)을 가진 쿠키를 설정할 때 발생하는 문제로, 백엔드나 JS가 어떤 쿠키인지 구분할 수 없음
-
Rust는 표준 라이브러리에 쿠키 처리 기능이 없으며, 서드파티 "cookie" 크레이트의 동작을 참고함. 이는 Ruby처럼 퍼센트 인코딩 옵션을 포함함
-
HTTP 프로토콜은 수많은 다른 프로토콜을 내포하고 있으며, 브라우저와 웹 서버는 다양한 기능을 추가함. 이러한 기능들은 명확한 규격이 없고, 클라이언트와 서버가 호환성을 지정할 수 없음. 따라서 과거의 잘못된 결정을 계속 이어가야 하는 상황임
-
약 10년 전, 프로젝트에서 쿠키 기반 세션을 구현했을 때 Safari에서는 작동하지만 Chrome에서는 작동하지 않는 문제를 겪음. 이는 브라우저가 올바른 형식이 아니면 쿠키를 설정하지 않는 차이 때문이었음
-
쿠키의 유일한 합리적인 사용은 서버가 클라이언트를 인식할 수 있도록 불투명한 토큰을 설정하는 것임. 클라이언트가 서버가 보내지 않을 값을 처리할 수 있는 것은 문제가 아님
-
쿠키는 복잡한 문제이며, 하위 호환성 문제로 인해 변경이 거의 불가능함. 새로운 메커니즘을 만들어야 할 필요성이 있음. 예를 들어, NewCookie 메커니즘은 현대 보안 조치와 엄격한 규격을 갖출 수 있음
-
쿠키는 사라져야 하며, 인증 헤더로 대체할 수 있음. 브라우저에서 웹사이트에 표준 방식으로 인증할 수 있다면 좋을 것임. Basic 및 Digest 인증이 충분하지 않았던 것이 아쉬움
-
Safari의 네트워킹 코드가 오픈 소스가 아니므로, Swift의 Foundation 포트가 좋은 대안이 될 수 있음. 여기서 제어 및 삭제 문자를 확인할 수 있음
-
쿠키 헤더 파싱은 혼란스러움. "표준"은 실제로 존재하는 것을 반영하지 않으며, 각 백엔드 서버나 라이브러리, 프레임워크는 서로 다른 것을 수용함. 프론트엔드와 백엔드를 완전히 제어할 수 있다면 큰 문제가 아니지만, 다른 것들과 상호작용해야 할 때 매우 복잡해짐
-
Crystal 언어로 실험할 때 유사한 문제를 겪었음. 간단한 웹 스크래퍼를 구축하려 했으나, 기본 HTTP 클라이언트가 응답에 설정된 많은 쿠키를 파싱하지 못하고 중단됨