From b50bfa1fda5826ccf1acb6d4d838fa5b8f801d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Wr=C3=B3blewski?= Date: Tue, 10 Sep 2024 18:37:36 +0300 Subject: [PATCH] =?UTF-8?q?AG-35484=20Fix=20'trusted-set-cookie'=20?= =?UTF-8?q?=E2=80=94=20cannot=20set=20cookie=20if=20name=20has=20'=5F=5FSe?= =?UTF-8?q?cure-'=20prefix.=20#448?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 99533751b13696145ef79607b9838c75ca6c4425 Author: Adam Wróblewski Date: Thu Sep 5 17:44:07 2024 +0200 Add a test for case with specified "domain" Log a message if "domainValue" is specified and cookie name has "__Host-" prefix commit 563a36f9d1b583c32769bd18278dbb11a62564dd Author: Slava Leleka Date: Thu Sep 5 18:16:38 2024 +0300 CHANGELOG.md edited online with Bitbucket commit 1b151e59bd0e74226852292e7dffc464bd606219 Author: Adam Wróblewski Date: Thu Sep 5 16:21:45 2024 +0200 Add tests to cookie utils Get rid of else statement commit f19ad00901ced53b06de981332d12c59986a5c89 Author: Adam Wróblewski Date: Thu Sep 5 15:23:16 2024 +0200 Fix 'trusted-set-cookie' — cannot set cookie if name has '__Secure-' or '__Host-' prefix --- CHANGELOG.md | 10 ++++++++++ src/helpers/cookie-utils.ts | 21 +++++++++++++++++++++ tests/helpers/cookie-utils.spec.js | 12 ++++++++++++ 3 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32e1c0483..3b092c484 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic +## [Unreleased] + +### Fixed + +- setting cookie which name has special prefix `__Host-` or `__Secure-` by + `trusted-set-cookie` and `trusted-set-cookie-reload` scriptlets [#448] + +[Unreleased]: https://github.com/AdguardTeam/Scriptlets/compare/v1.11.27...HEAD +[#448]: https://github.com/AdguardTeam/Scriptlets/issues/448 + ## [v1.11.27] - 2024-08-29 ### Added diff --git a/src/helpers/cookie-utils.ts b/src/helpers/cookie-utils.ts index 8cff2caa5..2960a4d96 100644 --- a/src/helpers/cookie-utils.ts +++ b/src/helpers/cookie-utils.ts @@ -42,6 +42,8 @@ export const serializeCookie = ( domainValue = '', shouldEncodeValue = true, ) => { + const HOST_PREFIX = '__Host-'; + const SECURE_PREFIX = '__Secure-'; const COOKIE_BREAKER = ';'; // semicolon will cause the cookie to break @@ -54,11 +56,30 @@ export const serializeCookie = ( let resultCookie = `${name}=${value}`; + if (name.startsWith(HOST_PREFIX)) { + // Cookie with "__Host-" prefix requires "secure" flag, path must be "/", + // and must not have a domain specified + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes + // https://github.com/AdguardTeam/Scriptlets/issues/448 + resultCookie += '; path=/; secure'; + if (domainValue) { + // eslint-disable-next-line no-console + console.debug( + `Domain value: "${domainValue}" has been ignored, because is not allowed for __Host- prefixed cookies`, + ); + } + return resultCookie; + } const path = getCookiePath(rawPath); if (path) { resultCookie += `; ${path}`; } + if (name.startsWith(SECURE_PREFIX)) { + // Cookie with "__Secure-" prefix requires "secure" flag + resultCookie += '; secure'; + } + if (domainValue) { resultCookie += `; domain=${domainValue}`; } diff --git a/tests/helpers/cookie-utils.spec.js b/tests/helpers/cookie-utils.spec.js index 602e3c4d2..39633f363 100644 --- a/tests/helpers/cookie-utils.spec.js +++ b/tests/helpers/cookie-utils.spec.js @@ -42,6 +42,18 @@ describe('serializeCookie', () => { actual: ['test', '1', '', 'example.com'], expected: 'test=1; domain=example.com', }, + { + actual: ['__Host-prefix', 'host_prefix', ''], + expected: '__Host-prefix=host_prefix; path=/; secure', + }, + { + actual: ['__Host-prefix_domain', 'host_prefix_domain', '', 'example.com'], + expected: '__Host-prefix_domain=host_prefix_domain; path=/; secure', + }, + { + actual: ['__Secure-prefix', 'secure_prefix', ''], + expected: '__Secure-prefix=secure_prefix; secure', + }, ])('$actual -> $expected', ({ actual, expected }) => { expect(serializeCookie(...actual)).toBe(expected); });