인터넷 초안 쿠키: HTTP 상태 관리 메커니즘 2026년 7월
Bingler 외 2027년 1월 2일 만료 [페이지]
작업 그룹:
HTTP
인터넷 초안:
draft-ietf-httpbis-rfc6265bis-latest
폐기 예정:
6265 (승인되는 경우)
공개일:
예정 상태:
표준 트랙
만료:
저자:
S. Bingler, 편집자
M. West, 편집자
Google LLC
J. Wilander, 편집자
Apple, Inc

쿠키: HTTP 상태 관리 메커니즘

초록

이 문서는 HTTP Cookie 및 Set-Cookie 헤더 필드를 정의한다. 이러한 헤더 필드는 HTTP 서버가 HTTP 사용자 에이전트에 상태(쿠키라고 함)를 저장하여, 대체로 상태가 없는 HTTP 프로토콜 위에서 서버가 상태를 가진 세션을 유지할 수 있게 한다. 쿠키에는 보안과 개인정보 보호를 저해하는 많은 역사적 결함이 있지만, Cookie 및 Set-Cookie 헤더 필드는 인터넷에서 널리 사용된다. 이 문서는 RFC 6265를 폐기한다.

이 문서에 관하여

이 참고 사항은 RFC로 게시되기 전에 제거된다.

이 문서의 상태 정보는 https://datatracker.ietf.org/doc/draft-ietf-httpbis-rfc6265bis/에서 확인할 수 있다.

이 문서에 대한 논의는 HTTP 작업 그룹 메일링 리스트(mailto:ietf-http-wg@w3.org)에서 이루어지며, 그 보관 문서는 https://lists.w3.org/Archives/Public/ietf-http-wg/에 있다. 작업 그룹 정보는 https://httpwg.org/에서 확인할 수 있다.

이 초안의 소스와 이슈 추적기는 https://github.com/httpwg/http-extensions/labels/6265bis에서 확인할 수 있다.

이 메모의 상태

이 인터넷 초안은 BCP 78 및 BCP 79의 조항을 완전히 준수하여 제출되었다.

인터넷 초안은 인터넷 엔지니어링 태스크 포스(IETF)의 작업 문서이다. 다른 그룹도 작업 문서를 인터넷 초안으로 배포할 수 있다는 점에 유의하라. 현재 인터넷 초안의 목록은 https://datatracker.ietf.org/drafts/current/에 있다.

인터넷 초안은 최대 6개월 동안 유효한 초안 문서이며, 언제든지 다른 문서에 의해 갱신, 대체 또는 폐기될 수 있다. 인터넷 초안을 참고 자료로 사용하거나 "진행 중인 작업" 이외의 방식으로 인용하는 것은 적절하지 않다.

이 인터넷 초안은 2027년 1월 2일에 만료된다.

목차

1. 서론

이 문서는 HTTP Cookie 및 Set-Cookie 헤더 필드를 정의한다. Set-Cookie 헤더 필드를 사용하여 HTTP 서버는 이름/값 쌍과 관련 메타데이터(쿠키라고 함)를 사용자 에이전트에 전달할 수 있다. 사용자 에이전트가 서버에 후속 요청을 보낼 때, 사용자 에이전트는 메타데이터와 기타 정보를 사용하여 Cookie 헤더 필드에 이름/값 쌍을 반환할지 여부를 결정한다.

겉보기에는 단순하지만, 쿠키에는 여러 복잡성이 있다. 예를 들어, 서버는 각 쿠키를 사용자 에이전트에 보낼 때 범위를 표시한다. 이 범위는 사용자 에이전트가 쿠키를 반환해야 하는 최대 시간, 사용자 에이전트가 쿠키를 반환해야 하는 서버, 그리고 쿠키가 적용되는 연결 유형을 나타낸다.

역사적 이유로 쿠키에는 여러 보안 및 개인정보 보호 결함이 포함되어 있다. 예를 들어, 서버는 특정 쿠키가 "보안" 연결을 위한 것이라고 표시할 수 있지만, Secure 속성은 능동적 네트워크 공격자가 있는 경우 무결성을 제공하지 않는다. 마찬가지로, 특정 호스트의 쿠키는 해당 호스트의 모든 포트에서 공유되며, 웹 브라우저에서 일반적으로 사용하는 "same-origin policy"가 서로 다른 포트를 통해 가져온 콘텐츠를 격리하는 것과 대조된다.

이 명세는 쿠키를 생성하는 서버와 쿠키를 소비하는 사용자 에이전트의 개발자 모두에게 적용된다. 3.2절은 각 구현 유형의 의도된 대상 독자를 명확히 하는 데 도움을 준다.

사용자 에이전트와의 상호운용성을 최대화하기 위해, 서버는 쿠키를 생성할 때 4절에서 정의한 잘 동작하는 프로파일로 스스로를 제한하는 것이 좋다.

사용자 에이전트는 4절에서 정의한 잘 동작하는 프로파일을 따르지 않는 기존 서버와의 상호운용성을 최대화하기 위해, 5절에서 정의한 더 관대한 처리 규칙을 구현해야 한다.

이 문서는 인터넷에서 실제로 사용되는 이러한 헤더 필드의 구문과 의미론을 지정한다. 특히 이 문서는 오늘날 사용 중인 것 이상의 새로운 구문이나 의미론을 만들지 않는다. 4절에서 제공하는 쿠키 생성 권장사항은 현재 서버 동작 중 선호되는 하위 집합을 나타내며, 5절에서 제공하는 더 관대한 쿠키 처리 알고리즘조차도 오늘날 사용 중인 모든 구문적·의미적 변형을 권장하지는 않는다. 일부 기존 소프트웨어가 권장 프로토콜과 중요한 방식으로 다른 경우, 이 문서는 그 차이를 설명하는 주석을 포함한다.

이 문서는 [RFC6265]를 폐기한다.

2. 규약

2.1. 적합성 기준

이 문서에서 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL"은 여기 표시된 것처럼 모두 대문자로 나타날 때, 그리고 오직 그 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석된다.

알고리즘의 일부로 명령형으로 표현된 요구사항(예: "strip any leading space characters" 또는 "return false and abort this algorithm")은 해당 알고리즘을 도입할 때 사용된 핵심 단어("MUST", "SHOULD", "MAY" 등)의 의미로 해석된다.

알고리즘이나 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동등하다면 어떤 방식으로든 구현할 수 있다. 특히 이 명세에서 정의하는 알고리즘은 이해하기 쉽도록 의도된 것이며, 성능이 뛰어나도록 의도된 것은 아니다.

2.2. 구문 표기법

이 명세는 [RFC5234]의 Augmented Backus-Naur Form(ABNF) 표기법을 사용한다.

다음 핵심 규칙은 [RFC5234] 부록 B.1에 정의된 대로 참조로 포함된다: ALPHA(문자), CR(캐리지 리턴), CRLF(CR LF), CTLs (제어 문자), DIGIT(10진수 0-9), DQUOTE(큰따옴표), HEXDIG (16진수 0-9/A-F/a-f), LF(라인 피드), NUL(null 옥텟), OCTET(NUL을 제외한 임의의 8비트 데이터 시퀀스), SP(공백), HTAB(수평 탭), CHAR(임의의 [USASCII] 문자), VCHAR(임의의 표시 가능한 [USASCII] 문자), WSP(공백류).

OWS(선택적 공백)와 BWS(잘못된 공백) 규칙은 [HTTP]의 5.6.3절에 정의되어 있다.

2.3. 용어

"user agent", "client", "server", "proxy", "origin server"라는 용어는 HTTP/1.1 명세([HTTP]의 3절)에서와 같은 의미를 가진다.

request-host는 사용자 에이전트가 알고 있는 호스트의 이름으로, 사용자 에이전트가 HTTP 요청을 보내고 있거나 HTTP 응답을 받고 있는 호스트 (즉, 대응하는 HTTP 요청을 보낸 호스트의 이름)를 말한다.

request-uri라는 용어는 [HTTP]의 7.1절에 정의된 "target URI"를 가리킨다.

두 옥텟 시퀀스가 대소문자를 구분하지 않고 서로 일치한다고 하는 것은 [RFC4790]에 정의된 i;ascii-casemap 정렬 기준 아래에서 두 시퀀스가 동등한 경우, 그리고 오직 그 경우뿐이다.

string이라는 용어는 NUL이 아닌 옥텟의 시퀀스를 의미한다.

"active browsing context", "active document", "ancestor navigables", "container document", "content navigable", "dedicated worker", "Document", "inclusive ancestor navigables", "navigable", "navigate", "opaque origin", "sandboxed origin browsing context flag", "shared worker", "the worker's Documents", "top-level traversable", "WorkerGlobalScope"라는 용어는 [HTML]에 정의되어 있다.

"Service Workers"는 Service Workers 명세 [SERVICE-WORKERS]에 정의되어 있다.

"origin"이라는 용어, URI에서 origin을 도출하는 메커니즘, 그리고 origin에 대한 "the same" 일치 알고리즘은 [RFC6454]에 정의되어 있다.

"안전한" HTTP 메서드에는 [HTTP]의 9.2.1절에 정의된 GET, HEAD, OPTIONS, TRACE가 포함된다.

도메인의 "public suffix"는 "com", "co.uk", "pvt.k12.wy.us"와 같이 공개 레지스트리가 제어하는 도메인의 부분이다. 도메인의 "registrable domain"은 도메인의 public suffix와 그 왼쪽의 레이블을 합친 것이다. 즉, https://www.site.example의 경우 public suffix는 example이고, registrable domain은 site.example이다. 보안 고려사항은 8.9절을 참조하라.

"request"라는 용어와 요청의 "client", "current url", "method", "target browsing context", "url list"는 [FETCH]에 정의되어 있다.

"non-HTTP APIs"라는 용어는 쿠키를 설정하고 검색하는 데 사용되는 비HTTP 메커니즘, 예를 들어 스크립트에 쿠키를 노출하는 웹 브라우저 API를 가리킨다.

"top-level navigation"이라는 용어는 top-level traversable의 탐색을 가리킨다.

2.4. 이름 확인 시스템

이 문서는 쿠키와 함께 사용할 특정 이름 확인 시스템을 엄격히 규정하지는 않지만, 해당 시스템이 [USASCII] 문자만 사용하거나 ASCII 호환 인코딩(ACE)을 사용할 것을 요구한다. Domain Name System(DNS)이 전형적이고 관례적인 예이므로, 이 문서는 이름 확인을 DNS 관점에서 참조할 것이다.

