From a3bddae4030260cb3ada3d9e2f45596f27fa4ebd Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Fri, 3 Mar 2023 11:13:53 +0000
Subject: [PATCH] Issue #3150614 by pfrenssen, cilefen, murilohp, FinnishFlash,
 mpp, andypost, ranjith_kumar_k_u, vagelis-prokopiou, blazey, tsplash, Winn,
 alexpott, Berdir, mxr576: Set SameSite on session cookies

---
 .../scaffold/files/default.services.yml       |  7 ++++++
 core/misc/cspell/dictionary.txt               |  1 +
 core/modules/system/system.install            | 22 +++++++++++++++++++
 .../Core/Session/SessionConfigurationTest.php | 11 ++++++++++
 sites/default/default.services.yml            |  7 ++++++
 5 files changed, 48 insertions(+)

diff --git a/core/assets/scaffold/files/default.services.yml b/core/assets/scaffold/files/default.services.yml
index eb530088efaf..8a6cdf2f77fa 100644
--- a/core/assets/scaffold/files/default.services.yml
+++ b/core/assets/scaffold/files/default.services.yml
@@ -37,6 +37,13 @@ parameters:
     # @default none
     # cookie_domain: '.example.com'
     #
+    # Set the SameSite cookie attribute: 'None', 'Lax', or 'Strict'. If set,
+    # this value will override the server value. See
+    # https://www.php.net/manual/en/session.security.ini.php for more
+    # information.
+    # @default no value
+    cookie_samesite: Lax
+    #
     # Set the session ID string length. The length can be between 22 to 256. The
     # PHP recommended value is 48. See
     # https://www.php.net/manual/session.security.ini.php for more information.
diff --git a/core/misc/cspell/dictionary.txt b/core/misc/cspell/dictionary.txt
index bb74373f9df9..5c5fa462786b 100644
--- a/core/misc/cspell/dictionary.txt
+++ b/core/misc/cspell/dictionary.txt
@@ -1031,6 +1031,7 @@ safa
 sameline
 samename
 sameorigin
+samesite
 sata
 savepoints
 sayre
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index a896ba989743..b0659ff3dd80 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1309,6 +1309,28 @@ function system_requirements($phase) {
     }
   }
 
+  // Check if the SameSite cookie attribute is set to a valid value. Since this
+  // involves checking whether we are using a secure connection this only makes
+  // sense inside an HTTP request, not on the command line.
+  if ($phase === 'runtime' && PHP_SAPI !== 'cli') {
+    $samesite = ini_get('session.cookie_samesite') ?: t('Not set');
+    // Check if the SameSite attribute is set to a valid value. If it is set to
+    // 'None' the request needs to be done over HTTPS.
+    $valid = match ($samesite) {
+      'Lax', 'Strict' => TRUE,
+      'None' => $request_object->isSecure(),
+      default => FALSE,
+    };
+    $requirements['php_session_samesite'] = [
+      'title' => t('SameSite cookie attribute'),
+      'value' => $samesite,
+      'severity' => $valid ? REQUIREMENT_OK : REQUIREMENT_WARNING,
+      'description' => t('This attribute should be explicitly set to Lax, Strict or None. If set to None then the request must be made via HTTPS. See <a href=":url" target="_blank">PHP documentation</a>', [
+        ':url' => 'https://www.php.net/manual/en/session.configuration.php#ini.session.cookie-samesite',
+      ]),
+    ];
+  }
+
   // See if trusted hostnames have been configured, and warn the user if they
   // are not set.
   if ($phase == 'runtime') {
diff --git a/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php b/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php
index ac6b0a769748..55282c05483c 100644
--- a/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php
+++ b/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php
@@ -116,6 +116,17 @@ public function testCookieSecure($uri, $expected_secure) {
     $this->assertEquals($expected_secure, $options['cookie_secure']);
   }
 
+  /**
+   * Test that session.cookie_samesite is configured correctly.
+   */
+  public function testSameSiteCookie() {
+    $request = Request::create('https://example.com');
+
+    $config = $this->createSessionConfiguration(['cookie_samesite' => 'Strict']);
+    $options = $config->getOptions($request);
+    $this->assertEquals('Strict', $options['cookie_samesite']);
+  }
+
   /**
    * Tests that session.cookie_secure ini settings cannot be overridden.
    *
diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml
index eb530088efaf..8a6cdf2f77fa 100644
--- a/sites/default/default.services.yml
+++ b/sites/default/default.services.yml
@@ -37,6 +37,13 @@ parameters:
     # @default none
     # cookie_domain: '.example.com'
     #
+    # Set the SameSite cookie attribute: 'None', 'Lax', or 'Strict'. If set,
+    # this value will override the server value. See
+    # https://www.php.net/manual/en/session.security.ini.php for more
+    # information.
+    # @default no value
+    cookie_samesite: Lax
+    #
     # Set the session ID string length. The length can be between 22 to 256. The
     # PHP recommended value is 48. See
     # https://www.php.net/manual/session.security.ini.php for more information.
-- 
GitLab