Skip to content

Add configurable session cookie SameSite and Secure preferences (#1501)#1660

Merged
mambax7 merged 3 commits intoXOOPS:masterfrom
mambax7:fix/session-samesite-preference
Mar 15, 2026
Merged

Add configurable session cookie SameSite and Secure preferences (#1501)#1660
mambax7 merged 3 commits intoXOOPS:masterfrom
mambax7:fix/session-samesite-preference

Conversation

@mambax7
Copy link
Collaborator

@mambax7 mambax7 commented Mar 15, 2026

Fixes #1501. Ports the session cookie preferences from the 259world development branch. The SameSite attribute was hardcoded to 'Lax' since PR #1488
now configurable via Admin > Preferences.

Changes:

  • session.php: Read session_cookie_samesite and session_cookie_secure from $xoopsConfig with fallback to 'Lax'/auto-detect. Forces Secure=true when SameSite=None (browser requirement).
  • preferences.php: Add _MD_AM_SESSSAMESITE and _MD_AM_SESSSECURE language constants.
  • makedata.php: Add config rows for fresh installs (conf_id 136, 137) with Lax/Strict/None select options.
  • upgrade/index.php: Add addsessioncookieprefs upgrade task that inserts the two config rows and select options for existing installations.

Summary by CodeRabbit

  • New Features

    • Added configurable session cookie SameSite (Lax, Strict, None) and Secure (HTTPS-only) settings.
    • Automatic enforcement: Secure is enabled when SameSite=None.
  • Documentation

    • Admin preference labels and descriptions added for SameSite and Secure settings.
  • Chores

    • Upgrade task added to add these settings and options for existing installations.

…S#1501)

  Fixes XOOPS#1501. Ports the session cookie preferences from the 259world development branch. The SameSite attribute was hardcoded to 'Lax' since PR XOOPS#1488 —
  now configurable via Admin > Preferences.

  Changes:
  - session.php: Read session_cookie_samesite and session_cookie_secure from $xoopsConfig with fallback to 'Lax'/auto-detect. Forces Secure=true when
  SameSite=None (browser requirement).
  - preferences.php: Add _MD_AM_SESSSAMESITE and _MD_AM_SESSSECURE language constants.
  - makedata.php: Add config rows for fresh installs (conf_id 136, 137) with Lax/Strict/None select options.
  - upgrade/index.php: Add addsessioncookieprefs upgrade task that inserts the two config rows and select options for existing installations.
Copilot AI review requested due to automatic review settings March 15, 2026 12:11
@coderabbitai
Copy link

coderabbitai bot commented Mar 15, 2026

Walkthrough

Adds configurable session cookie attributes: SameSite and Secure. Installer data and upgrade logic add the new config entries and options; runtime session code reads and validates these settings to set cookie parameters; language strings for admin UI are included.

Changes

Cohort / File(s) Summary
Installer data
htdocs/install/include/makedata.php
Insert two new config rows: session_cookie_samesite (conf_id 136) and session_cookie_secure (conf_id 137), plus three SameSite options (Lax, Strict, None).
Runtime session handling
htdocs/kernel/session.php
Replace hardcoded SameSite/Secure with config-driven resolution: validate SameSite values, derive/override Secure (enforce Secure when SameSite=None), and pass dynamic samesite/secure into session_set_cookie_params.
Admin language strings
htdocs/modules/system/language/english/admin/preferences.php
Add four language constants for SameSite and Secure labels and descriptions shown in preferences UI.
Upgrade migration
upgrade/upd_2.5.11-to-2.5.12/index.php
Add upgrade task addsessioncookieprefs with check_addsessioncookieprefs() and apply_addsessioncookieprefs() to idempotently create the two config entries and the three SameSite options (recreate options to avoid duplicates).

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Upgrade as Upgrade Script
participant DB as Database (config, configoption)
participant Kernel as PHP Kernel / Session
participant Browser as Client (Browser)
Upgrade->>DB: check for session_cookie_samesite / session_cookie_secure
alt missing
Upgrade->>DB: insert config rows and options (Lax, Strict, None)
DB-->>Upgrade: success/failure
end
Browser->>Kernel: HTTP request
Kernel->>DB: read config values (SameSite, Secure)
DB-->>Kernel: returns values
Kernel->>Kernel: validate SameSite; enforce Secure if SameSite=None
Kernel->>Browser: send Set-Cookie with computed path, domain, secure, httponly, samesite

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • redheadedrod
  • tad0616
  • Philoxx
  • GregMage
  • ihackcode
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: adding configurable session cookie SameSite and Secure preferences, which aligns with the core changes across all modified files.
Linked Issues check ✅ Passed The PR successfully implements the feature request #1501 by making session cookie preferences (SameSite and Secure) configurable via Admin > Preferences, replacing previous hardcoding and enabling flexible setup.
Out of Scope Changes check ✅ Passed All changes are scoped to session cookie preference functionality: installer data, session handling logic, language definitions, and upgrade tasks—with no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable session-cookie attributes (SameSite and Secure) to XOOPS core so administrators can tune cookie behavior via System Preferences, with installer + upgrader support for 2.5.12.

Changes:

  • Add new upgrade task to create session_cookie_samesite / session_cookie_secure preferences (and options) during 2.5.11 → 2.5.12 upgrade.
  • Add new System Preferences language strings for the new settings.
  • Update session cookie initialization to use configured SameSite/Secure values; update installer seed data to include the new config rows and options.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
upgrade/upd_2.5.11-to-2.5.12/index.php Adds an upgrade task to insert the new session cookie preferences and SameSite options.
htdocs/modules/system/language/english/admin/preferences.php Adds English labels/descriptions for the new preferences.
htdocs/kernel/session.php Reads the new preferences to set session cookie samesite and secure attributes.
htdocs/install/include/makedata.php Seeds new installs with the new config entries and SameSite options.

Comment on lines +200 to +205
// Insert SameSite preference
$db->exec("INSERT INTO `{$configTable}` (conf_modid, conf_catid, conf_name, conf_title, conf_value, conf_desc, conf_formtype, conf_valuetype, conf_order) VALUES (0, 1, 'session_cookie_samesite', '_MD_AM_SESSSAMESITE', 'Lax', '_MD_AM_SESSSAMESITE_DSC', 'select', 'text', 43)");

// Insert Secure preference
$db->exec("INSERT INTO `{$configTable}` (conf_modid, conf_catid, conf_name, conf_title, conf_value, conf_desc, conf_formtype, conf_valuetype, conf_order) VALUES (0, 1, 'session_cookie_secure', '_MD_AM_SESSSECURE', '0', '_MD_AM_SESSSECURE_DSC', 'yesno', 'int', 44)");

Comment on lines +200 to +219
// Insert SameSite preference
$db->exec("INSERT INTO `{$configTable}` (conf_modid, conf_catid, conf_name, conf_title, conf_value, conf_desc, conf_formtype, conf_valuetype, conf_order) VALUES (0, 1, 'session_cookie_samesite', '_MD_AM_SESSSAMESITE', 'Lax', '_MD_AM_SESSSAMESITE_DSC', 'select', 'text', 43)");

// Insert Secure preference
$db->exec("INSERT INTO `{$configTable}` (conf_modid, conf_catid, conf_name, conf_title, conf_value, conf_desc, conf_formtype, conf_valuetype, conf_order) VALUES (0, 1, 'session_cookie_secure', '_MD_AM_SESSSECURE', '0', '_MD_AM_SESSSECURE_DSC', 'yesno', 'int', 44)");

// Add select options for SameSite preference
$sql = "SELECT conf_id FROM `{$configTable}` WHERE conf_name = 'session_cookie_samesite'";
$result = $db->query($sql);
if ($db->isResultSet($result) && ($result instanceof \mysqli_result)) {
$row = $db->fetchRow($result);
if ($row) {
$confId = (int) $row[0];
$db->exec("INSERT INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('Lax', 'Lax', {$confId})");
$db->exec("INSERT INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('Strict', 'Strict', {$confId})");
$db->exec("INSERT INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('None', 'None', {$confId})");
}
}

return true;
Comment on lines +179 to +186
$sql = 'SELECT COUNT(*) FROM `' . $GLOBALS['xoopsDB']->prefix('config')
. "` WHERE `conf_name` IN ('session_cookie_samesite', 'session_cookie_secure')";
$result = $GLOBALS['xoopsDB']->query($sql);
if (!$GLOBALS['xoopsDB']->isResultSet($result) || !($result instanceof \mysqli_result)) {
return false;
}
$row = $GLOBALS['xoopsDB']->fetchRow($result);
return $row && (int) $row[0] >= 2;
Comment on lines +71 to +81
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

$secureFromConfig = isset($xoopsConfig['session_cookie_secure']) ? (bool) $xoopsConfig['session_cookie_secure'] : null;
$secure = is_bool($secureFromConfig) ? $secureFromConfig : (XOOPS_PROT === 'https://');

// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
}
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@htdocs/kernel/session.php`:
- Around line 75-77: The current logic lets a stored value like '0' in
$xoopsConfig['session_cookie_secure'] override HTTPS auto-detection, weakening
security; change the handling so only an explicit affirmative (e.g. string '1'
or boolean true) forces Secure=true, otherwise leave $secureFromConfig as null
so $secure falls back to XOOPS_PROT auto-detection. Update the assignment around
$secureFromConfig/$secure (variables $xoopsConfig['session_cookie_secure'],
$secureFromConfig, $secure and use XOOPS_PROT) to map only explicit true values
to true and treat any other stored value as “auto” (null) so HTTPS sites still
get Secure cookies by default; if you need full on/off/auto semantics implement
a tri-state config instead.

In `@upgrade/upd_2.5.11-to-2.5.12/index.php`:
- Around line 177-220: The migration currently always returns true and can leave
a half-applied state; update apply_addsessioncookieprefs() to be idempotent and
fail-fast: before inserting use existence checks (or INSERT IGNORE/ON DUPLICATE)
against $configTable to avoid duplicate conf_name inserts, verify each
$db->exec() and $db->query() call succeeds (and return false on any failure),
ensure after inserting the 'session_cookie_samesite' row you re-query
$configTable and validate $confId (using $db->isResultSet() and $db->fetchRow())
and then verify each $optionTable insert for SameSite options succeeds (return
false on failure), and finally only return true when all inserts/validations
complete successfully; reference apply_addsessioncookieprefs(),
check_addsessioncookieprefs(), $db, $configTable, $optionTable, $confId, exec(),
query(), isResultSet(), fetchRow().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8f62a277-74a2-49eb-a285-7b2b850f1cc5

📥 Commits

Reviewing files that changed from the base of the PR and between 83f55e2 and 2609925.

📒 Files selected for processing (4)
  • htdocs/install/include/makedata.php
  • htdocs/kernel/session.php
  • htdocs/modules/system/language/english/admin/preferences.php
  • upgrade/upd_2.5.11-to-2.5.12/index.php

Comment on lines +75 to +77
$secureFromConfig = isset($xoopsConfig['session_cookie_secure']) ? (bool) $xoopsConfig['session_cookie_secure'] : null;
$secure = is_bool($secureFromConfig) ? $secureFromConfig : (XOOPS_PROT === 'https://');

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

session_cookie_secure default handling weakens HTTPS cookie security.

At Line 76, config value '0' overrides HTTPS auto-detection to false. Because this PR seeds 'session_cookie_secure' = '0' in installer/upgrade, many HTTPS sites will emit non-Secure session cookies by default.

🔐 Suggested fix (preserve HTTPS-safe default; allow explicit force-on)
-        $secureFromConfig = isset($xoopsConfig['session_cookie_secure']) ? (bool) $xoopsConfig['session_cookie_secure'] : null;
-        $secure = is_bool($secureFromConfig) ? $secureFromConfig : (XOOPS_PROT === 'https://');
+        // Keep secure-by-default behavior on HTTPS, allow explicit force-on from config.
+        $secure = (XOOPS_PROT === 'https://');
+        if (isset($xoopsConfig['session_cookie_secure']) && (string)$xoopsConfig['session_cookie_secure'] === '1') {
+            $secure = true;
+        }

If you need full explicit on/off/auto behavior, model this preference as a tri-state option instead of yes/no.

As per coding guidelines, htdocs/kernel/**/*.php requires special attention to security and backward compatibility in core kernel classes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@htdocs/kernel/session.php` around lines 75 - 77, The current logic lets a
stored value like '0' in $xoopsConfig['session_cookie_secure'] override HTTPS
auto-detection, weakening security; change the handling so only an explicit
affirmative (e.g. string '1' or boolean true) forces Secure=true, otherwise
leave $secureFromConfig as null so $secure falls back to XOOPS_PROT
auto-detection. Update the assignment around $secureFromConfig/$secure
(variables $xoopsConfig['session_cookie_secure'], $secureFromConfig, $secure and
use XOOPS_PROT) to map only explicit true values to true and treat any other
stored value as “auto” (null) so HTTPS sites still get Secure cookies by
default; if you need full on/off/auto semantics implement a tri-state config
instead.

…handling

  Addresses P1 and P2 from Codex review on PR XOOPS#1660:

  P1 — Security regression in session.php:
  The (bool) cast on session_cookie_secure turned the DB default '0' into false, overriding HTTPS auto-detection. Now: Secure is auto-detected from
  XOOPS_PROT, and the preference can only force it ON (never OFF). SameSite=None still forces Secure=true.

  P2 — Upgrade task half-applied state:
  - check_addsessioncookieprefs() now verifies both config rows AND the 3 SameSite options exist
  - apply_addsessioncookieprefs() is idempotent: skips inserts if rows already exist, uses INSERT IGNORE for options, logs DB errors via $this->logs[],
  returns false on failure
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable session-cookie security preferences to XOOPS 2.5.12, ensuring modern browser compatibility (SameSite + Secure) across both fresh installs and upgrades.

Changes:

  • Add new system preferences for session_cookie_samesite and session_cookie_secure (including installer defaults + SameSite options).
  • Apply these preferences when setting session cookie parameters in the core session handler.
  • Add an upgrade task to backfill the new preferences into existing installations.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
upgrade/upd_2.5.11-to-2.5.12/index.php Adds an upgrade task to insert the new config rows + SameSite options.
htdocs/modules/system/language/english/admin/preferences.php Adds English admin strings for the new preferences.
htdocs/kernel/session.php Uses the new preferences to compute samesite and secure cookie params (including forcing Secure for SameSite=None).
htdocs/install/include/makedata.php Seeds default config values and SameSite select options for new installs.

}
// Re-fetch the conf_id
$result = $db->query($sql);
$sameSiteRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;

if (!$optRow || (int) $optRow[0] < 3) {
foreach (['Lax', 'Strict', 'None'] as $opt) {
$db->exec("INSERT IGNORE INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('{$opt}', '{$opt}', {$confId})");
Comment on lines +246 to +252
$sql = "SELECT COUNT(*) FROM `{$optionTable}` WHERE conf_id = {$confId}";
$result = $db->query($sql);
$optRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;

if (!$optRow || (int) $optRow[0] < 3) {
foreach (['Lax', 'Strict', 'None'] as $opt) {
$db->exec("INSERT IGNORE INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('{$opt}', '{$opt}', {$confId})");
Comment on lines +71 to +79
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

// Auto-detect Secure from protocol; preference can only force it ON, never OFF
$secure = (XOOPS_PROT === 'https://');
if (!empty($xoopsConfig['session_cookie_secure'])) {
$secure = true;
}
Comment on lines +71 to +85
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

// Auto-detect Secure from protocol; preference can only force it ON, never OFF
$secure = (XOOPS_PROT === 'https://');
if (!empty($xoopsConfig['session_cookie_secure'])) {
$secure = true;
}

// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
}

@mambax7 mambax7 requested a review from Copilot March 15, 2026 12:58
@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
upgrade/upd_2.5.11-to-2.5.12/index.php (2)

248-250: ⚠️ Potential issue | 🟠 Major

Handle DELETE failure before reinserting options.

DELETE FROM configoption result is not checked. If it fails, migration can proceed and still return success in a partially failed state.

🔧 Proposed fix
-        $db->exec("DELETE FROM `{$optionTable}` WHERE conf_id = {$confId}");
+        if (!$db->exec("DELETE FROM `{$optionTable}` WHERE conf_id = {$confId}")) {
+            $this->logs[] = "Failed to reset SameSite options for conf_id {$confId}: " . $db->error();
+            return false;
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@upgrade/upd_2.5.11-to-2.5.12/index.php` around lines 248 - 250, The DELETE
that removes existing config options for SameSite uses $db->exec("DELETE FROM
`{$optionTable}` WHERE conf_id = {$confId}") but its result isn't checked;
modify the migration to capture the return value/rowcount from $db->exec (or
check $db->errorInfo()/lastError) after the DELETE for $confId (derived from
$sameSiteRow) and if it indicates failure or zero rows when rows were expected,
abort the migration (return/throw) and log or surface the DB error so
reinsertion of options for $confId does not proceed on a failed delete.

195-203: ⚠️ Potential issue | 🟠 Major

check_addsessioncookieprefs() can return true with wrong option values.

The query only checks option count (>= 3), so any three rows pass even if Lax/Strict/None are missing or corrupted. Tighten to required values with COUNT(DISTINCT ...) = 3.

🔧 Proposed fix
-        $sql = "SELECT COUNT(*) FROM `" . $db->prefix('configoption') . "` co"
+        $sql = "SELECT COUNT(DISTINCT co.confop_value) FROM `" . $db->prefix('configoption') . "` co"
             . " INNER JOIN `" . $db->prefix('config') . "` c ON co.conf_id = c.conf_id"
-            . " WHERE c.conf_name = 'session_cookie_samesite' AND c.conf_modid = 0";
+            . " WHERE c.conf_name = 'session_cookie_samesite' AND c.conf_modid = 0"
+            . " AND co.confop_value IN ('Lax', 'Strict', 'None')";
@@
-        return $row && (int) $row[0] >= 3;
+        return $row && (int) $row[0] === 3;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@upgrade/upd_2.5.11-to-2.5.12/index.php` around lines 195 - 203, The
check_addsessioncookieprefs() currently counts rows and can return true for any
three rows; fix it by changing the SQL to verify the three required option
values explicitly: use COUNT(DISTINCT co.conf_value) with a WHERE ... AND
co.conf_value IN ('Lax','Strict','None') (or equivalent normalized values) and
compare to = 3, then fetch the row as before; update the $sql string near the
existing $sql/$db->query/$db->fetchRow usage so the function only returns true
when all three distinct expected values exist.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@htdocs/kernel/session.php`:
- Around line 69-92: Add unit tests for session cookie option resolution around
the $sameSite and $secure logic in session.php: write tests that (1) pass an
invalid session_cookie_samesite value and assert $sameSite falls back to 'Lax'
and is passed to session_set_cookie_params, (2) set session_cookie_samesite to
'None' and assert the resulting options have 'secure' === true, and (3) verify
HTTPS auto-detection by toggling XOOPS_PROT between 'https://' and 'http://'
with session_cookie_secure set to false/0 and asserting 'secure' is true only
when XOOPS_PROT === 'https://'; call the code path that builds $options and
inspect the array passed to session_set_cookie_params or provide a hook to
return options for assertion.

---

Duplicate comments:
In `@upgrade/upd_2.5.11-to-2.5.12/index.php`:
- Around line 248-250: The DELETE that removes existing config options for
SameSite uses $db->exec("DELETE FROM `{$optionTable}` WHERE conf_id =
{$confId}") but its result isn't checked; modify the migration to capture the
return value/rowcount from $db->exec (or check $db->errorInfo()/lastError) after
the DELETE for $confId (derived from $sameSiteRow) and if it indicates failure
or zero rows when rows were expected, abort the migration (return/throw) and log
or surface the DB error so reinsertion of options for $confId does not proceed
on a failed delete.
- Around line 195-203: The check_addsessioncookieprefs() currently counts rows
and can return true for any three rows; fix it by changing the SQL to verify the
three required option values explicitly: use COUNT(DISTINCT co.conf_value) with
a WHERE ... AND co.conf_value IN ('Lax','Strict','None') (or equivalent
normalized values) and compare to = 3, then fetch the row as before; update the
$sql string near the existing $sql/$db->query/$db->fetchRow usage so the
function only returns true when all three distinct expected values exist.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d6989ef-5be1-4158-a484-c1d9ff23e387

📥 Commits

Reviewing files that changed from the base of the PR and between 2609925 and 1210470.

📒 Files selected for processing (2)
  • htdocs/kernel/session.php
  • upgrade/upd_2.5.11-to-2.5.12/index.php

Comment on lines +69 to 92
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

// Auto-detect Secure from protocol; preference can only force it ON, never OFF
$secure = (XOOPS_PROT === 'https://');
if (!empty($xoopsConfig['session_cookie_secure'])) {
$secure = true;
}

// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
}

$options = [
'lifetime' => $lifetime,
'path' => '/',
'domain' => $cookieDomain,
'secure' => $secure,
'httponly' => true,
'samesite' => 'Lax',
'samesite' => $sameSite,
];
session_set_cookie_params($options);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add regression tests for SameSite/Secure combinations.

Please add tests for: invalid SameSite fallback to Lax, None forcing Secure=true, and HTTPS auto-detection behavior when session_cookie_secure=0.

Based on learnings: New functionality must have corresponding unit tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@htdocs/kernel/session.php` around lines 69 - 92, Add unit tests for session
cookie option resolution around the $sameSite and $secure logic in session.php:
write tests that (1) pass an invalid session_cookie_samesite value and assert
$sameSite falls back to 'Lax' and is passed to session_set_cookie_params, (2)
set session_cookie_samesite to 'None' and assert the resulting options have
'secure' === true, and (3) verify HTTPS auto-detection by toggling XOOPS_PROT
between 'https://' and 'http://' with session_cookie_secure set to false/0 and
asserting 'secure' is true only when XOOPS_PROT === 'https://'; call the code
path that builds $options and inspect the array passed to
session_set_cookie_params or provide a hook to return options for assertion.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable session cookie attributes (SameSite + Secure) to XOOPS core, wiring them into new installs and the 2.5.11→2.5.12 upgrade path so admins can control cookie policy via system preferences.

Changes:

  • Add an upgrade task to create session_cookie_samesite / session_cookie_secure preferences (and SameSite options) for existing installs.
  • Add English admin preference strings for the new settings.
  • Update the session handler to derive samesite/secure cookie params from preferences (including forcing Secure when SameSite=None).
  • Seed the new config rows/options during installation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
upgrade/upd_2.5.11-to-2.5.12/index.php Adds upgrade task to insert the new config entries and SameSite options.
htdocs/modules/system/language/english/admin/preferences.php Adds preference titles/descriptions for the new session cookie settings.
htdocs/kernel/session.php Uses the new preferences to set session cookie parameters.
htdocs/install/include/makedata.php Seeds the new config rows and configoption values on fresh installs.

Comment on lines +217 to +240
// Insert SameSite preference (skip if exists)
$sql = "SELECT conf_id FROM `{$configTable}` WHERE conf_name = 'session_cookie_samesite' AND conf_modid = 0";
$result = $db->query($sql);
$sameSiteRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;

if (!$sameSiteRow) {
if (!$db->exec("INSERT INTO `{$configTable}` (conf_modid, conf_catid, conf_name, conf_title, conf_value, conf_desc, conf_formtype, conf_valuetype, conf_order) VALUES (0, 1, 'session_cookie_samesite', '_MD_AM_SESSSAMESITE', 'Lax', '_MD_AM_SESSSAMESITE_DSC', 'select', 'text', 43)")) {
$this->logs[] = 'Failed to insert session_cookie_samesite config: ' . $db->error();
return false;
}
// Re-fetch the conf_id
$result = $db->query($sql);
$sameSiteRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;
if (!$sameSiteRow) {
$this->logs[] = 'Failed to retrieve session_cookie_samesite conf_id after insert';
return false;
}
}

// Insert Secure preference (skip if exists)
$sql = "SELECT conf_id FROM `{$configTable}` WHERE conf_name = 'session_cookie_secure' AND conf_modid = 0";
$result = $db->query($sql);
$secureRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;


// Add select options for SameSite — delete and recreate to avoid duplicates
$confId = (int) $sameSiteRow[0];
$db->exec("DELETE FROM `{$optionTable}` WHERE conf_id = {$confId}");
$confId = (int) $sameSiteRow[0];
$db->exec("DELETE FROM `{$optionTable}` WHERE conf_id = {$confId}");
foreach (['Lax', 'Strict', 'None'] as $opt) {
if (!$db->exec("INSERT INTO `{$optionTable}` (confop_name, confop_value, conf_id) VALUES ('{$opt}', '{$opt}', {$confId})")) {
Comment on lines +69 to 91
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

// Auto-detect Secure from protocol; preference can only force it ON, never OFF
$secure = (XOOPS_PROT === 'https://');
if (!empty($xoopsConfig['session_cookie_secure'])) {
$secure = true;
}

// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
}

$options = [
'lifetime' => $lifetime,
'path' => '/',
'domain' => $cookieDomain,
'secure' => $secure,
'httponly' => true,
'samesite' => 'Lax',
'samesite' => $sameSite,
];
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable session cookie attributes to XOOPS Core 2.5.12, wiring new preferences into installation defaults, the 2.5.11→2.5.12 upgrade path, and the runtime session cookie configuration.

Changes:

  • Add new core preferences for session_cookie_samesite and session_cookie_secure (installer seed + upgrade task).
  • Update session handler to apply SameSite/Secure cookie params based on preferences with sensible defaults.
  • Add English admin preference labels/descriptions for the new settings.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
upgrade/upd_2.5.11-to-2.5.12/index.php Adds an upgrade task to create the new config rows/options for existing installations.
htdocs/modules/system/language/english/admin/preferences.php Adds language constants for the new session cookie preferences.
htdocs/kernel/session.php Applies SameSite/Secure cookie params from XOOPS preferences when configuring session cookies.
htdocs/install/include/makedata.php Seeds fresh installs with the new config rows and SameSite select options.

Comment on lines +218 to +220
$sql = "SELECT conf_id FROM `{$configTable}` WHERE conf_name = 'session_cookie_samesite' AND conf_modid = 0";
$result = $db->query($sql);
$sameSiteRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;
Comment on lines +237 to +239
$sql = "SELECT conf_id FROM `{$configTable}` WHERE conf_name = 'session_cookie_secure' AND conf_modid = 0";
$result = $db->query($sql);
$secureRow = ($db->isResultSet($result) && ($result instanceof \mysqli_result)) ? $db->fetchRow($result) : false;
Comment on lines +194 to +203
// Check SameSite options exist (Lax, Strict, None)
$sql = "SELECT COUNT(*) FROM `" . $db->prefix('configoption') . "` co"
. " INNER JOIN `" . $db->prefix('config') . "` c ON co.conf_id = c.conf_id"
. " WHERE c.conf_name = 'session_cookie_samesite' AND c.conf_modid = 0";
$result = $db->query($sql);
if (!$db->isResultSet($result) || !($result instanceof \mysqli_result)) {
return false;
}
$row = $db->fetchRow($result);
return $row && (int) $row[0] >= 3;

// Add select options for SameSite — delete and recreate to avoid duplicates
$confId = (int) $sameSiteRow[0];
$db->exec("DELETE FROM `{$optionTable}` WHERE conf_id = {$confId}");
Comment on lines +79 to +81
// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
Comment on lines +69 to +82
// Resolve SameSite and Secure from XOOPS config preferences
$sameSite = isset($xoopsConfig['session_cookie_samesite']) ? (string) $xoopsConfig['session_cookie_samesite'] : 'Lax';
$sameSite = in_array($sameSite, ['Lax', 'Strict', 'None'], true) ? $sameSite : 'Lax';

// Auto-detect Secure from protocol; preference can only force it ON, never OFF
$secure = (XOOPS_PROT === 'https://');
if (!empty($xoopsConfig['session_cookie_secure'])) {
$secure = true;
}

// Browsers require Secure when SameSite=None
if ($sameSite === 'None') {
$secure = true;
}
@mambax7 mambax7 merged commit e489500 into XOOPS:master Mar 15, 2026
18 of 19 checks passed
@mambax7 mambax7 deleted the fix/session-samesite-preference branch March 15, 2026 13:50
@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (9075584) to head (1210470).
⚠️ Report is 35 commits behind head on master.

Additional details and impacted files
@@      Coverage Diff       @@
##   master   #1660   +/-   ##
==============================
==============================

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: XOOPS 2.5.11 session handling too strict?

2 participants