Unicode와 같이 비ASCII 문자를 직접 노출하는 이름 확인 시스템은 이 문서의 범위를 벗어난다.

3. 개요

이 절은 origin server가 사용자 에이전트에 상태 정보를 보내고, 사용자 에이전트가 그 상태 정보를 origin server에 반환하는 방식을 개략적으로 설명한다.

상태를 저장하기 위해 origin server는 HTTP 응답에 Set-Cookie 헤더 필드를 포함한다. 후속 요청에서 사용자 에이전트는 Cookie 요청 헤더 필드를 origin server에 반환한다. Cookie 헤더 필드에는 사용자가 이전 Set-Cookie 헤더 필드에서 받은 쿠키가 포함된다. origin server는 Cookie 헤더 필드를 무시하거나 그 내용을 애플리케이션 정의 목적에 사용할 수 있다.

Origin server는 어떤 응답에도 Set-Cookie 응답 헤더 필드를 보낼 수 있다(MAY). Origin server는 하나의 응답에 여러 Set-Cookie 헤더 필드를 포함할 수 있다. Cookie 또는 Set-Cookie 헤더 필드가 있다고 해서 HTTP 캐시가 응답을 저장하고 재사용하는 것이 배제되지는 않는다.

Origin server와 중개자는 여러 Set-Cookie 헤더 필드를 하나의 헤더 필드로 결합해서는 안 된다(MUST NOT). HTTP 헤더 필드를 결합하는 일반적인 메커니즘 (즉, [HTTP]의 5.3절에 정의된 것)은 Set-Cookie 헤더 필드의 의미론을 변경할 수 있다. 이는 %x2C(",") 문자가 Set-Cookie에서 그러한 결합과 충돌하는 방식으로 사용되기 때문이다.

예를 들어,

Set-Cookie: a=b;path=/c,d=e

는 모호하다. 이는 a=b와 d=e라는 두 개의 쿠키로 의도되었을 수도 있고, /c,d=e 경로를 가진 하나의 쿠키로 의도되었을 수도 있다.

사용자 에이전트는 응답 상태 코드 또는 사용자 에이전트의 쿠키 정책에 따라 Set-Cookie 헤더 필드를 무시할 수 있다(MAY)(5.3절 참조).

참고: 쿠키의 옥텟은 [USASCII] 문자로 처리되어야 한다(MUST). 비HTTP API가 하나 이상의 비[USASCII] 문자를 포함한 set-cookie-string을 전달할 수는 있지만, 이러한 옥텟을 [USASCII] 문자 이외의 것으로 해석하려고 시도해서는 안 된다.

3.1. 예시

Set-Cookie 헤더 필드를 사용하여 서버는 HTTP 응답에서 사용자 에이전트에 짧은 문자열을 보낼 수 있으며, 사용자 에이전트는 쿠키의 범위 안에 있는 향후 HTTP 요청에서 그 문자열을 반환한다. 예를 들어, 서버는 사용자 에이전트에 31d4d96e407aad42 값을 가진 SID라는 "session identifier"를 보낼 수 있다. 그러면 사용자 에이전트는 후속 요청에서 그 세션 식별자를 반환한다.

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42

서버는 Path 및 Domain 속성을 사용하여 쿠키의 기본 범위를 변경할 수 있다. 예를 들어, 서버는 사용자 에이전트에 site.example의 모든 경로와 모든 하위 도메인에 쿠키를 반환하도록 지시할 수 있다.

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=site.example

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42

다음 예시에서 보듯이, 서버는 사용자 에이전트에 여러 쿠키를 저장할 수 있다. 예를 들어, 서버는 두 개의 Set-Cookie 헤더 필드를 반환하여 세션 식별자와 사용자의 선호 언어를 저장할 수 있다. 더 민감한 세션 식별자에 추가 보안 보호를 제공하기 위해 서버가 Secure 및 HttpOnly 속성을 사용한다는 점에 유의하라 (4.1.2절 참조).

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: lang=en-US; Path=/; Domain=site.example

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42; lang=en-US

위 Cookie 헤더 필드에는 SID라는 이름의 쿠키 하나와 lang이라는 이름의 쿠키 하나, 총 두 개의 쿠키가 포함되어 있다는 점에 유의하라.

쿠키 이름은 대소문자를 구분한다. 즉, 서버가 이름의 대소문자만 다른 두 개의 Set-Cookie 헤더 필드를 사용자 에이전트에 보내면, 사용자 에이전트는 후속 요청에서 이 두 쿠키를 모두 저장하고 반환한다.

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42
Set-Cookie: sid=31d4d96e407aad42

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42; sid=31d4d96e407aad42

서버가 사용자 에이전트가 여러 "세션"(예: 사용자 에이전트 재시작)에 걸쳐 쿠키를 지속하기를 원한다면, 서버는 Expires 속성에 만료 날짜를 지정할 수 있다. 사용자 에이전트의 쿠키 저장소가 할당량을 초과하거나 사용자가 서버의 쿠키를 수동으로 삭제하는 경우, 사용자 에이전트가 만료 날짜 전에 쿠키를 삭제할 수 있음에 유의하라.

== Server -> User Agent ==

Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2026 10:18:14 GMT

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42; lang=en-US

마지막으로 쿠키를 제거하려면, 서버는 과거의 만료 날짜를 가진 Set-Cookie 헤더 필드를 반환한다. 서버는 Set-Cookie 헤더 필드의 Path 및 Domain 속성이 쿠키가 생성될 때 사용된 값과 일치하는 경우에만 쿠키 제거에 성공한다.

== Server -> User Agent ==

Set-Cookie: lang=; Expires=Sun, 06 Nov 1994 08:49:37 GMT

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42

3.2. 구현할 요구사항 선택

이어지는 두 절인 4절5절은 두 가지 서로 다른 구현 유형에 대한 요구사항 집합을 논의한다. 이 절은 구현자가 자신의 목표에 가장 적합한 요구사항 집합을 판단하는 데 도움을 주기 위한 것이다. 잘못된 요구사항 집합을 선택하면 다른 쿠키 구현과의 호환성이 부족해질 수 있다.

호환성이 있다는 것이 구현자의 목표에 따라 서로 다른 의미를 가진다는 점이 중요하다. 이러한 차이는 의도적·비의도적 명세 변경, 명세 해석, 역사적 구현 차이로 인해 시간이 지나며 축적되어 왔다.

이 절은 쿠키 명세의 구현자를 대략 두 유형, 즉 생산자와 소비자로 나눈다. 이는 공식 용어가 아니며, 독자가 사용 사례를 직관적으로 이해하도록 돕기 위해 여기에서만 사용된다.

4. 서버 요구사항

이 절은 Cookie 및 Set-Cookie 헤더 필드의 잘 동작하는 프로파일에 대한 구문과 의미론을 설명한다.

5. 사용자 에이전트 요구사항

이 절은 이러한 요구사항을 정확히 구현하는 사용자 에이전트가 기존 서버(4절에 설명된 잘 동작하는 프로파일을 따르지 않는 서버도 포함)와 상호운용할 수 있을 만큼 충분히 상세하게 Cookie 및 Set-Cookie 헤더 필드를 지정한다.

사용자 에이전트는 여기에 지정된 것보다 더 많은 제한을 적용할 수도 있다 (예: 7.2절에 설명된 쿠키 정책에 의해 지정되는 제한). 그러나 그러한 추가 제한은 사용자 에이전트가 기존 서버와 상호운용할 가능성을 줄일 수 있다.

5.1. 하위 구성요소 알고리즘

이 절은 사용자 에이전트가 Cookie 및 Set-Cookie 헤더 필드의 특정 하위 구성요소를 처리하는 데 사용하는 몇 가지 알고리즘을 정의한다.

5.1.2. 정규화된 호스트 이름

정규화된 호스트 이름은 다음 알고리즘에 의해 생성되는 문자열이다:

  1. 호스트 이름을 개별 도메인 이름 레이블의 시퀀스로 변환한다.

  2. 모든 레이블은 U-label, A-label 또는 Non-Reserved LDH(NR-LDH) label([RFC5890]의 2.3.1절 참조) 중 하나여야 한다. 어떤 레이블이라도 이 중 하나가 아니면 이 알고리즘을 중단하고 호스트 이름 정규화에 실패한다.

  3. 각 U-label을 A-label로 변환한다([RFC5890]의 2.3.2.1절 참조).

  4. 어떤 레이블이라도 Fake A-label이면 이 알고리즘을 중단하고 호스트 이름 정규화에 실패한다.

  5. 결과 레이블을 %x2E(".") 문자로 구분하여 연결한다.

5.1.3. 도메인 일치

참고: 이 알고리즘은 두 입력이 모두 정규화되어 있다고 기대한다.

다음 조건 중 적어도 하나가 성립하면, 문자열은 주어진 도메인 문자열과 domain-match한다:

  • 도메인 문자열과 문자열이 동일하다. (이 시점에서 도메인 문자열과 문자열은 모두 소문자로 정규화되어 있음을 유의하라.)

  • 다음 조건이 모두 성립한다:

    • 도메인 문자열이 문자열의 접미사이다.

    • 도메인 문자열에 포함되지 않는 문자열의 마지막 문자가 %x2E(".") 문자이다.

    • 문자열이 호스트 이름이다(즉, IP 주소가 아니다).

5.2. "Same-site" 및 "cross-site" 요청

두 origin이 [SAMESITE]에 정의된 "same site" 기준을 만족하면 same-site이다. 다음 기준이 참이면 요청은 "same-site"이다:

  1. 요청이 사용자 인터페이스 요소를 통해 트리거된 새로고침 탐색의 결과가 아니다(사용자 에이전트가 정의한 대로; 예: 사용자가 툴바의 새로고침 버튼을 클릭해 트리거한 요청).

  2. 요청의 current url의 origin이 요청 클라이언트의 "site for cookies"(origin임)와 same-site이거나, 요청에 클라이언트가 없거나 요청의 클라이언트가 null이다.

사용자 인터페이스 요소를 통해 트리거된 새로고침 탐색의 결과인 요청은, 다시 로드된 문서가 원래 same-site 요청을 통해 탐색된 경우 same-site이다. "same-site"가 아닌 요청은 대신 "cross-site"이다.

요청 클라이언트의 "site for cookies"는 다음 하위 절에 설명된 대로 클라이언트 유형에 따라 계산된다:

5.2.1. 문서 기반 요청

사용자 에이전트의 주소 표시줄에 표시되는 URI는 사용자에게 직접 노출되는 유일한 보안 컨텍스트이며, 따라서 사용자가 특정 웹사이트를 신뢰할지 여부를 판단하기 위해 합리적으로 의존할 수 있는 유일한 신호이다. 그 URI의 origin은 사용자가 자신이 상호작용하고 있다고 가장 그럴듯하게 믿는 컨텍스트를 나타낸다. 이 origin, 즉 top-level traversable의 active document의 origin은 "top-level origin"으로 정의된다.

top-level traversable에 표시되는 문서의 경우, 문서의 "site for cookies"는 top-level origin이다.

container document의 경우, [RFC7034]의 4절에 설명된 "multiple-nested scenarios"를 고려하기 위해 문서의 각 ancestor navigable의 active document의 origin을 검사해야 한다. 문서의 "site for cookies"는 top-level origin이 문서의 origin 및 문서의 각 ancestor document의 origin과 same-site인 경우에만 top-level origin이다. 그렇지 않으면 그 "site for cookies"는 opaque origin으로 설정된 origin이다.

Document(document)가 주어지면, 다음 알고리즘은 그 "site for cookies"를 반환한다:

  1. top-documentdocument의 navigable의 top-level traversable에 있는 active document로 둔다.

  2. top-document의 sandboxed origin browsing context flag가 설정되어 있으면 top-origintop-document의 URI의 origin으로 두고, 그렇지 않으면 top-document의 origin으로 둔다.

  3. documentsdocument의 inclusive ancestor navigables의 active documents로 구성된 목록으로 둔다.

  4. documents 안의 각 item에 대해:

    1. item의 sandboxed origin browsing context flag가 설정되어 있으면 originitem의 URI의 origin으로 두고, 그렇지 않으면 item의 origin으로 둔다.

    2. origintop-origin과 same-site가 아니면, opaque origin으로 설정된 origin을 반환한다.

  5. top-origin을 반환한다.

참고: 이 알고리즘은 top-document부터 document까지의 전체 문서 체인이 모두 active인 경우에만 적용된다.

5.2.2. 워커 기반 요청

워커 기반 요청은 문서 기반 요청만큼 명확하지 않다. top-level traversable과 워커 사이에 명확한 연결이 없기 때문이다. 이는 Service Workers [SERVICE-WORKERS]에서 특히 그렇다. Service Workers는 보이는 문서가 전혀 없어도 백그라운드에서 코드를 실행할 수 있다.

5.2.2.1. Dedicated 및 Shared Workers

Dedicated worker는 간단하다. 각 dedicated worker가 오직 하나의 문서에만 바인딩되기 때문이다. 워커의 "site for cookies"는 워커의 origin이 문서의 "site for cookies"와 same-site이면 문서의 "site for cookies"이고, 그렇지 않으면 opaque origin으로 설정된 origin이다.

Shared worker는 동시에 여러 문서에 바인딩될 수 있다. 이러한 문서들이 서로 다른 "site for cookies" 값을 가질 가능성이 충분히 있으므로, 그 값들이 모두 워커의 origin과 same-site가 아닌 경우 워커의 "site for cookies"는 opaque origin으로 설정된 origin이 되고, 그 값들이 일치하는 경우에는 워커의 origin이 된다.

WorkerGlobalScope(worker)가 주어지면, 다음 알고리즘은 그 "site for cookies"를 반환한다:

  1. siteworker의 origin으로 둔다.

  2. worker의 Documents 안의 각 document에 대해:

    1. document-site를 (5.2.1절에 정의된 대로) document의 "site for cookies"로 둔다.

    2. document-sitesite와 same-site가 아니면, opaque origin으로 설정된 origin을 반환한다.

  3. site를 반환한다.

5.2.2.2. Service Workers

Service Workers는 더 복잡하다. Service Workers는 이를 등록한 Document와는 부차적인 관계만 있는 완전히 별개의 실행 컨텍스트로 동작하기 때문이다.

사용자 에이전트가 Service Workers를 처리하는 방식은 다를 수 있지만, 사용자 에이전트는 [SERVICE-WORKERS] 명세와 일치하는 것이 좋다(SHOULD).

사용자 에이전트는 100 레벨 상태 코드가 있는 응답에 포함된 Set-Cookie 헤더 필드를 무시하거나, 자신의 쿠키 정책에 따라 무시할 수 있다(MAY)(7.2절 참조).

그 밖의 모든 Set-Cookie 헤더 필드는 5.6절에 따라 처리하는 것이 좋다(SHOULD). 즉, 100 레벨이 아닌 상태 코드가 있는 응답(400 및 500 레벨 상태 코드의 응답도 포함)에 포함된 Set-Cookie 헤더 필드는 사용자 에이전트의 쿠키 정책에 따라 무시되지 않는 한 처리하는 것이 좋다(SHOULD).

쿠키 이름 접두사에 대한 사용자 에이전트의 요구사항은 서버의 요구사항(4.1.3절)과 약간 다르다. UA는 접두사 문자열을 대소문자를 구분하지 않고 일치시켜야 하기 때문이다(MUST).

접두사에 대한 규범 요구사항은 5.7절에 정의된 저장 모델 알고리즘에 자세히 설명되어 있다.

이는 일부 서버가 쿠키를 대소문자를 구분하지 않고 처리하여, 의도치 않게 대소문자가 잘못된 접두사를 잘못 대문자화하고 수락하는 결과를 낳기 때문이다.

예를 들어, 서버가 다음 Set-Cookie 헤더 필드를 보낸다면

Set-Cookie: __SECURE-SID=12345

접두사를 대소문자를 구분하여 검사하는 UA는 이 쿠키를 수락하며, 서버는 그 쿠키가 __Secure-로 철자된 쿠키와 동일한 보장의 대상이라고 잘못 믿게 된다.

또한 서버는 공격자가 접두사가 붙은 쿠키를 가장하기 위해 의도적으로 쿠키의 대소문자를 잘못 쓰는 공격에 취약하다. 예를 들어, 사이트에 이미 __Secure-SID=12345 쿠키가 있고, 어떤 수단으로든 공격자가 접두사를 대소문자를 구분하여 검사하는 UA에 대해 해당 사이트에 다음 Set-Cookie 헤더 필드를 보낸다고 하자.

Set-Cookie: __SeCuRe-SID=evil

다음에 사용자가 사이트를 방문하면 UA는 두 쿠키를 모두 보낸다:

Cookie: __Secure-SID=12345; __SeCuRe-SID=evil

대소문자를 구분하지 않는 서버는 두 쿠키를 구분할 수 없으므로, 공격자가 사이트를 침해할 수 있게 된다.

이러한 문제를 방지하기 위해 UA는 쿠키 이름 접두사를 대소문자를 구분하지 않고 일치시켜야 한다(MUST).

참고: 이름이 다른 쿠키는 여전히 UA에 의해 별개의 것으로 간주된다. 따라서 __Secure-foo=bar__secure-foo=baz는 서로 다른 쿠키로 동시에 존재할 수 있으며, 둘 다 __Secure- 접두사의 요구사항이 적용된다.

다음은 적합한 사용자 에이전트가 거부할 Set-Cookie 헤더 필드의 예이다.

Set-Cookie: __Secure-SID=12345; Domain=site.example
Set-Cookie: __secure-SID=12345; Domain=site.example
Set-Cookie: __SECURE-SID=12345; Domain=site.example
Set-Cookie: __Host-SID=12345
Set-Cookie: __host-SID=12345; Secure
Set-Cookie: __host-SID=12345; Domain=site.example
Set-Cookie: __HOST-SID=12345; Domain=site.example; Path=/
Set-Cookie: __Host-SID=12345; Secure; Domain=site.example; Path=/
Set-Cookie: __host-SID=12345; Secure; Domain=site.example; Path=/
Set-Cookie: __HOST-SID=12345; Secure; Domain=site.example; Path=/

반면 다음 Set-Cookie 헤더 필드는 보안 origin에서 설정된 경우 수락된다.

Set-Cookie: __Secure-SID=12345; Domain=site.example; Secure
Set-Cookie: __secure-SID=12345; Domain=site.example; Secure
Set-Cookie: __SECURE-SID=12345; Domain=site.example; Secure
Set-Cookie: __Host-SID=12345; Secure; Path=/
Set-Cookie: __host-SID=12345; Secure; Path=/
Set-Cookie: __HOST-SID=12345; Secure; Path=/

5.7. 저장 모델

사용자 에이전트는 각 쿠키에 대해 다음 필드를 저장한다: name, value, expiry-time, domain, path, creation-time, last-access-time, persistent-flag, host-only-flag, secure-only-flag, http-only-flag, same-site-flag.

