Bug Report
Summary
A PHP fatal error (HTTP 500) occurs when a logged-in user with an existing session (one that pre-dates CSRF token generation, or after a partial session reset) tries to submit any form containing a CSRF token field.
Steps to Reproduce
- Have a user with an active session (
$_SESSION['client_logged_in'] = true) that does not contain a csrf_token key.
- Navigate to
/client/ticket_add.php (or any page rendering <?= $_SESSION['csrf_token'] ?>).
- Submit the form.
Expected Behaviour
User is redirected with a friendly "session expired" message and prompted to retry.
Actual Behaviour
PHP Fatal Error → HTTP 500:
PHP Warning: Undefined array key "csrf_token" in client/ticket_add.php on line 28
PHP Warning: Undefined array key "csrf_token" in functions.php on line 650
PHP Fatal error: Uncaught TypeError: hash_equals(): Argument #2 ($user_string) must be of type string, null given in functions.php:650
Root Cause
$_SESSION['csrf_token'] is only set in login.php after a successful login. Neither includes/check_login.php nor client/includes/check_login.php check for or regenerate a missing token. validateCSRFToken() in functions.php passes the value directly to hash_equals() with no null/type guard, causing a fatal TypeError when the token is null.
Affected Files
functions.php — validateCSRFToken() lacks a null/type check before hash_equals()
includes/check_login.php — never regenerates a missing CSRF token for active sessions
client/includes/check_login.php — same issue
Suggested Fix
1. Add a null guard to validateCSRFToken() in functions.php:
function validateCSRFToken($token)
{
if (!is_string($token) || empty($token) || empty($_SESSION['csrf_token'])) {
$_SESSION['alert_type'] = 'warning';
$_SESSION['alert_message'] = 'Your session has expired or is invalid. Please try again.';
header('Location: index.php');
exit();
}
if (hash_equals($_SESSION['csrf_token'], $token)) {
return true;
} else {
$_SESSION['alert_type'] = 'warning';
$_SESSION['alert_message'] = 'CSRF token verification failed. Try again, or log out to refresh your token.';
header('Location: index.php');
exit();
}
}
2. Ensure the token is always present at session check time (both check_login.php files):
// At the end of check_login.php, after all session validation passes:
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = randomString(32);
}
Environment
- ITFlow self-hosted (latest stable)
- PHP 8.x
- Reproducible on the client portal (
/client/) — likely also affects the agent portal for the same reason.
Bug Report
Summary
A PHP fatal error (HTTP 500) occurs when a logged-in user with an existing session (one that pre-dates CSRF token generation, or after a partial session reset) tries to submit any form containing a CSRF token field.
Steps to Reproduce
$_SESSION['client_logged_in'] = true) that does not contain acsrf_tokenkey./client/ticket_add.php(or any page rendering<?= $_SESSION['csrf_token'] ?>).Expected Behaviour
User is redirected with a friendly "session expired" message and prompted to retry.
Actual Behaviour
PHP Fatal Error → HTTP 500:
Root Cause
$_SESSION['csrf_token']is only set inlogin.phpafter a successful login. Neitherincludes/check_login.phpnorclient/includes/check_login.phpcheck for or regenerate a missing token.validateCSRFToken()infunctions.phppasses the value directly tohash_equals()with no null/type guard, causing a fatal TypeError when the token is null.Affected Files
functions.php—validateCSRFToken()lacks a null/type check beforehash_equals()includes/check_login.php— never regenerates a missing CSRF token for active sessionsclient/includes/check_login.php— same issueSuggested Fix
1. Add a null guard to
validateCSRFToken()infunctions.php:2. Ensure the token is always present at session check time (both
check_login.phpfiles):Environment
/client/) — likely also affects the agent portal for the same reason.