init: llm-wiki-haness 하네스 설계
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: official-doc / MDN — Set-Cookie SameSite Attribute (Strict / Lax / None Semantics)
|
||||
source_type: official-doc
|
||||
url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie
|
||||
archive_url: http://web.archive.org/web/20260723032604/https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie
|
||||
related_branches: [feature-keycloak-bff-csrf-samesite-defense]
|
||||
related_projects: []
|
||||
tags: [official-doc, keycloak-patterns, security, auth, http]
|
||||
created: 2026-07-23
|
||||
---
|
||||
|
||||
# official-doc / MDN — Set-Cookie SameSite Attribute (Strict / Lax / None Semantics)
|
||||
|
||||
> Layer: `raw/` — 외부 자료(공식 문서)의 **원문 발췌·출처 기록**.
|
||||
> 본 템플릿은 `raw/official-docs/` 와 `raw/company-tech-blogs/` 두 폴더가 공유.
|
||||
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 `source-summary-template` 형식으로 별도 작성. 원본은 raw에 영구 보관.
|
||||
|
||||
## source_type 허용값
|
||||
|
||||
`official-doc` — 공식 레퍼런스 (MDN Web Docs, `Set-Cookie` HTTP 응답 헤더의 `SameSite` attribute 섹션).
|
||||
|
||||
## Parent / 활용 branch (필수, 최소 1개+)
|
||||
|
||||
| Branch | 이 자료가 정당화하는 결정 |
|
||||
|---|---|
|
||||
| [[raw/branch-notes/feature-keycloak-bff-csrf-samesite-defense]] | D2 — AP3 BFF `SESSION` 쿠키에 어떤 `SameSite` 값(`Strict` / `Lax` / `None`)을 CSRF 방어로 설정할지 결정하는 근거. 이 자료는 `Strict`/`Lax`/`None` 각각의 정확한 전송 semantics(언제 cross-site 요청에 쿠키가 실리고 안 실리는지), `SameSite` 미지정 시 브라우저 기본값(`Lax`), `None` 사용 시 `Secure` 필수 요건을 verbatim 으로 확보한다. |
|
||||
|
||||
## 출처 / Source
|
||||
|
||||
- 원본 URL: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie/SameSite (요청된 원본 URL — **404**, 아래 "왜 저장했는지" 참조)
|
||||
- 실제 확인 URL(사용): https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie (`SameSite` 는 이 통합 `Set-Cookie` reference 문서의 하위 섹션, anchor `#samesitesamesite-value` / `#strict` / `#lax` / `#none`)
|
||||
- 아카이브 URL: http://web.archive.org/web/20260723032604/https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie
|
||||
- 저자 / 조직: MDN Web Docs (Mozilla), 커뮤니티 편집 공식 웹 플랫폼 레퍼런스
|
||||
- 발행일: 페이지에 명시된 발행일 없음 (MDN 은 지속 갱신되는 living reference)
|
||||
- 마지막 확인일: 2026-07-23
|
||||
|
||||
## 왜 저장했는지 / Why archived
|
||||
|
||||
사용자가 요청한 원본 URL `.../Set-Cookie/SameSite` 은 standalone 페이지가 아니라 **404** 를 반환한다(리다이렉트 아님 — `curl -I -L` 확인, HTTP 404 그대로). MDN 최신 정보 구조에서 `SameSite` 는 별도 페이지가 아니라 `Set-Cookie` 헤더 reference 문서 안의 하위 attribute 섹션으로 통합되어 있다. 이 페이지의 `SameSite=<samesite-value>` 섹션(그 안의 `Strict`/`Lax`/`None` sub-definition)을 대신 archive 했다 — `feature-keycloak-bff-csrf-samesite-defense` branch 의 D2(AP3 BFF SESSION 쿠키의 SameSite 값 선택)를 정당화하는 1차 공식 근거.
|
||||
|
||||
## 핵심 인용 / Key quotes (verbatim, 5문장)
|
||||
|
||||
> [§SameSite → Strict] "Send the cookie only for requests originating from the same site that set the cookie."
|
||||
|
||||
> [§SameSite → Lax] "Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:"
|
||||
|
||||
> [§SameSite → Lax, 두 번째 기준] "The request uses a safe method: in particular, this excludes POST, PUT, and DELETE."
|
||||
|
||||
> [§SameSite → None] "Send the cookie with both cross-site and same-site requests.
|
||||
> The Secure attribute must also be set when using this value."
|
||||
|
||||
> [§SameSite → Lax, 기본값 각주] "Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details."
|
||||
|
||||
## Claims Extracted / 추출된 주장
|
||||
|
||||
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
||||
|---|---|---|---|---|---|
|
||||
| MDN-SAMESITE-C1 | `SameSite=Strict` 쿠키는 그 쿠키를 설정한 것과 **같은 site 로부터 발생한 요청에만** 전송된다 — cross-site 요청(최상위 탐색 포함)에는 절대 실리지 않는다. | [§Strict] "Send the cookie only for requests originating from the same site that set the cookie." | `official-reference` | 세션 쿠키에 `SameSite=Strict` 를 적용했을 때의 cross-site 완전 차단 semantics 확인 | 어떤 상황에서 `Strict` 를 써야 하는지(UX trade-off, 외부 링크로 진입 시 로그아웃처럼 보이는 문제)는 이 문장이 직접 다루지 않음 |
|
||||
| MDN-SAMESITE-C2 | `SameSite=Lax` 쿠키는 same-site 요청에는 항상 전송되고, cross-site 요청 중에서는 **두 기준을 모두 만족**하는 경우에만 전송된다(다른 기준은 "top-level navigation" — C3 은 그중 하나인 safe method 기준). | [§Lax] "Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:" | `official-reference` | `Lax` 가 조건부로만 cross-site 전송을 허용한다는 원칙 확인 | "top-level navigation" 자체의 상세 정의(예: `fetch()`/`<img>`/`<iframe>` 은 제외, 링크 클릭/`document.location`/`<form>` 제출은 포함)는 이 인용 자체에는 없음(같은 페이지 다른 문단에 있으나 별도 Claim 으로 분리하지 않음 — 메모 참조) |
|
||||
| MDN-SAMESITE-C3 | `SameSite=Lax` cross-site 허용 기준 중 하나는 "safe" HTTP method 사용이며, `POST`/`PUT`/`DELETE` 는 명시적으로 **제외**된다 — 즉 cross-site `POST` 요청에는 `Lax` 쿠키가 (기본값이 아닌 명시적 `Lax` 로) 실리지 않는다. | [§Lax] "The request uses a safe method: in particular, this excludes POST, PUT, and DELETE." | `official-reference` | cross-site state-changing 요청(POST 기반 CSRF 공격 벡터)에 명시적 `SameSite=Lax` 쿠키가 실리지 않는다는 근거 | 브라우저가 기본값으로 `Lax` 를 적용할 때는 "더 관대한 버전"이 적용되어 예외가 있음(C5 의 각주 참조) — C3 의 배제는 **명시적으로 설정된** `Lax` 에 대한 서술이지, 기본값-`Lax` 의 permissive 예외까지 부정하지 않는다 |
|
||||
| MDN-SAMESITE-C4 | `SameSite=None` 쿠키는 cross-site 와 same-site 요청 모두에 전송되며, 이 값을 사용할 때는 `Secure` attribute 도 **반드시 함께 설정**해야 한다. | [§None] "Send the cookie with both cross-site and same-site requests.\nThe Secure attribute must also be set when using this value." | `official-reference` | `None` 이 CSRF 방어 목적으로는 사용할 수 없는 값이며(cross-site 무조건 전송), 사용 시 `Secure` 가 필수 요건임을 확인 | `Secure` 누락 시 브라우저가 정확히 어떻게 처리하는지(무시/거부 등 구현별 동작)는 이 문장 자체가 규정하지 않음 |
|
||||
| MDN-SAMESITE-C5 | `SameSite` attribute 를 명시하지 않으면 일부 브라우저는 `Lax` 를 기본값으로 취급한다. | [§Lax, 기본값] "Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details." | `official-reference` | `SameSite` 를 생략했을 때의 브라우저 기본 동작(전부는 아니고 "일부 브라우저"라는 단서 포함) | 모든 브라우저가 동일하게 기본값을 적용한다는 뜻은 아님 — 원문이 "Some browsers" 라고 명시하며 Browser compatibility 표를 별도로 참조하라고 안내(이 표 자체는 이번 fetch 범위 밖) |
|
||||
|
||||
### Strength 허용값
|
||||
|
||||
- `official-standard` — RFC, 표준 사양, 언어/프로토콜 표준
|
||||
- `official-vendor-doc` — Spring, Keycloak, AWS, Google 등 공식 벤더 문서
|
||||
- `official-reference` — 공식 reference/API 문서
|
||||
- `company-case-study` — 대기업/실무 기술 블로그의 특정 사례
|
||||
- `engineering-blog` — 개인/팀 블로그의 엔지니어링 해설
|
||||
- `tutorial` — 튜토리얼/가이드. 일반화 금지
|
||||
- `needs-confirmation` — 원문만으로는 적용 판단 불가
|
||||
|
||||
## Usage Boundaries / 적용 경계
|
||||
|
||||
- 이 자료가 직접 증명하는 것:
|
||||
- `MDN-SAMESITE-C1`: `Strict` 는 same-site 요청에만 쿠키를 전송함(cross-site 완전 차단).
|
||||
- `MDN-SAMESITE-C2`/`C3`: `Lax` 는 "top-level navigation" + "safe method(GET 등, POST/PUT/DELETE 제외)" 두 기준을 모두 만족하는 cross-site 요청에만 조건부로 쿠키를 전송함.
|
||||
- `MDN-SAMESITE-C4`: `None` 은 cross-site 포함 모든 요청에 쿠키를 전송하며 `Secure` 가 필수임.
|
||||
- `MDN-SAMESITE-C5`: `SameSite` 미지정 시 일부 브라우저가 `Lax` 를 기본값으로 적용함.
|
||||
- 이 자료가 증명하지 않는 것:
|
||||
- 기본값(암묵적) `Lax` 가 적용될 때의 "더 관대한 버전"(2분 이내 설정된 쿠키는 cross-site `POST` 에도 실림)의 정확한 브라우저별 구현 범위 — 원문에 언급은 있으나 이번 발췌 5개 인용에는 포함하지 않음(메모 참조).
|
||||
- AP3 BFF 세션 쿠키에 실제로 `Strict` 를 선택해야 하는지 `Lax` 를 선택해야 하는지에 대한 권고 — 이 문서는 **각 값의 semantics 만** 정의하며, OIDC redirect 콜백처럼 top-level cross-site 진입이 필요한 흐름과의 상호작용은 branch-note 의 별도 D2 결정 근거(예: OIDC 표준 문서)와 함께 판단해야 함.
|
||||
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
|
||||
- AP3 BFF 의 실제 쿠키 설정 코드(Set-Cookie 헤더 생성 위치)에서 `SameSite`/`Secure` 값이 이 semantics 대로 설정되는지 로컬 검증 필요.
|
||||
|
||||
## 메모 / Notes
|
||||
|
||||
- 원문에는 `Lax` 의 "top-level navigation" 정의에 대한 추가 설명 문단(예: `fetch()`/`<img>`/`<script>`/`<iframe>` 은 제외, 링크 클릭·`document.location`·`<form>` 제출은 포함)과, 기본값 `Lax` 가 적용될 때의 "더 관대한 버전"(2분 이내 설정된 쿠키는 `POST` 에도 포함) 각주가 더 있다. 이번 발췌는 branch D2 결정에 직접 필요한 5개 핵심 문장만 verbatim 으로 확보했다 — 두 세부 사항이 실제로 필요해지면(예: OAuth2/OIDC redirect 콜백이 top-level navigation 인지 판단해야 할 때) 같은 페이지를 재방문해 추가 Claim 을 이 문서에 append 할 것.
|
||||
- (미검증, 인용 아님) top-level navigation 기준 때문에 OIDC Authorization Code redirect(브라우저 최상위 이동 + GET)는 `Lax` 쿠키가 실리는 경우로 보이지만, 이는 이 raw 문서의 인용이 직접 증명하지 않으므로 branch-note 의 D2 본문에서 별도로 검증해야 한다.
|
||||
|
||||
## Related / 관련
|
||||
|
||||
- `raw/official-docs/csrf-prevention-owasp-official` — (검토 후보, 아직 raw 부재) OWASP CSRF Prevention Cheat Sheet — SameSite 는 defense-in-depth 이지 유일한 방어가 아니라는 논지의 근거 후보
|
||||
- 이 자료를 인용한 wiki 요약: (아직 생성 안 됨)
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schema_version": "document-commit/v1",
|
||||
"candidate": {
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/candidate.md",
|
||||
"sha256": "81fe00cc1fb048e3aa8afe255553a73491294f6676f5d204fcede46b8e6944f9"
|
||||
},
|
||||
"target": {
|
||||
"path": "raw/official-docs/samesite-cookie-attribute-mdn-official.md",
|
||||
"must_not_exist": true
|
||||
},
|
||||
"proof_manifest": {
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/proof-manifest.json",
|
||||
"sha256": "9a7dfe5bf9074b500c90a51faed31b6bc4756054a70d2108083f5719cc392619"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"proofs": [
|
||||
{
|
||||
"execution": {
|
||||
"argv": [
|
||||
"proof-runner/exact-utf8-v1",
|
||||
"repo",
|
||||
"harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"94:94"
|
||||
],
|
||||
"exact_match": true,
|
||||
"exit_code": 0,
|
||||
"stdout_sha256": "962ffdf6e80d4084705c99aa00699dad5836429b514772fc5e401e3a0e09821d",
|
||||
"stdout_utf8": "Send the cookie only for requests originating from the same site that set the cookie."
|
||||
},
|
||||
"finding": {
|
||||
"id": "MDN-SAMESITE-C1",
|
||||
"role": "quote"
|
||||
},
|
||||
"source": {
|
||||
"line_end": 94,
|
||||
"line_start": 94,
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie only for requests originating from the same site that set the cookie.",
|
||||
"sha256": "730103fe0c74ccbf31f34d793d1fcb0cd54342b992d3b48732e622f271103e49"
|
||||
}
|
||||
},
|
||||
{
|
||||
"execution": {
|
||||
"argv": [
|
||||
"proof-runner/exact-utf8-v1",
|
||||
"repo",
|
||||
"harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"96:96"
|
||||
],
|
||||
"exact_match": true,
|
||||
"exit_code": 0,
|
||||
"stdout_sha256": "47ffccbd6fa06676ca8391bc2decf6e165246a9f9778ff3e12abfc75d6b97edb",
|
||||
"stdout_utf8": "Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:"
|
||||
},
|
||||
"finding": {
|
||||
"id": "MDN-SAMESITE-C2",
|
||||
"role": "quote"
|
||||
},
|
||||
"source": {
|
||||
"line_end": 96,
|
||||
"line_start": 96,
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:",
|
||||
"sha256": "730103fe0c74ccbf31f34d793d1fcb0cd54342b992d3b48732e622f271103e49"
|
||||
}
|
||||
},
|
||||
{
|
||||
"execution": {
|
||||
"argv": [
|
||||
"proof-runner/exact-utf8-v1",
|
||||
"repo",
|
||||
"harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"100:100"
|
||||
],
|
||||
"exact_match": true,
|
||||
"exit_code": 0,
|
||||
"stdout_sha256": "cf505469eb2b045be635dac31610f8401a9a5b7795fd1b40946749dc51e0b870",
|
||||
"stdout_utf8": "The request uses a safe method: in particular, this excludes POST, PUT, and DELETE."
|
||||
},
|
||||
"finding": {
|
||||
"id": "MDN-SAMESITE-C3",
|
||||
"role": "quote"
|
||||
},
|
||||
"source": {
|
||||
"line_end": 100,
|
||||
"line_start": 100,
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "The request uses a safe method: in particular, this excludes POST, PUT, and DELETE.",
|
||||
"sha256": "730103fe0c74ccbf31f34d793d1fcb0cd54342b992d3b48732e622f271103e49"
|
||||
}
|
||||
},
|
||||
{
|
||||
"execution": {
|
||||
"argv": [
|
||||
"proof-runner/exact-utf8-v1",
|
||||
"repo",
|
||||
"harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"105:106"
|
||||
],
|
||||
"exact_match": true,
|
||||
"exit_code": 0,
|
||||
"stdout_sha256": "3cd8be39b44d32d0cd3e7fb3cf6d655e909a7432d8d7c277f31c7f20159bd6ff",
|
||||
"stdout_utf8": "Send the cookie with both cross-site and same-site requests.\nThe Secure attribute must also be set when using this value."
|
||||
},
|
||||
"finding": {
|
||||
"id": "MDN-SAMESITE-C4",
|
||||
"role": "quote"
|
||||
},
|
||||
"source": {
|
||||
"line_end": 106,
|
||||
"line_start": 105,
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie with both cross-site and same-site requests.\nThe Secure attribute must also be set when using this value.",
|
||||
"sha256": "730103fe0c74ccbf31f34d793d1fcb0cd54342b992d3b48732e622f271103e49"
|
||||
}
|
||||
},
|
||||
{
|
||||
"execution": {
|
||||
"argv": [
|
||||
"proof-runner/exact-utf8-v1",
|
||||
"repo",
|
||||
"harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"101:101"
|
||||
],
|
||||
"exact_match": true,
|
||||
"exit_code": 0,
|
||||
"stdout_sha256": "e66802caf9f4332a22cfc26e5a499679663a0c88d537e6edbd9f2058321d9cb9",
|
||||
"stdout_utf8": "Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details."
|
||||
},
|
||||
"finding": {
|
||||
"id": "MDN-SAMESITE-C5",
|
||||
"role": "quote"
|
||||
},
|
||||
"source": {
|
||||
"line_end": 101,
|
||||
"line_start": 101,
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details.",
|
||||
"sha256": "730103fe0c74ccbf31f34d793d1fcb0cd54342b992d3b48732e622f271103e49"
|
||||
}
|
||||
}
|
||||
],
|
||||
"run": {
|
||||
"id": "wiki-source-summarizer-samesite-mdn-2026-07-23",
|
||||
"profile": "capture"
|
||||
},
|
||||
"schema_version": "proof-manifest/v1",
|
||||
"verification": {
|
||||
"fail_count": 0,
|
||||
"pass_count": 5,
|
||||
"proof_count": 5,
|
||||
"schema_version": "proof-manifest-result/v1",
|
||||
"status": "PASS"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"schema_version": "proof-request/v1",
|
||||
"run": {
|
||||
"id": "wiki-source-summarizer-samesite-mdn-2026-07-23",
|
||||
"profile": "capture"
|
||||
},
|
||||
"proofs": [
|
||||
{
|
||||
"finding": {"id": "MDN-SAMESITE-C1", "role": "quote"},
|
||||
"source": {
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie only for requests originating from the same site that set the cookie."
|
||||
}
|
||||
},
|
||||
{
|
||||
"finding": {"id": "MDN-SAMESITE-C2", "role": "quote"},
|
||||
"source": {
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:"
|
||||
}
|
||||
},
|
||||
{
|
||||
"finding": {"id": "MDN-SAMESITE-C3", "role": "quote"},
|
||||
"source": {
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "The request uses a safe method: in particular, this excludes POST, PUT, and DELETE."
|
||||
}
|
||||
},
|
||||
{
|
||||
"finding": {"id": "MDN-SAMESITE-C4", "role": "quote"},
|
||||
"source": {
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Send the cookie with both cross-site and same-site requests.\nThe Secure attribute must also be set when using this value."
|
||||
}
|
||||
},
|
||||
{
|
||||
"finding": {"id": "MDN-SAMESITE-C5", "role": "quote"},
|
||||
"source": {
|
||||
"namespace": "repo",
|
||||
"path": "harness/state/commit-runs/samesite-cookie-mdn/source-fetch.txt",
|
||||
"quote_utf8": "Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
## 증명 결과
|
||||
|
||||
- Manifest: `harness/state/commit-runs/samesite-cookie-mdn/proof-manifest.json`
|
||||
- Manifest SHA-256: `9a7dfe5bf9074b500c90a51faed31b6bc4756054a70d2108083f5719cc392619`
|
||||
- Proof: 5
|
||||
- PASS: 5
|
||||
- FAIL: 0
|
||||
@@ -0,0 +1,176 @@
|
||||
Skip to main content
|
||||
Skip to search
|
||||
Web
|
||||
HTTP
|
||||
Reference
|
||||
Headers
|
||||
Set-Cookie
|
||||
Set-Cookie header
|
||||
Baseline
|
||||
Widely available
|
||||
*
|
||||
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
|
||||
* Some parts of this feature may have varying levels of support.
|
||||
Learn more
|
||||
See full compatibility
|
||||
The HTTP Set-Cookie response header is used to send a cookie from the server to the user agent, so that the user agent can send it back to the server later.
|
||||
To send multiple cookies, multiple Set-Cookie headers should be sent in the same response.
|
||||
Warning:
|
||||
Browsers block frontend JavaScript code from accessing the Set-Cookie header, as required by the Fetch spec, which defines Set-Cookie as a forbidden response header name that must be filtered out from any response exposed to frontend code.
|
||||
When a Fetch API or XMLHttpRequest API request uses CORS, browsers will ignore Set-Cookie headers present in the server's response unless the request includes credentials. Visit Using the Fetch API - Including credentials and the XMLHttpRequest article to learn how to include credentials.
|
||||
For more information, see the guide on Using HTTP cookies.
|
||||
Header type
|
||||
Response header
|
||||
Forbidden request header
|
||||
No
|
||||
Forbidden response header
|
||||
Yes
|
||||
Syntax
|
||||
http
|
||||
Set-Cookie: <cookie-name>=<cookie-value>
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<number>
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Partitioned
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Secure
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure
|
||||
// Multiple attributes are also possible, for example:
|
||||
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
|
||||
Attributes
|
||||
<cookie-name>=<cookie-value>
|
||||
Defines the cookie name and its value.
|
||||
A cookie definition begins with a name-value pair.
|
||||
A <cookie-name> can contain any US-ASCII characters except for control characters (ASCII characters 0 up to 31 and ASCII character 127) or separator characters (space, tab and the characters: ( ) < > @ , ; : \ " / [ ] ? = { })
|
||||
A <cookie-value> can optionally be wrapped in double quotes and include any US-ASCII character excluding control characters (ASCII characters 0 up to 31 and ASCII character 127), Whitespace, double quotes, commas, semicolons, and backslashes.
|
||||
Encoding: Many implementations perform percent-encoding on cookie values. However, this is not required by the RFC specification. The percent-encoding does help to satisfy the requirements of the characters allowed for <cookie-value>.
|
||||
Note:
|
||||
Some cookie names contain prefixes that impose specific restrictions on the cookie's attributes in supporting user-agents. See Cookie prefixes for more information.
|
||||
Domain=<domain-value> Optional
|
||||
Defines the host to which the cookie will be sent.
|
||||
Only the current domain can be set as the value, or a domain of a higher order, unless it is a public suffix. Setting the domain will make the cookie available to it, as well as to all its subdomains.
|
||||
If omitted, the cookie is returned only to the host that sent them (i.e., it becomes a "host-only cookie").
|
||||
This is more restrictive than setting the host name, as the cookie is not made available to subdomains of the host.
|
||||
Contrary to earlier specifications, leading dots in domain names (.example.com) are ignored.
|
||||
Multiple host/domain values are not allowed, but if a domain is specified, then subdomains are always included.
|
||||
Expires=<date> Optional
|
||||
Indicates the maximum lifetime of the cookie as an HTTP-date timestamp.
|
||||
See Date for the required formatting.
|
||||
If unspecified, the cookie becomes a session cookie.
|
||||
A session finishes when the client shuts down, after which
|
||||
the session cookie is removed.
|
||||
Warning:
|
||||
Many web browsers have a session restore feature that will save all tabs and restore them the next time the browser is used. Session cookies will also be restored, as if the browser was never closed.
|
||||
The Expires attribute is set by the server with a value relative to its own internal clock, which may differ from that of the client browser.
|
||||
Firefox and Chromium-based browsers internally use an expiry (max-age) value that is adjusted to compensate for clock difference, storing and expiring cookies based on the time intended by the server.
|
||||
The adjustment for clock skew is calculated from the value of the DATE header.
|
||||
Note that the specification explains how the attribute should be parsed, but does not indicate if/how the value should be corrected by the recipient.
|
||||
HttpOnly Optional
|
||||
Forbids JavaScript from accessing the cookie, for example, through the Document.cookie property.
|
||||
Note that a cookie that has been created with HttpOnly will still be sent with JavaScript-initiated requests, for example, when calling XMLHttpRequest.send() or fetch().
|
||||
This mitigates attacks against cross-site scripting (XSS).
|
||||
Max-Age=<number> Optional
|
||||
Indicates the number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. If both Expires and Max-Age are set, Max-Age has precedence.
|
||||
Partitioned Optional
|
||||
Indicates that the cookie should be stored using partitioned storage.
|
||||
Note that if this is set, the Secure directive must also be set.
|
||||
See Cookies Having Independent Partitioned State (CHIPS) for more details.
|
||||
Path=<path-value> Optional
|
||||
Indicates the path that must exist in the requested URL for the browser to send the Cookie header.
|
||||
If omitted, this attribute defaults to the path component of the request URL. For example, if a cookie is set by a request to https://example.com/docs/Web/HTTP/index.html, the default path would be /docs/Web/HTTP/.
|
||||
The forward slash (/) character is interpreted as a directory separator, and subdirectories are matched as well. For example, for Path=/docs,
|
||||
the request paths /docs, /docs/, /docs/Web/, and /docs/Web/HTTP will all match.
|
||||
the request paths /, /docsets, /fr/docs will not match.
|
||||
Note:
|
||||
The path attribute lets you control what cookies the browser sends based on the different parts of a site.
|
||||
It is not intended as a security measure, and does not protect against unauthorized reading of the cookie from a different path.
|
||||
SameSite=<samesite-value> Optional
|
||||
Controls whether or not a cookie is sent with cross-site requests: that is, requests originating from a different site, including the scheme, from the site that set the cookie. This provides some protection against certain cross-site attacks, including cross-site request forgery (CSRF) attacks.
|
||||
The possible attribute values are:
|
||||
Strict
|
||||
Send the cookie only for requests originating from the same site that set the cookie.
|
||||
Lax
|
||||
Send the cookie only for requests originating from the same site that set the cookie, and for cross-site requests that meet both of the following criteria:
|
||||
The request is a top-level navigation: this essentially means that the request causes the URL shown in the browser's address bar to change.
|
||||
This would exclude, for example, requests made using the fetch() API, or requests for subresources from <img> or <script> elements, or navigations inside <iframe> elements.
|
||||
It would include requests made when the user clicks a link in the top-level browsing context from one site to another, or an assignment to document.location, or a <form> submission.
|
||||
The request uses a safe method: in particular, this excludes POST, PUT, and DELETE.
|
||||
Some browsers use Lax as the default value if SameSite is not specified: see Browser compatibility for details.
|
||||
Note:
|
||||
When Lax is applied as a default, a more permissive version is used. In this more permissive version, cookies are also included in POST requests, as long as they were set no more than two minutes before the request was made.
|
||||
None
|
||||
Send the cookie with both cross-site and same-site requests.
|
||||
The Secure attribute must also be set when using this value.
|
||||
Secure Optional
|
||||
Indicates that the cookie is sent to the server only when a request is made with the https: scheme (except on localhost), and therefore, is more resistant to man-in-the-middle attacks.
|
||||
Note:
|
||||
Do not assume that Secure prevents all access to sensitive information in cookies (session keys, login details, etc.).
|
||||
Cookies with this attribute can still be read/modified either with access to the client's hard disk or from JavaScript if the HttpOnly cookie attribute is not set.
|
||||
Insecure sites (http:) cannot set cookies with the Secure attribute. The https: requirements are ignored when the Secure attribute is set by localhost.
|
||||
Cookie prefixes
|
||||
Some cookie names contain prefixes that impose specific restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (__) and end in a dash (-). The following prefixes are defined:
|
||||
__Secure-: Cookies with names starting with __Secure- must be set with the Secure attribute by a secure page (HTTPS).
|
||||
__Host-: Cookies with names starting with __Host- must be set with the Secure attribute by a secure page (HTTPS). In addition, they must not have a Domain attribute specified, and the Path attribute must be set to /. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary.
|
||||
__Http-: Cookies with names starting with __Http- must be set with the Secure flag by a secure page (HTTPS) and in addition must have the HttpOnly attribute set to prove that they were set via the Set-Cookie header (they can't be set or modified via JavaScript features such as Document.cookie or the Cookie Store API).
|
||||
__Host-Http-: Cookies with names starting with __Host-Http- must be set with the Secure flag by a secure page (HTTPS) and must have the HttpOnly attribute set to prove that they were set via the Set-Cookie header. In addition, they also have the same restrictions as __Host--prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests.
|
||||
Warning:
|
||||
You cannot count on these additional assurances on browsers that don't support cookie prefixes; in such cases, prefixed cookies will always be accepted.
|
||||
Examples
|
||||
Session cookie
|
||||
Session cookies are removed when the client shuts down. Cookies are session cookies if they do not specify the Expires or Max-Age attribute.
|
||||
http
|
||||
Set-Cookie: sessionId=38afes7a8
|
||||
Permanent cookie
|
||||
Permanent cookies are removed at a specific date (Expires) or after a specific length of time (Max-Age) and not when the client is closed.
|
||||
http
|
||||
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT
|
||||
http
|
||||
Set-Cookie: id=a3fWa; Max-Age=2592000
|
||||
Invalid domains
|
||||
A cookie for a domain that does not include the server that set it should be rejected by the user agent.
|
||||
The following cookie will be rejected if set by a server hosted on original-company.com:
|
||||
http
|
||||
Set-Cookie: qwerty=219ffwef9w0f; Domain=some-company.co.uk
|
||||
A cookie for a subdomain of the serving domain will be rejected.
|
||||
The following cookie will be rejected if set by a server hosted on example.com:
|
||||
http
|
||||
Set-Cookie: sessionId=e8bb43229de9; Domain=foo.example.com
|
||||
Cookie prefixes
|
||||
Cookie names prefixed with __Secure- or __Host- can be used only if they are set with the Secure attribute from a secure (HTTPS) origin.
|
||||
Cookie names prefixed with __Http- or __Host-Http- can be used only if they are set with the Secure attribute from a secure (HTTPS) origin and in addition must have the HttpOnly attribute set to prove that they were set via the Set-Cookie header and not on the client-side via JavaScript.
|
||||
In addition, cookies with the __Host- or __Host-Http- prefix must have a path of / (meaning any path at the host) and must not have a Domain attribute.
|
||||
http
|
||||
// Both accepted when from a secure origin (HTTPS)
|
||||
Set-Cookie: __Secure-ID=123; Secure; Domain=example.com
|
||||
Set-Cookie: __Host-ID=123; Secure; Path=/
|
||||
// Rejected due to missing Secure attribute
|
||||
Set-Cookie: __Secure-id=1
|
||||
// Rejected due to the missing Path=/ attribute
|
||||
Set-Cookie: __Host-id=1; Secure
|
||||
// Rejected due to setting a Domain
|
||||
Set-Cookie: __Host-id=1; Secure; Path=/; Domain=example.com
|
||||
// Only settable via Set-Cookie
|
||||
Set-Cookie: __Http-ID=123; Secure; Domain=example.com
|
||||
Set-Cookie: __Host-Http-ID=123; Secure; Path=/
|
||||
Partitioned cookie
|
||||
http
|
||||
Set-Cookie: __Host-example=34d8g; SameSite=None; Secure; Path=/; Partitioned;
|
||||
Note:
|
||||
Partitioned cookies must be set with Secure. In addition, it is recommended to use a __Host or __Host-Http- prefix when setting partitioned cookies to make them bound to the hostname and not the registrable domain.
|
||||
Specifications
|
||||
Specification
|
||||
HTTP State Management Mechanism
|
||||
# sane-set-cookie
|
||||
Browser compatibility
|
||||
See also
|
||||
HTTP cookies
|
||||
Cookie
|
||||
Document.cookie
|
||||
Samesite cookies explained (web.dev blog)
|
||||
Help improve MDN
|
||||
Learn how to contribute
|
||||
This page was last modified on Jun 15, 2026 by MDN contributors.
|
||||
View this page on GitHub • Report a problem with this content
|
||||
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user