outline fixture: read Outline 1.10's __Host-csrfToken cookie (R-744)
gates / gates (push) Successful in 2s

Outline 1.10 names the CSRF cookie __Host-csrfToken on a secure request and csrfToken over plain HTTP (server/utils/
csrf.ts getCookieName); 1.9.1 always said csrfToken. Proven on 9202 at the live pin 1.10.1: installation.create 302,
cookie __Host-csrfToken, apiKeys.create, a published document read back, unknown id and wrong key refused
(felhom.eu/documentation/audits/rulings-2026-10-01/D/D2-outline-fixture-9202.txt). The old pattern cannot match that
header line (the red: 2026-09-30, both venues).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-01 08:19:19 +02:00
parent 804884a749
commit 9fc705209d
+8 -4
View File
@@ -1413,12 +1413,16 @@ class Outline:
self.tried = f"POST /api/installation.create -> {code}" self.tried = f"POST /api/installation.create -> {code}"
return None return None
rc, code, out = w.app_curl(sub, "/home", "-D", "-", "-o", "/dev/null", "-H", f"Cookie: {ck}") rc, code, out = w.app_curl(sub, "/home", "-D", "-", "-o", "/dev/null", "-H", f"Cookie: {ck}")
csrf = re.search(r"(?im)^set-cookie:\s*csrfToken=([^;\r\n]+)", out or "") # R-744: Outline 1.10 names the cookie `__Host-csrfToken` on a secure request (server/utils/csrf.ts getCookieName,
# shared/constants.ts CSRF.secureCookieName) and `csrfToken` over plain HTTP — 1.9.1 always said `csrfToken`.
# The double-submit check compares the cookie under the request's own name with the x-csrf-token header.
csrf = re.search(r"(?im)^set-cookie:\s*((?:__Host-)?csrfToken)=([^;\r\n]+)", out or "")
if not csrf: if not csrf:
self.tried = "no csrfToken cookie from GET /home" self.tried = "no csrfToken / __Host-csrfToken cookie from GET /home"
return None return None
cs = csrf.group(1) cn, cs = csrf.group(1), csrf.group(2)
rc, code, out = w.app_curl(sub, "/api/apiKeys.create", "-H", f"Cookie: {ck}; csrfToken={cs}", "-H", f"x-csrf-token: {cs}", say(f" outline: CSRF cookie {cn}")
rc, code, out = w.app_curl(sub, "/api/apiKeys.create", "-H", f"Cookie: {ck}; {cn}={cs}", "-H", f"x-csrf-token: {cs}",
"-H", "Content-Type: application/json", "-H", f"Origin: {o}", "-H", "Content-Type: application/json", "-H", f"Origin: {o}",
data=json.dumps({"name": "drill"}), method="POST") data=json.dumps({"name": "drill"}), method="POST")
try: try: