From c76b8314add15cad7d3ffaec7680c128d5b81191 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Mon, 6 Apr 2026 09:02:01 +0200 Subject: [PATCH] [ext/session] Validate session.cookie_samesite against allowed values Add OnUpdateSessionSameSite() INI handler that enforces the SameSite whitelist (Strict, Lax, None, or empty string), rejecting any other value with E_WARNING. Previously OnUpdateSessionStr() accepted arbitrary strings including CRLF sequences, which were appended verbatim into the Set-Cookie header. The php_setcookie() function has a TODO comment for the same gap; this addresses it at the INI layer. --- ext/session/session.c | 19 +++++++++++- .../session_cookie_samesite_validation.phpt | 31 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 ext/session/tests/session_cookie_samesite_validation.phpt diff --git a/ext/session/session.c b/ext/session/session.c index c04e19e25edc..7c5df503ea2f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -733,6 +733,23 @@ static PHP_INI_MH(OnUpdateSessionStr) return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static PHP_INI_MH(OnUpdateSessionSameSite) +{ + SESSION_CHECK_ACTIVE_STATE; + SESSION_CHECK_OUTPUT_STATE; + + if (new_value && ZSTR_LEN(new_value) > 0 + && !zend_string_equals_literal_ci(new_value, "Strict") + && !zend_string_equals_literal_ci(new_value, "Lax") + && !zend_string_equals_literal_ci(new_value, "None")) { + php_error_docref(NULL, E_WARNING, + "session.cookie_samesite must be \"Strict\", \"Lax\", \"None\", or \"\""); + return FAILURE; + } + + return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + static PHP_INI_MH(OnUpdateSessionBool) { SESSION_CHECK_ACTIVE_STATE; @@ -904,7 +921,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_partitioned", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_samesite, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) diff --git a/ext/session/tests/session_cookie_samesite_validation.phpt b/ext/session/tests/session_cookie_samesite_validation.phpt new file mode 100644 index 000000000000..be1cf29925f3 --- /dev/null +++ b/ext/session/tests/session_cookie_samesite_validation.phpt @@ -0,0 +1,31 @@ +--TEST-- +session.cookie_samesite only accepts Strict, Lax, None, or empty string +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: ini_set(): session.cookie_samesite must be "Strict", "Lax", "None", or "" in %s on line %d + +Warning: ini_set(): session.cookie_samesite must be "Strict", "Lax", "None", or "" in %s on line %d +string(0) "" +bool(true) +bool(true) +bool(true) +bool(true)