사용자 에이전트가 request-uri로부터 name이 cookie-name, value가 cookie-value, attributes가 cookie-attribute-list인 "쿠키를 수신"하면, 사용자 에이전트는 다음과 같이 쿠키를 처리해야 한다(MUST):

  1. 사용자 에이전트는 수신한 쿠키 전체를 무시할 수 있다(MAY). 5.3절을 참조하라.

  2. cookie-name이 비어 있고 cookie-value도 비어 있으면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  3. cookie-name 또는 cookie-value가 %x00-08 / %x0A-1F / %x7F 문자(HTAB을 제외한 CTL 문자)를 포함하면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  4. cookie-name과 cookie-value 길이의 합이 4096 옥텟보다 크면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  5. name이 cookie-name이고 value가 cookie-value인 새 쿠키를 생성한다. creation-time과 last-access-time을 현재 날짜와 시간으로 설정한다.

  6. cookie-attribute-list가 attribute-name이 "Max-Age"인 속성을 포함하면:

    1. 쿠키의 persistent-flag를 true로 설정한다.

    2. 쿠키의 expiry-time을 cookie-attribute-list에서 attribute-name이 "Max-Age"인 마지막 속성의 attribute-value로 설정한다.

    그렇지 않고, cookie-attribute-list가 attribute-name이 "Expires"인 속성을 포함하며(attribute-name이 "Max-Age"인 속성은 포함하지 않으면):

    1. 쿠키의 persistent-flag를 true로 설정한다.

    2. 쿠키의 expiry-time을 cookie-attribute-list에서 attribute-name이 "Expires"인 마지막 속성의 attribute-value로 설정한다.

    그렇지 않으면:

    1. 쿠키의 persistent-flag를 false로 설정한다.

    2. 쿠키의 expiry-time을 표현 가능한 가장 늦은 날짜로 설정한다.

  7. cookie-attribute-list가 attribute-name이 "Domain"인 속성을 포함하면:

    1. domain-attribute를 cookie-attribute-list에서 attribute-name이 "Domain"이고 attribute-value 길이가 1024 옥텟 이하인 마지막 속성의 attribute-value로 둔다. (앞에 %x2E(".")가 있으면, 그 문자가 허용되지 않더라도 무시된다는 점에 유의하라.)

    그렇지 않으면:

    1. domain-attribute를 빈 문자열로 둔다.

  8. domain-attribute가 CHAR에 속하지 않는 문자를 포함하면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  9. 사용자 에이전트가 "public suffixes"를 거부하도록 구성되어 있고 domain-attribute가 public suffix이면:

    1. request-host-canonical을 정규화된 request-host로 둔다.

    2. request-host 정규화에 실패하면 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

    3. domain-attribute가 request-host-canonical과 동일하면:

      1. domain-attribute를 빈 문자열로 둔다.

      그렇지 않으면:

      1. 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

    참고: 이 단계는 attacker.example이 Domain 속성이 "example"인 쿠키를 설정하여 site.example의 무결성을 방해하는 것을 방지한다.

  10. domain-attribute가 비어 있지 않으면:

    1. request-host-canonical이 domain-attribute와 domain-match하지 않으면(5.1.3절 참조):

      1. 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

      그렇지 않으면:

      1. 쿠키의 host-only-flag를 false로 설정한다.

      2. 쿠키의 domain을 domain-attribute로 설정한다.

    그렇지 않으면:

    1. 쿠키의 host-only-flag를 true로 설정한다.

    2. 쿠키의 domain을 request-host-canonical로 설정한다.

  11. cookie-attribute-list가 attribute-name이 "Path"인 속성을 포함하면, 쿠키의 path를 cookie-attribute-list에서 attribute-name이 "Path"이고 attribute-value 길이가 1024 옥텟 이하인 마지막 속성의 attribute-value로 설정한다. 그렇지 않으면 쿠키의 path를 request-uri의 default-path로 설정한다.

  12. cookie-attribute-list가 attribute-name이 "Secure"인 속성을 포함하면, 쿠키의 secure-only-flag를 true로 설정한다. 그렇지 않으면 쿠키의 secure-only-flag를 false로 설정한다.

  13. request-uri가 (사용자 에이전트가 정의한) "secure" 연결을 나타내지 않고, 쿠키의 secure-only-flag가 true이면, 이 단계들을 중단하고 쿠키 전체를 무시한다.

  14. cookie-attribute-list가 attribute-name이 "HttpOnly"인 속성을 포함하면, 쿠키의 http-only-flag를 true로 설정한다. 그렇지 않으면 쿠키의 http-only-flag를 false로 설정한다.

  15. 쿠키가 "non-HTTP" API에서 수신되었고 쿠키의 http-only-flag가 true이면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  16. 쿠키의 secure-only-flag가 false이고 request-uri가 "secure" 연결을 나타내지 않으면, 쿠키 저장소에 다음 기준을 모두 만족하는 쿠키가 하나 이상 있는 경우 이 알고리즘을 중단하고 쿠키 전체를 무시한다:

    1. 그 이름이 새로 생성된 쿠키의 이름과 일치한다.

    2. 그 secure-only-flag가 true이다.

    3. 그 domain이 새로 생성된 쿠키의 domain과 domain-match하거나(5.1.3절 참조), 그 반대이다.

    4. 새로 생성된 쿠키의 path가 기존 쿠키의 path와 path-match한다.

    참고: 경로 비교는 대칭적이지 않다. 이는 새로 생성된 비보안 쿠키가 기존 보안 쿠키를 덮어쓰지 않도록 보장하여, cookie-fixing 공격에 대한 일부 완화를 제공한다. 즉, 이름이 'a'이고 경로가 '/login'인 기존 보안 쿠키가 있을 때, 이름이 'a'인 비보안 쿠키는 '/' 또는 '/foo' 경로에 대해 설정될 수 있지만, '/login' 또는 '/login/en' 경로에 대해서는 설정될 수 없다.

  17. cookie-attribute-list가 attribute-name이 "SameSite"이고 attribute-value가 "Strict", "Lax" 또는 "None"인 속성을 포함하면, 쿠키의 same-site-flag를 cookie-attribute-list에서 attribute-name이 "SameSite"인 마지막 속성의 attribute-value로 설정한다. 그렇지 않으면 쿠키의 same-site-flag를 "Default"로 설정한다.

  18. 쿠키의 same-site-flag가 "None"이 아니면:

    1. 쿠키가 "non-HTTP" API에서 수신되었고, 그 API가 navigable의 active document에서 호출되었으며 해당 "site for cookies"가 top-level origin과 same-site가 아니면, 이 알고리즘을 중단하고 새로 생성된 쿠키 전체를 무시한다.

    2. 쿠키가 "same-site" 요청에서 수신되었으면 (5.2절에 정의됨), 나머지 하위 단계를 건너뛰고 쿠키 처리를 계속한다.

    3. 쿠키가 top-level traversable [HTML]을 탐색하는 요청에서 수신되었으면 (예: 요청의 "reserved client"가 null이거나, 그 "target browsing context"의 navigable이 top-level traversable인 환경인 경우), 나머지 하위 단계를 건너뛰고 쿠키 처리를 계속한다.

      참고: 최상위 탐색은 새 쿠키가 탐색 전에 이미 존재했다면 요청과 함께 전송되지 않았을 경우라도, 어떤 SameSite 값이든 가진 쿠키를 생성할 수 있다.

    4. 이 알고리즘을 중단하고 새로 생성된 쿠키 전체를 무시한다.

  19. 쿠키의 "same-site-flag"가 "None"이면, 쿠키의 secure-only-flag가 true가 아닌 한 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  20. cookie-name이 대소문자를 구분하지 않고 문자열 "__Secure-"와 일치하는 것으로 시작하면, 쿠키의 secure-only-flag가 true가 아닌 한 이 알고리즘을 중단하고 쿠키 전체를 무시한다.

  21. cookie-name이 대소문자를 구분하지 않고 문자열 "__Host-"와 일치하는 것으로 시작하면, 쿠키가 다음 기준을 모두 만족하지 않는 한 이 알고리즘을 중단하고 쿠키 전체를 무시한다:

    1. 쿠키의 secure-only-flag가 true이다.

    2. 쿠키의 host-only-flag가 true이다.

    3. cookie-attribute-list가 attribute-name이 "Path"인 속성을 포함하고, 쿠키의 path가 /이다.

  22. cookie-name이 비어 있고 다음 조건 중 하나가 true이면, 이 알고리즘을 중단하고 쿠키 전체를 무시한다:

    • cookie-value가 대소문자를 구분하지 않고 문자열 "__Secure-"와 일치하는 것으로 시작한다

    • cookie-value가 대소문자를 구분하지 않고 문자열 "__Host-"와 일치하는 것으로 시작한다

  23. 쿠키 저장소가 새로 생성된 쿠키와 동일한 name, domain, host-only-flag, path를 가진 쿠키를 포함하면:

    1. old-cookie를 새로 생성된 쿠키와 동일한 name, domain, host-only-flag, path를 가진 기존 쿠키로 둔다. (이 알고리즘은 그러한 쿠키가 최대 하나만 존재한다는 불변식을 유지한다는 점에 유의하라.)

    2. 새로 생성된 쿠키가 "non-HTTP" API에서 수신되었고 old-cookie의 http-only-flag가 true이면, 이 알고리즘을 중단하고 새로 생성된 쿠키 전체를 무시한다.

    3. 새로 생성된 쿠키의 creation-time을 old-cookie의 creation-time과 일치하도록 업데이트한다.

    4. 쿠키 저장소에서 old-cookie를 제거한다.

  24. 새로 생성된 쿠키를 쿠키 저장소에 삽입한다.

쿠키의 만료 날짜가 과거이면 그 쿠키는 "expired"이다.

쿠키 저장소에 만료된 쿠키가 언제든 존재하면, 사용자 에이전트는 쿠키 저장소에서 모든 만료된 쿠키를 제거해야 한다(MUST).

어떤 domain 필드를 공유하는 쿠키의 수가 구현에서 정의한 상한(예: 50개의 쿠키)을 초과하면, 사용자 에이전트는 언제든 쿠키 저장소에서 "초과 쿠키 제거"를 할 수 있다(MAY).

쿠키 저장소가 미리 정해진 상한(예: 총 3000개의 쿠키)을 초과하면, 사용자 에이전트는 언제든 쿠키 저장소에서 "초과 쿠키 제거"를 할 수 있다(MAY).

사용자 에이전트가 쿠키 저장소에서 초과 쿠키를 제거할 때, 사용자 에이전트는 다음 우선순위 순서로 쿠키를 제거해야 한다(MUST):

  1. 만료된 쿠키.

  2. secure-only-flag가 false이고, 미리 정해진 수보다 많은 다른 쿠키와 domain 필드를 공유하는 쿠키.

  3. 미리 정해진 수보다 많은 다른 쿠키와 domain 필드를 공유하는 쿠키.

  4. 모든 쿠키.

두 쿠키의 제거 우선순위가 같으면, 사용자 에이전트는 last-access-time이 가장 이른 쿠키를 먼저 제거해야 한다(MUST).

"현재 세션이 끝나면"(사용자 에이전트가 정의한 대로), 사용자 에이전트는 persistent-flag가 false로 설정된 모든 쿠키를 쿠키 저장소에서 제거해야 한다(MUST).

5.8. 검색 모델

이 절은 쿠키 저장소에서 cookie-string 형태로 쿠키를 검색하는 방식을 정의한다. "retrieval"은 cookie-string 생성이 필요한 모든 이벤트이다. 예를 들어, HTTP 요청을 위한 Cookie 헤더 필드를 만들기 위해 retrieval이 발생할 수 있고, 쿠키에 대한 접근을 제공하는 "non-HTTP" API 호출에서 cookie-string을 반환하기 위해 retrieval이 필요할 수도 있다. retrieval에는 관련 URI, same-site 상태, type이 있으며, 이들은 retrieval의 유형에 따라 아래에 정의된다.

5.8.2. 비HTTP API

사용자 에이전트는 저장된 쿠키에 접근하는 데 사용할 수 있는 "non-HTTP" API를 구현할 수 있다(MAY).

사용자 에이전트는 retrieval이 third-party 컨텍스트 안에서 발생하는 경우와 같은 특정 컨텍스트에서 빈 cookie-string을 반환할 수 있다(MAY) (7.1절 참조).

사용자 에이전트가 관련 Document가 있는 "non-HTTP" API의 특정 호출에 대해 쿠키를 반환하는 경우, 사용자 에이전트는 5.8.3절에 정의된 알고리즘에 따라 cookie-string을 계산해야 한다(MUST). 이때 retrieval의 URI는 호출자가 정의하며 ([DOM-DOCUMENT-COOKIE] 참조), retrieval의 same-site 상태는 Document의 "site for cookies"가 5.2.1절에 정의된 top-level origin과 same-site이면 "same-site"이고(그렇지 않으면 "cross-site"), retrieval의 type은 "non-HTTP"이다.

5.8.3. 검색 알고리즘

쿠키 저장소와 retrieval이 주어지면, 다음 알고리즘은 주어진 쿠키 저장소에서 cookie-string을 반환한다.

  1. retrieval-host-canonical을 retrieval URI의 정규화된 host로 둔다.

  2. retrieval URI의 host 정규화에 실패하면, 이 알고리즘을 중단한다.

  3. cookie-list를 쿠키 저장소에서 다음 요구사항을 모두 만족하는 쿠키의 집합으로 둔다:

    • 다음 중 하나:

      • 쿠키의 host-only-flag가 true이고 retrieval-host-canonical이 쿠키의 domain과 동일하다.

      또는:

      • 쿠키의 host-only-flag가 false이고 retrieval-host-canonical이 쿠키의 domain과 domain-match한다(5.1.3절 참조).

      • "public suffixes"를 거부하도록 구성된 사용자 에이전트의 경우, 쿠키의 domain이 public suffix가 아니다.

      참고: public suffix list가 쿠키 생성 이후 변경되었을 수 있다. 이 변경으로 인해 쿠키의 domain이 public suffix가 되었다면, 그 쿠키가 지금 생성되었다면 생성 중에 거부되었을 것이다 (5.7절 9단계 참조).

    • retrieval URI의 path가 쿠키의 path와 path-match한다.

    • 쿠키의 secure-only-flag가 true이면, retrieval URI는 (사용자 에이전트가 정의한) "secure" 연결을 나타내야 한다.

      참고: "secure" 연결의 개념은 이 문서에서 정의하지 않는다. 일반적으로 사용자 에이전트는 연결이 SSL 또는 TLS [TLS13]와 같은 전송 계층 보안을 사용하거나 host가 신뢰되는 경우 연결을 secure하다고 간주한다. 예를 들어 대부분의 사용자 에이전트는 "https"를 secure 프로토콜을 나타내는 scheme으로, "localhost"를 신뢰된 host로 간주한다.

    • 쿠키의 http-only-flag가 true이면, retrieval의 type이 "non-HTTP"인 경우 쿠키를 제외한다.

    • 쿠키의 same-site-flag가 "None"이 아니고 retrieval의 same-site 상태가 "cross-site"이면, 다음 조건을 모두 만족하지 않는 한 쿠키를 제외한다:

      • retrieval의 type이 "HTTP"이다.

      • same-site-flag가 "Lax" 또는 "Default"이다.

      • retrieval과 관련된 HTTP 요청이 "safe" 메서드를 사용한다.

      • retrieval과 관련된 HTTP 요청의 target browsing context가 active browsing context 또는 top-level traversable이다.

  4. 사용자 에이전트는 cookie-list를 다음 순서로 정렬하는 것이 좋다(SHOULD):

    • 더 긴 path를 가진 쿠키가 더 짧은 path를 가진 쿠키보다 먼저 나열된다.

    • path 필드 길이가 같은 쿠키들 사이에서는, creation-time이 더 이른 쿠키가 creation-time이 더 늦은 쿠키보다 먼저 나열된다.

    참고: 모든 사용자 에이전트가 cookie-list를 이 순서로 정렬하는 것은 아니지만, 이 순서는 이 문서가 작성될 당시의 일반적인 관행을 반영하며, 역사적으로 이 순서에 (잘못) 의존한 서버들이 있었다.

  5. cookie-list 안의 각 쿠키의 last-access-time을 현재 날짜와 시간으로 업데이트한다.

  6. cookie-list의 각 쿠키를 순서대로 처리하여 cookie-list를 cookie-string으로 직렬화한다:

    1. 쿠키의 name이 비어 있지 않으면, 쿠키의 name 뒤에 %x3D("=") 문자를 출력한다.

    2. 쿠키의 value가 비어 있지 않으면, 쿠키의 value를 출력한다.

    3. 쿠키가 cookie-list의 마지막 쿠키가 아니면, 문자 %x3B 및 %x20("; ")을 출력한다.

6. 구현 고려사항

6.1. 제한

실제 사용자 에이전트 구현에는 저장할 수 있는 쿠키의 수와 크기에 제한이 있다. 범용 사용자 에이전트는 다음 최소 기능을 각각 제공하는 것이 좋다(SHOULD):

  • 도메인당 최소 50개의 쿠키.

  • 총 최소 3000개의 쿠키.

사용자 에이전트는 저장하는 쿠키의 최대 수를 제한할 수 있으며, 언제든 어떤 쿠키든 제거할 수 있다(사용자의 요청에 의해서든 구현 제한 때문이든).

쿠키 최대 수에 대한 제한은 저장된 쿠키의 총 크기도 제한한다는 점에 유의하라. 이는 5.6절에서 반드시 적용되어야 하는 길이 제한 때문이다.

서버는 이러한 구현 제한에 도달하는 것을 피하고, 모든 요청에 Cookie 헤더 필드가 포함됨으로 인한 네트워크 대역폭을 최소화하며, 서버 헤더 필드 제한에 도달하는 것을 피하기 위해 가능한 한 적고 작은 쿠키를 사용하는 것이 좋다(SHOULD)(4.2.1절 참조).

사용자 에이전트가 언제든 어떤 쿠키든 제거할 수 있으므로, 사용자 에이전트가 Cookie 헤더 필드에서 하나 이상의 쿠키를 반환하지 못하는 경우 서버는 우아하게 성능을 낮추는 것이 좋다(SHOULD).

6.2. 응용 프로그래밍 인터페이스

Cookie 및 Set-Cookie 헤더 필드가 이처럼 난해한 처리를 사용하는 한 가지 이유는, 많은 플랫폼(서버와 사용자 에이전트 모두)이 쿠키에 대해 문자열 기반 응용 프로그래밍 인터페이스(API)를 제공하여, 애플리케이션 계층 프로그래머가 Cookie 및 Set-Cookie 헤더 필드에서 사용하는 구문을 생성하고 파싱해야 하기 때문이다. 많은 프로그래머가 이를 잘못 처리했고, 그 결과 상호운용성 문제가 발생했다.

쿠키에 문자열 기반 API를 제공하는 대신, 플랫폼은 더 의미론적인 API를 제공하는 것이 유리할 것이다. 특정 API 설계를 권장하는 것은 이 문서의 범위를 벗어나지만, 직렬화된 날짜 문자열 대신 추상적인 "Date" 객체를 수락하는 데는 분명한 이점이 있다.

7. 개인정보 보호 고려사항

쿠키의 주요 개인정보 보호 위험은 사용자 활동을 상관시킬 수 있는 능력이다. 이는 단일 사이트에서 발생할 수 있지만, 겉보기에 서로 연결되지 않은 여러 웹사이트에서 활동을 추적하여 사용자 프로파일을 만들 때 가장 문제가 된다.

시간이 지나면서, 이 능력([RFC2109] 및 그 모든 후속 문서에서 명시적으로 경고한 것)은 다음을 포함한 다양한 이유로 널리 사용되게 되었다:

쿠키의 모든 사용이 반드시 개인정보 보호에 문제가 되는 것은 아니지만, 남용 가능성은 인터넷 커뮤니티와 더 넓은 사회에서 광범위한 우려가 되었다. 이러한 우려에 대응하여 사용자 에이전트는 (이전 명세에서 허용하고 권장한 대로) 여러 방식으로 쿠키 기능을 적극적으로 제한해 왔으며, 동시에 웹의 건강에 바람직하다고 판단하는 기능의 중단은 피하고 있다.

쿠키의 개인정보 보호 영향을 완화하는 데 어떤 특정 메커니즘을 사용해야 하는지에 대한 합의를 선언하기에는 아직 이르다. 사용자 에이전트가 쿠키 처리 방식을 계속 변경하는 것은 최종 합의에 입력을 제공할 수 있는 실험으로 보는 것이 가장 적절하다.

대신 이 문서는 작성 시점에 널리 배포되어 있는, 쿠키와 관련된 개인정보 보호 위험에 대한 제한적이고 일반적인 완화책을 설명한다. 구현은 시간이 지나면서 쿠키에 대해 더 엄격하고 더 잘 정의된 제한을 계속 실험하고 부과할 것으로 예상된다. 이 문서의 향후 버전은 배포 경험을 바탕으로 그러한 메커니즘을 성문화할 수 있다. 현재 쿠키에 의존하는 기능을 별도의 대상화된 메커니즘으로 지원할 수 있다면, 별도의 명세에 문서화될 수 있고 쿠키에 대한 더 엄격한 제한이 가능해질 수 있다.

쿠키가 사이트 간 사용자를 추적하는 데 사용할 수 있는 유일한 메커니즘은 아니므로, 이러한 완화책은 웹 개인정보 보호를 개선하는 데 필요하지만 그 자체만으로는 충분하지 않다는 점에 유의하라.

7.1. 제3자 쿠키

"third-party" 또는 cross-site 쿠키는 기본 리소스(보통 사용자가 보고 있는 웹 페이지)를 호스팅하는 서버와 다른 서버에서 얻은 삽입된 콘텐츠(예: scripts, images, stylesheets, frames)와 관련된 쿠키이다. 제3자 쿠키는 흔히 서로 다른 사이트에서 사용자의 활동을 상관시키는 데 사용된다.

