CSRF Header - Not enabled in the system/core/security code?

Author: gidzrCreated Jan 29, 2025Updated Apr 15, 2025

Hey @narfbg

Still loving CI3.. but every now and then something crops up that maybe it's me or maybe a bug..

I was struggling to get Fetch working with CSRF when data sent as a stringified json object.. presumable because $this->input library is required to intercept and hasn't yet run or placed this into the $_POST superglobal.. ie.. which I would interpret as a php problem.

I thought the Header method for CSRF should resolve this.. but wasn't working.. So I went into the Security class under system/core and noticed a) there is NO CSRF check on the Headers in the verification function b) when print_r/var_dump $_POST super with the stringified json body, $POST is empty

system/core/Security.php, at line

209:	public function csrf_verify()

230:		// Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
		$valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
			&& is_string($_POST[$this->_csrf_token_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])
			&& hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);

So I created this as a quick patch to check the HEADER, and now everything works..

	// Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
	$valid1 = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
		&& is_string($_POST[$this->_csrf_token_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])
		&& hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);

	$valid2 = isset($_SERVER['HTTP_X_CSRF_TOKEN'], $_COOKIE[$this->_csrf_cookie_name])
		&& is_string($_SERVER['HTTP_X_CSRF_TOKEN']) && is_string($_COOKIE[$this->_csrf_cookie_name])
		&& hash_equals($_SERVER['HTTP_X_CSRF_TOKEN'], $_COOKIE[$this->_csrf_cookie_name]);


	$valid = $valid1 || $valid2;

Please let me know if its an oversight skipping the header or have I misused CI?