﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37485	set_cookie() ignores the cookie flags required by name prefixes and SameSite=None	Knk		"`HttpResponse.set_cookie()` emits the `secure` and `httponly` values exactly as it receives them, while
`HttpResponse.delete_cookie()` already applies the flags a browser requires before it stores a cookie.
The result is a syntactically valid `Set-Cookie` header that the browser silently discards.

This affects three documented cases:

|| Cookie name / parameters || Required by the browser || Emitted by set_cookie() ||
|| `__Secure-x`, `__Host-x`, `__Http-x` || `Secure` || nothing, unless the caller passes `secure=True` ||
|| `__Http-x`, `__Host-Http-x` || `HttpOnly` || nothing, unless the caller passes `httponly=True` ||
|| `samesite=""None""` || `Secure` || nothing ||

References: RFC 6265bis section 4.1.3 (cookie name prefixes) and the SameSite=None requirements. The
`__Http-` and `__Host-Http-` prefixes come from CHIPS; `delete_cookie()` already handles them, so the
inconsistency is inside the same class.

The failure is silent. The response is a normal 200 with a `Set-Cookie` header, the browser drops the
cookie, and the following request arrives without it. A project that sets
`SESSION_COOKIE_NAME = ""__Host-sessionid""` and keeps `SESSION_COOKIE_SECURE = False` (local development,
or TLS terminated in a reverse proxy) sees a successful login followed by a request with no session, and
nothing appears in the server logs.

Steps to reproduce, current behavior:

{{{
>>> from django.http import HttpResponse
>>> r = HttpResponse()
>>> r.set_cookie(""__Host-sessionid"", ""abc"")
>>> r.cookies[""__Host-sessionid""][""secure""]
''
>>> r.set_cookie(""c"", ""abc"", samesite=""None"")
>>> r.cookies[""c""][""secure""]
''
}}}

Expected behavior: `secure` is `True` in both cases, because a browser will not store either cookie
otherwise. Cookies without a name prefix and without `SameSite=None` must keep behaving exactly as
before, with the flags the caller passed and nothing else.

Proposed fix: a module-level helper in `django/http/response.py` that computes the flags required by the
name and by `samesite`, used by both `set_cookie()` and `delete_cookie()` so the two paths cannot
diverge again. The helper only adds flags a browser already requires for that cookie; it never removes
one.

Patch: https://github.com/django/django/pull/22261 (branch `set-cookie-required-flags`), with four
regression tests in `tests/responses/test_cookie.py` and a paragraph in
`docs/ref/request-response.txt`.

Verification:

{{{
$ python tests/runtests.py responses --parallel 1     # with the patch
Ran 61 tests
OK (skipped=1)

$ python tests/runtests.py responses --parallel 1     # django/http/response.py reverted
FAILED (failures=7, skipped=1)
}}}

The seven failures are exactly the new assertions (the prefixed-name loops count one subtest each), so
they measure the change and not the environment.

Not covered by this patch: `__Host-` also requires `Path=/` and no `Domain` attribute. Enforcing that
means changing the contract of `set_cookie()` or adding a `security.W0xx` deployment check that reads
`SESSION_COOKIE_NAME` / `CSRF_COOKIE_NAME`; it can be a follow-up rather than part of this diff.

I searched the existing tickets for cookie prefixes, `Secure`, `HttpOnly` and `SameSite`. The open ones I
found, including 34613 (`Partitioned` support) and the older cookie parsing tickets, do not cover
`set_cookie()` applying the flags required by name prefixes or by `SameSite=None`."	Bug	assigned	HTTP handling	dev	Normal		cookies samesite secure httponly	Knk	Unreviewed	1	0	0	0	0	0