고유한 개인정보 보호 문제 때문에, 대부분의 사용자 에이전트는 이제 다양한 방식으로 제3자 쿠키를 제한한다. 일부는 제3자 Set-Cookie 헤더 필드 처리를 거부하고 제3자 Cookie 헤더 필드 전송을 거부하여 제3자 쿠키를 완전히 차단한다. 일부는 first-party 컨텍스트에 따라 쿠키를 분할하여, 탐색 중인 사이트에 따라 서로 다른 쿠키가 전송되게 한다. 일부는 사용자 에이전트 쿠키 정책 및/또는 사용자 제어에 따라 쿠키를 차단한다.

이 문서는 특정 접근 방식을 지지하거나 요구하지 않지만, 사용자 에이전트가 호환성 제약이 허용하는 한 가능한 한 제한적인 제3자 쿠키 정책을 채택할 것을 권장한다(RECOMMENDED). 따라서 리소스는 예측 가능한 미래 동안 사용자 에이전트가 제3자 쿠키를 일관되게 처리할 것이라고 의존할 수 없다.

7.3. 사용자 제어

사용자 에이전트는 쿠키 저장소에 저장된 쿠키를 관리하기 위한 메커니즘을 사용자에게 제공하는 것이 좋다(SHOULD). 예를 들어, 사용자 에이전트는 지정된 기간 동안 수신된 모든 쿠키 또는 특정 도메인과 관련된 모든 쿠키를 사용자가 삭제할 수 있게 할 수 있다. 또한 많은 사용자 에이전트는 사용자가 쿠키 저장소에 저장된 쿠키를 검사할 수 있게 하는 사용자 인터페이스 요소를 포함한다.

사용자 에이전트는 쿠키를 비활성화하기 위한 메커니즘을 사용자에게 제공하는 것이 좋다(SHOULD). 쿠키가 비활성화되면, 사용자 에이전트는 나가는 HTTP 요청에 Cookie 헤더 필드를 포함해서는 안 되며(MUST NOT), 들어오는 HTTP 응답의 Set-Cookie 헤더 필드를 처리해서는 안 된다(MUST NOT).

사용자 에이전트는 쿠키 정책을 변경할 수 있는 방법을 제공할 수 있다(MAY) (7.2절 참조).

사용자 에이전트는 세션 간 쿠키의 영구 저장을 방지하는 옵션을 사용자에게 제공할 수 있다(MAY). 이렇게 구성된 경우, 사용자 에이전트는 수신한 모든 쿠키를 persistent-flag가 false로 설정된 것처럼 취급해야 한다(MUST). 일부 인기 있는 사용자 에이전트는 이 기능을 "private browsing" 모드 [Aggarwal2010]를 통해 노출한다.

7.4. 만료 날짜

서버가 쿠키의 만료 날짜를 먼 미래로 설정할 수는 있지만, 대부분의 사용자 에이전트는 실제로 여러십 년 동안 쿠키를 유지하지 않는다. 불필요하게 긴 만료 기간을 선택하기보다, 서버는 쿠키의 목적에 따라 합리적인 쿠키 만료 기간을 선택하여 사용자의 개인정보 보호를 증진하는 것이 좋다(SHOULD). 예를 들어, 일반적인 세션 식별자는 2주 후에 만료되도록 설정하는 것이 합리적일 수 있다.

8. 보안 고려사항

8.1. 개요

쿠키에는 여러 보안상 함정이 있다. 이 절은 그중 몇 가지 더 두드러진 문제를 개관한다.

특히 쿠키는 개발자가 인증을 위해 주변 권한에 의존하도록 장려하여, 종종 cross-site request forgery [CSRF]와 같은 공격에 취약해진다. 또한 개발자는 세션 식별자를 쿠키에 저장할 때 세션 고정 취약점을 만드는 경우가 많다.

HTTPS에서 사용되는 것과 같은 전송 계층 암호화는 쿠키에 대한 네트워크 공격에 대해 상당한 방어 계층을 제공한다. 그러나 쿠키 프로토콜 자체의 본질적인 취약점 때문에 네트워크 공격자가 피해자의 쿠키를 얻거나 변경하는 것을 완전히 방지하기에는 충분하지 않다(아래의 "약한 기밀성" 및 "약한 무결성" 참조). 또한 기본적으로 쿠키는 HTTPS와 함께 사용되더라도 네트워크 공격자로부터의 기밀성이나 무결성을 제공하지 않는다. 이는 쿠키가 보호 속성을 명시적으로 지정해야 함을 의미한다. 예를 들어, 다음 쿠키는:

Set-Cookie: a=b

Secure 속성을 지정하지 않으므로, 생성된 원래 연결 유형과 관계없이 보안 연결과 비보안 연결 모두에서 접근 가능하다. 이러한 동작은 공격자가 쿠키를 읽거나 수정할 수 있게 할 수 있다.

8.2. 주변 권한

사용자를 인증하기 위해 쿠키를 사용하는 서버는 보안 취약점을 겪을 수 있다. 일부 사용자 에이전트가 원격 당사자가 사용자 에이전트에서 HTTP 요청을 발행할 수 있게 하기 때문이다(예: HTTP 리다이렉트 또는 HTML 양식을 통해). 이러한 요청을 발행할 때, 사용자 에이전트는 원격 당사자가 쿠키의 내용을 알지 못하더라도 쿠키를 첨부하며, 이로 인해 원격 당사자가 부주의한 서버에서 권한을 행사할 수 있게 될 수 있다.

이 보안 우려는 여러 이름(예: cross-site request forgery, confused deputy)으로 불리지만, 문제는 쿠키가 주변 권한의 한 형태라는 데서 비롯된다. 쿠키는 서버 운영자가 지정(URL 형식)과 권한 부여(쿠키 형식)를 분리하도록 장려한다. 그 결과 사용자 에이전트는 공격자가 지정한 리소스에 대해 권한 부여를 제공할 수 있으며, 서버 또는 그 클라이언트가 마치 사용자가 권한을 부여한 것처럼 공격자가 지정한 작업을 수행하게 할 수 있다.

권한 부여에 쿠키를 사용하는 대신, 서버 운영자는 URL을 capability로 취급하여 지정과 권한 부여를 얽어 두는 방식을 고려할 수 있다. 이 접근법은 비밀을 쿠키에 저장하는 대신 URL에 저장하여, 원격 엔터티가 비밀 자체를 제공하도록 요구한다. 이 접근법이 만병통치약은 아니지만, 이러한 원칙을 신중하게 적용하면 더 견고한 보안으로 이어질 수 있다.

8.3. 평문

보안 채널(예: TLS [TLS13])을 통해 전송되지 않는 한, Cookie 및 Set-Cookie 헤더 필드의 정보는 평문으로 전송된다.

  1. 이러한 헤더 필드로 전달되는 모든 민감한 정보는 도청자에게 노출된다.

  2. 악의적인 중개자가 어느 방향으로든 이동하는 동안 헤더 필드를 변경할 수 있으며, 그 결과는 예측할 수 없다.

서버는 쿠키를 사용자 에이전트로 전송할 때(보안 채널을 통해 쿠키를 보내는 경우에도) 쿠키의 내용을 암호화하고 서명하는 것이 좋다(SHOULD)(서버가 원하는 어떤 형식이든 사용). 그러나 쿠키 내용을 암호화하고 서명하더라도 공격자가 한 사용자 에이전트에서 다른 사용자 에이전트로 쿠키를 이식하거나 나중에 쿠키를 재생하는 것을 방지하지는 못한다.

모든 쿠키의 내용을 암호화하고 서명하는 것에 더하여, 더 높은 수준의 보안을 요구하는 서버는 보안 채널에서만 Cookie 및 Set-Cookie 헤더 필드를 사용하는 것이 좋다(SHOULD). 보안 채널에서 쿠키를 사용할 때, 서버는 모든 쿠키에 Secure 속성(4.1.2.5절 참조)을 설정하는 것이 좋다(SHOULD). 서버가 Secure 속성을 설정하지 않으면, 보안 채널이 제공하는 보호는 대체로 무의미해진다.

예를 들어, 세션 식별자를 쿠키에 저장하고 일반적으로 HTTPS를 통해 접근되는 웹메일 서버를 생각해 보자. 서버가 쿠키에 Secure 속성을 설정하지 않으면, 능동적 네트워크 공격자는 사용자 에이전트에서 나가는 모든 HTTP 요청을 가로채어 그 요청을 HTTP를 통해 웹메일 서버로 리다이렉트할 수 있다. 웹메일 서버가 HTTP 연결을 수신하지 않더라도, 사용자 에이전트는 여전히 요청에 쿠키를 포함한다. 능동적 네트워크 공격자는 이러한 쿠키를 가로채고 서버에 대해 재생하여 사용자의 이메일 내용을 알 수 있다. 반대로 서버가 쿠키에 Secure 속성을 설정했다면, 사용자 에이전트는 평문 요청에 쿠키를 포함하지 않았을 것이다.

8.4. 세션 식별자

세션 정보를 쿠키에 직접 저장하는 대신(그 정보가 공격자에게 노출되거나 재생될 수 있음), 서버는 일반적으로 nonce(또는 "session identifier")를 쿠키에 저장한다. 서버가 nonce가 포함된 HTTP 요청을 받으면, 서버는 nonce를 키로 사용하여 쿠키와 관련된 상태 정보를 조회할 수 있다.

세션 식별자 쿠키를 사용하면, 공격자가 쿠키의 내용을 알게 되더라도 공격자가 초래할 수 있는 피해가 제한된다. nonce는 서버와 상호작용하는 데에만 유용하기 때문이다(nonce가 아닌 쿠키 내용은 그 자체로 민감할 수 있음). 더 나아가 단일 nonce를 사용하면, 공격자가 서버와의 두 상호작용에서 얻은 쿠키 내용을 "splicing"하여 서버가 예기치 않게 동작하게 하는 것을 방지한다.

세션 식별자를 사용하는 데 위험이 없는 것은 아니다. 예를 들어, 서버는 "session fixation" 취약점을 피하도록 주의하는 것이 좋다(SHOULD). 세션 고정 공격은 세 단계로 진행된다. 첫째, 공격자는 자신의 사용자 에이전트에서 피해자의 사용자 에이전트로 세션 식별자를 이식한다. 둘째, 피해자는 그 세션 식별자를 사용해 서버와 상호작용하며, 세션 식별자에 사용자의 자격 증명이나 기밀 정보를 부여할 수 있다. 셋째, 공격자는 그 세션 식별자를 사용해 서버와 직접 상호작용하여 사용자의 권한 또는 기밀 정보를 얻을 수 있다.

