PHP Session
debt(d7/e3/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). While semgrep and phpcs can flag missing session_regenerate_id or insecure cookie flags, misconfiguration in php.ini and missing hardening typically only surface in security review or pentesting — production silently accepts insecure sessions.
Closest to 'simple parameterised fix' (e3). The quick_fix is a handful of ini settings plus a session_regenerate_id(true) call on login — small, parameterised changes, but touches both config and login flow rather than a single line.
Closest to 'persistent productivity tax' (b5). Sessions are load-bearing for authentication across the entire web context (applies_to: web); every auth-related feature, logout flow, and security review must account for session semantics, but it doesn't define the system's overall shape.
Closest to 'serious trap' (t7). The misconception is explicit: developers assume sessions are secure by default when in fact PHPSESSID, /tmp storage, and absent Secure/HttpOnly flags make defaults dangerous — contradicts the reasonable expectation that a built-in session API would be hardened.
Also Known As
TL;DR
Explanation
PHP sessions store data server-side ($_SESSION) and associate it with a session ID transmitted via a cookie. Because the data lives on the server, the client cannot tamper with it — making sessions the correct location for auth state (logged-in user ID, role, CSRF token). session_start() must be called before any output. Use session_regenerate_id(true) after login to prevent session fixation. Configure the session cookie with HttpOnly, Secure, and SameSite=Strict.
Diagram
sequenceDiagram
participant B as Browser
participant PHP as PHP
participant STORE as Session Store
B->>PHP: First request
PHP->>STORE: Create session data
STORE-->>PHP: session_id abc123
PHP-->>B: Set-Cookie: PHPSESSID=abc123
B->>PHP: Next request + cookie
PHP->>STORE: Load session abc123
STORE-->>PHP: Session data
PHP-->>B: Response using session data
Note over PHP,STORE: session_regenerate_id after login
Note over PHP,STORE: Prevents session fixation
Common Misconception
Why It Matters
Common Mistakes
- Not calling session_regenerate_id(true) after login — leaves old session ID valid for fixation attacks.
- Not setting session.cookie_httponly, session.cookie_secure, and session.cookie_samesite.
- Storing sensitive data like plaintext passwords in the session.
- Not destroying the session completely on logout — session_destroy() alone does not unset the cookie.
Code Examples
// Insecure session start — default settings:
session_start(); // No secure flags, no regeneration
$_SESSION['user_id'] = $user->id;
// Secure:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Lax');
session_start();
session_regenerate_id(true); // After login
// Secure session configuration (php.ini or ini_set before session_start)
ini_set('session.cookie_httponly', 1); // JS cannot read cookie
ini_set('session.cookie_secure', 1); // HTTPS only
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.use_strict_mode', 1); // reject unrecognised session IDs
ini_set('session.gc_maxlifetime', 1800); // 30 min idle timeout
session_start();
// After login — always regenerate to prevent session fixation
session_regenerate_id(true);
$_SESSION['user_id'] = $user->id;
$_SESSION['role'] = $user->role;
// Destroy on logout
$_SESSION = [];
session_destroy();
setcookie(session_name(), '', time() - 3600, '/'); // clear cookie