8.5. 약한 기밀성

쿠키는 포트별 격리를 제공하지 않는다. 한 포트에서 실행되는 서비스가 쿠키를 읽을 수 있으면, 같은 서버의 다른 포트에서 실행되는 서비스도 그 쿠키를 읽을 수 있다. 한 포트의 서비스가 쿠키를 쓸 수 있으면, 같은 서버의 다른 포트에서 실행되는 서비스도 그 쿠키를 쓸 수 있다. 이러한 이유로 서버는 같은 호스트의 서로 다른 포트에서 서로 신뢰하지 않는 서비스를 동시에 실행하면서 보안에 민감한 정보를 저장하는 데 쿠키를 사용하지 않는 것이 좋다(SHOULD NOT).

쿠키는 scheme별 격리를 제공하지 않는다. 가장 흔히 http 및 https scheme과 함께 사용되지만, 주어진 호스트의 쿠키는 ftp 및 gopher와 같은 다른 scheme에서도 사용 가능할 수 있다. 이러한 scheme별 격리 부재는 쿠키 접근을 허용하는 비HTTP API(예: HTML의 document.cookie API)에서 가장 분명하지만, scheme별 격리 부재는 실제로 쿠키 자체를 처리하기 위한 요구사항에도 존재한다 (예: HTTP를 통해 gopher scheme의 URI를 검색하는 경우를 생각해 보라).

쿠키는 항상 path별 격리를 제공하지는 않는다. 네트워크 수준 프로토콜은 한 path에 저장된 쿠키를 다른 path로 보내지 않지만, 일부 사용자 에이전트는 HTML의 document.cookie API와 같은 비HTTP API를 통해 쿠키를 노출한다. 이러한 사용자 에이전트 중 일부(예: 웹 브라우저)는 서로 다른 path에서 받은 리소스를 격리하지 않기 때문에, 한 path에서 검색된 리소스가 다른 path에 저장된 쿠키에 접근할 수 있을 수 있다.

8.6. 약한 무결성

쿠키는 형제 도메인(및 그 하위 도메인)에 대한 무결성 보장을 제공하지 않는다. 예를 들어 foo.site.example과 bar.site.example을 생각해 보자. foo.site.example 서버는 Domain 속성이 "site.example"인 쿠키를 설정할 수 있으며 (bar.site.example이 설정한 기존 "site.example" 쿠키를 덮어쓸 수도 있음), 사용자 에이전트는 bar.site.example에 대한 HTTP 요청에 그 쿠키를 포함한다. 최악의 경우 bar.site.example은 이 쿠키를 자신이 직접 설정한 쿠키와 구별할 수 없다. foo.site.example 서버는 이 능력을 이용하여 bar.site.example에 대한 공격을 수행할 수 있을 수 있다.

Set-Cookie 헤더 필드가 Path 속성을 지원하더라도, Path 속성은 무결성 보호를 제공하지 않는다. 사용자 에이전트가 Set-Cookie 헤더 필드 안의 임의의 Path 속성을 수락하기 때문이다. 예를 들어 http://site.example/foo/bar에 대한 요청의 HTTP 응답은 Path 속성이 "/qux"인 쿠키를 설정할 수 있다. 따라서 서버는 같은 호스트의 서로 다른 path에서 서로 신뢰하지 않는 서비스를 동시에 실행하면서 보안에 민감한 정보를 저장하는 데 쿠키를 사용하지 않는 것이 좋다(SHOULD NOT).

능동적 네트워크 공격자는 http://site.example/의 응답을 가장하고 Set-Cookie 헤더 필드를 삽입함으로써 https://site.example/로 전송되는 Cookie 헤더 필드에 쿠키를 주입할 수도 있다. site.example의 HTTPS 서버는 이러한 쿠키를 자신이 HTTPS 응답에서 직접 설정한 쿠키와 구별할 수 없다. 능동적 네트워크 공격자는 site.example이 HTTPS만 사용하더라도 이 능력을 이용하여 site.example에 대한 공격을 수행할 수 있을 수 있다.

서버는 쿠키의 내용을 암호화하고 서명하거나 쿠키 이름에 __Secure- 접두사를 붙여 이러한 공격을 부분적으로 완화할 수 있다. 그러나 암호화를 사용하더라도 문제가 완전히 완화되지는 않는다. 공격자가 진짜 site.example 서버에서 받은 쿠키를 사용자의 세션에서 재생할 수 있으며, 그 결과는 예측할 수 없기 때문이다.

마지막으로, 공격자는 많은 수의 쿠키를 저장하여 사용자 에이전트가 쿠키를 삭제하도록 강제할 수 있을 수 있다. 사용자 에이전트가 저장 제한에 도달하면, 사용자 에이전트는 일부 쿠키를 제거할 수밖에 없다. 서버는 사용자 에이전트가 쿠키를 유지할 것이라고 의존해서는 안 된다(SHOULD NOT).

8.7. DNS에 대한 의존

쿠키는 보안을 위해 Domain Name System(DNS)에 의존한다. DNS가 부분적으로 또는 완전히 손상되면, 쿠키 프로토콜은 애플리케이션이 요구하는 보안 속성을 제공하지 못할 수 있다.

8.8. SameSite 쿠키

8.8.1. 심층 방어

"SameSite" 쿠키는 strict 모드로 배포되고 클라이언트가 이를 지원할 때 CSRF 공격에 대한 견고한 방어를 제공한다. 그러나 same-site 탐색과 제출은 cross-site scripting 또는 페이지 리다이렉션 악용과 같은 다른 공격 벡터와 함께 실행될 수 있으므로, 이 지정이 사이트의 CSRF 방어 전부가 되지 않도록 보장하는 것이 신중하다.

요청이 언제 어떻게 same-site로 간주되는지 이해하는 것도 SameSite 쿠키를 위한 사이트를 적절히 설계하는 데 중요하다. 예를 들어, 민감한 페이지에 대해 cross-site 최상위 요청이 이루어지면 그 요청은 cross-site로 간주되고 SameSite=Strict 쿠키는 전송되지 않는다. 그러나 그 페이지의 하위 리소스 요청은 same-site이며 SameSite=Strict 쿠키를 받게 된다. 사이트는 적절한 쿠키가 포함되어 있지 않은 경우 초기 페이지 요청에 대해 오류를 반환함으로써, 이러한 하위 리소스에 대한 접근을 의도치 않게 허용하는 것을 피할 수 있다.

개발자는 위험을 더 완전하게 완화하기 위해 일반적인 서버 측 방어(CSRF 토큰, "safe" HTTP 메서드가 멱등적임을 보장하는 것 등)를 배포할 것을 강하게 권장한다.

또한 [app-isolation]에 설명된 것과 같은 클라이언트 측 기법도 CSRF에 효과적일 수 있으며, "SameSite" 쿠키와 결합하여 탐색해 볼 가치가 있다.

8.8.2. 최상위 탐색

SameSite 속성을 "strict" 모드로 설정하면 CSRF 공격에 대한 견고한 심층 방어를 제공하지만, 사이트 개발자가 쿠키 기반 세션 관리 시스템이 최상위 탐색을 합리적으로 잘 처리하도록 신중하게 보장하지 않으면 사용자를 혼란스럽게 할 가능성이 있다.

사용자가 MegaCorp Inc의 웹메일 제공자 https://site.example/에서 이메일을 읽는 시나리오를 생각해 보자. 사용자는 이메일로 받은 https://projects.example/secret/project 링크를 클릭하면 자신이 볼 권한이 있는 비밀 프로젝트가 표시될 것이라고 기대할 수 있다. 그러나 https://projects.example가 세션 쿠키를 SameSite=Strict로 표시했다면, 이 cross-site 탐색은 요청과 함께 쿠키를 보내지 않는다. https://projects.example는 비밀 정보 유출을 피하기 위해 404 오류를 렌더링하고, 사용자는 상당히 혼란스러울 것이다.

개발자는 하나가 아니라 두 개의 쿠키에 의존하는 세션 관리 시스템을 채택하여 이러한 혼란을 피할 수 있다. 하나는 개념적으로 "read" 접근을 부여하고, 다른 하나는 "write" 접근을 부여한다. 후자는 SameSite=Strict로 표시할 수 있으며, 그 부재는 멱등적이지 않은 작업을 실행하기 전에 재인증 단계를 유도할 수 있다. 전자는 사용자가 최상위 탐색을 통해 데이터에 접근할 수 있도록 SameSite=Lax로 표시하거나, 모든 컨텍스트(cross-site 임베디드 컨텍스트 포함)에서 접근을 허용하기 위해 SameSite=None으로 표시할 수 있다.

8.8.3. 매시업과 위젯

SameSite 속성의 LaxStrict 값은 일부 중요한 사용 사례에 적합하지 않다. 특히 cross-site 컨텍스트에 삽입되도록 의도된 콘텐츠(예: 소셜 네트워킹 위젯 또는 댓글 서비스)는 same-site 쿠키에 접근할 수 없다는 점에 유의하라. 이러한 상황에서 필요한 쿠키는 cross-site 컨텍스트에서 접근을 허용하기 위해 SameSite=None으로 표시해야 한다.

마찬가지로, 일부 Single-Sign-On 형태는 cross-site 컨텍스트에서 쿠키 기반 인증을 필요로 할 수 있다. 이러한 메커니즘은 same-site 쿠키로는 의도한 대로 동작하지 않으며, 역시 SameSite=None을 필요로 한다.

8.8.4. 서버 제어

SameSite 쿠키 자체는 [RFC6265]의 7.1절에 개략적으로 설명된 일반적인 개인정보 보호 우려를 해결하지 않는다. "SameSite" 속성은 서버가 설정하며, 서버가 우려하는 특정 종류의 공격 위험을 완화하는 역할을 한다. 사용자는 이 결정에 관여하지 않는다. 또한 쿠키가 없더라도 서버가 서로 다른 요청을 연결할 수 있게 하는 여러 사이드 채널이 존재한다 (예: same-site 요청과 cross-site 요청 사이의 연결 및/또는 소켓 풀링).

8.8.5. 새로고침 탐색

사용자 인터페이스 요소(예: 도구 모음의 새로고침 버튼)를 통해 트리거된 새로고침을 위해 발행된 요청은, 새로고침되는 문서가 원래 same-site 요청을 통해 탐색된 경우에만 same-site이다. 이는 다른 새로고침 탐색의 처리와 다르다. 다른 새로고침 탐색은 최상위인 경우 항상 same-site인데, source navigable의 active document가 정확히 새로고침되는 문서이기 때문이다.

사용자 인터페이스 요소를 통해 트리거된 새로고침에 대한 이러한 특별 처리는, 원래 탐색에서 SameSite 쿠키가 보류되었다면(즉, 초기 탐색이 cross-site였다면) 사용자가 시작한 새로고침에서 SameSite 쿠키를 보내지 않도록 피한다. 새로고침 탐색이 대신 same-site로 간주되어 처음에 보류된 모든 SameSite 쿠키를 보낸다면, 애초에 쿠키를 보류한 보안상의 이점은 무효화될 것이다. 이는 cross-site 탐색 요청에서 보류된 SameSite 쿠키의 부재가 눈에 보이는 사이트 파손으로 이어져 사용자가 새로고침을 트리거하게 할 수 있다는 점에서 특히 중요하다.

예를 들어, 사용자가 https://attacker.example/의 링크를 클릭하여 https://victim.example/로 이동한다고 가정하자. 이는 cross-site 요청이므로 SameSite=Strict 쿠키는 보류된다. 특정 SameSite 쿠키가 요청에 있어야만 사이트가 민감한 콘텐츠를 표시하기 때문에, 이로 인해 https://victim.example/가 깨진 것처럼 보인다고 가정하자. 예기치 않게 깨진 사이트에 좌절한 사용자가 브라우저 도구 모음의 새로고침을 누른다. 이제 새로고침 요청을 same-site로 간주하고 처음에 보류된 SameSite 쿠키를 보내는 것은 애초에 그것을 보류한 목적을 무너뜨릴 것이다. 사용자 인터페이스를 통해 트리거된 새로고침 탐색은 원래의(잠재적으로 악의적인) 요청을 재생할 수 있기 때문이다. 따라서 새로고침 요청은 처음 페이지로 탐색한 요청과 마찬가지로 cross-site로 간주되어야 한다.

사용자가 시작하지 않은 새로고침을 위해 발행된 요청은 모든 SameSite 쿠키를 첨부하므로, 개발자는 CSRF 공격을 피하기 위해 언제 새로고침을 시작할지 신중하고 사려 깊게 결정해야 한다. 예를 들어, 페이지는 초기 요청에 CSRF 토큰이 있는 경우에만 새로고침을 시작할 수 있다.

8.8.6. "unsafe" 메서드를 사용하는 최상위 요청

5.6.7.1절에 설명된 "Lax" enforcement mode는 cross-site HTTP 요청이 "safe" HTTP 메서드를 사용하는 최상위 탐색인 경우, 그리고 오직 그 경우에만 쿠키가 전송되도록 허용한다. 구현 경험에 따르면 이를 기본 동작으로 적용하기는 어렵다. 일부 사이트는 SameSite 속성을 명시적으로 지정하지 않은 쿠키가 "unsafe" HTTP 메서드를 사용하는 최상위 cross-site 요청에 포함되는 것에 의존할 수 있기 때문이다(SameSite 속성이 도입되기 전의 경우와 같음).

예를 들어, 로그인 흐름의 마지막 단계에는 엔드포인트에 대한 cross-site 최상위 POST 요청이 포함될 수 있다. 이 엔드포인트는 로그인을 안전하게 완료하는 데 필요한 트랜잭션 상태 정보를 포함하는 최근에 생성된 쿠키를 기대한다. 이러한 쿠키에 대해 "Lax" enforcement는 적절하지 않다. 안전하지 않은 HTTP 요청 메서드 때문에 쿠키가 제외되어 전체 로그인 흐름의 복구 불가능한 실패로 이어질 것이기 때문이다.

5.6.7.2절에 설명된 "Lax-allowing-unsafe" enforcement mode는 "Lax" enforcement의 일부 보호("None"과 비교했을 때)를 유지하면서도, 최근에 생성된 쿠키가 안전하지 않은 최상위 요청과 함께 cross-site로 전송될 수 있게 한다.

"Lax" 모드의 더 관대한 변형으로서, "Lax-allowing-unsafe" 모드는 필연적으로 CSRF에 대해 더 적은 보호를 제공한다. 궁극적으로 이러한 enforcement mode의 제공은 기본적으로 "Lax" enforcement를 채택하기 쉽게 하기 위한 임시적·전환적 조치로 보아야 한다.

8.9. 공개 접미사 목록

쿠키의 경계는 사이트의 "registrable domain"에 의존하며, 이는 다시 도메인의 public suffix에 의존한다.

가능할 때마다, 사용자 에이전트는 [PSL]에 있는 Mozilla 프로젝트가 유지 관리하는 것과 같은 최신 public suffix list를 사용하는 것이 좋다(SHOULD).

그렇게 하지 않으면 악의적이거나 민감한 쿠키가 registrable domain 사이에서 누출될 수 있다.

9. IANA 고려사항

10. 참고문헌

10.1. 규범 참고문헌

van Kesteren, A., Denicola, D., Farolino, D., Hickson, I., Jägenstedt, P., and S. Pieters, "HTML - Living Standard", 일자 없음, <https://html.spec.whatwg.org/#dom-document-cookie>. WHATWG
[HTTP]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/rfc/rfc9110>.
[RFC1034]
Mockapetris, P., "Domain names - concepts and facilities", STD 13, RFC 1034, DOI 10.17487/RFC1034, , <https://www.rfc-editor.org/rfc/rfc1034>.
[RFC1123]
Braden, R., Ed., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, DOI 10.17487/RFC1123, , <https://www.rfc-editor.org/rfc/rfc1123>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC4790]
Newman, C., Duerst, M., and A. Gulbrandsen, "Internet Application Protocol Collation Registry", RFC 4790, DOI 10.17487/RFC4790, , <https://www.rfc-editor.org/rfc/rfc4790>.
[RFC5234]
Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, , <https://www.rfc-editor.org/rfc/rfc5234>.
[RFC5890]
Klensin, J., "Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework", RFC 5890, DOI 10.17487/RFC5890, , <https://www.rfc-editor.org/rfc/rfc5890>.
[RFC6454]
Barth, A., "The Web Origin Concept", RFC 6454, DOI 10.17487/RFC6454, , <https://www.rfc-editor.org/rfc/rfc6454>.
[RFC8126]
Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/rfc/rfc8126>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[SAMESITE]
van Kesteren, A., Denicola, D., Farolino, D., Hickson, I., Jägenstedt, P., and S. Pieters, "HTML Living Standard", 일자 없음, <https://html.spec.whatwg.org/#same-site>. WHATWG
[USASCII]
American National Standards Institute, "Coded Character Set -- 7-bit American Standard Code for Information Interchange", ANSI X3.4, .

10.2. 정보 참고문헌

[Aggarwal2010]
Aggarwal, G., Burzstein, E., Jackson, C., and D. Boneh, "An Analysis of Private Browsing Modes in Modern Browsers", , <http://www.usenix.org/events/sec10/tech/full_papers/Aggarwal.pdf>.
[app-isolation]
Chen, E., Bau, J., Reis, C., Barth, A., and C. Jackson, "App Isolation - Get the Security of Multiple Browsers with Just One", , <http://www.collinjackson.com/research/papers/appisolation.pdf>.
[CSRF]
Barth, A., Jackson, C., and J. Mitchell, "Robust Defenses for Cross-Site Request Forgery", DOI 10.1145/1455770.1455782, ISBN 978-1-59593-810-7, ACM CCS '08: Proceedings of the 15th ACM conference on Computer and communications security (pages 75-88), , <http://portal.acm.org/citation.cfm?id=1455770.1455782>.
[FETCH]
van Kesteren, A., "Fetch Living Standard", 일자 없음, <https://fetch.spec.whatwg.org/>. WHATWG
[HTML]
van Kesteren, A., Denicola, D., Farolino, D., Hickson, I., Jägenstedt, P., and S. Pieters, "HTML Living Standard", 일자 없음, <https://html.spec.whatwg.org/>. WHATWG
[HttpFieldNameRegistry]
"Hypertext Transfer Protocol (HTTP) Field Name Registry", 일자 없음, <https://www.iana.org/assignments/http-fields/>.
[prerendering]
Bentzel, C., "Chrome Prerendering", 일자 없음, <https://www.chromium.org/developers/design-documents/prerender>.
[PSL]
"Public Suffix List", 일자 없음, <https://publicsuffix.org/list/>.
[RFC2109]
Kristol, D. and L. Montulli, "HTTP State Management Mechanism", RFC 2109, DOI 10.17487/RFC2109, , <https://www.rfc-editor.org/rfc/rfc2109>.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/rfc/rfc4648>.
[RFC6265]
Barth, A., "HTTP State Management Mechanism", RFC 6265, DOI 10.17487/RFC6265, , <https://www.rfc-editor.org/rfc/rfc6265>.
[RFC7034]
Ross, D. and T. Gondrom, "HTTP Header Field X-Frame-Options", RFC 7034, DOI 10.17487/RFC7034, , <https://www.rfc-editor.org/rfc/rfc7034>.
[RFC9113]
Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, DOI 10.17487/RFC9113, , <https://www.rfc-editor.org/rfc/rfc9113>.
[RFC9114]
Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, , <https://www.rfc-editor.org/rfc/rfc9114>.
[SERVICE-WORKERS]
Archibald, J. and M. Kruisselbrink, "Service Workers", 일자 없음, <https://www.w3.org/TR/service-workers/>.
[TLS13]
Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/rfc/rfc8446>.

부록 A. RFC 6265로부터의 변경사항

감사의 말

RFC 6265는 Adam Barth가 작성했다. 이 문서는 RFC 6265의 업데이트로, 기능을 추가하고 명세를 오늘날 배포 현실에 맞춘다. 여기에서 우리는 거인의 어깨 위에 서 있다. 텍스트의 대부분은 여전히 Adam의 것이기 때문이다.

이 초안을 개선하는 데 상당한 기여를 한 명예 편집자인 Lily Chen과 Steven Englehardt 두 분께 감사드린다.

저자 주소

Steven Bingler (편집자)
Mike West (편집자)
Google LLC
John Wilander (편집자)
Apple, Inc