Input and Data Security (CSRF, XSS)
Relevant source files
The following files were used as context for generating this wiki page:
CodeIgniter 4 provides a robust set of features to help developers secure their applications against common threats like Cross-Site Request Forgery (CSRF) and Cross-Site Scripting (XSS). These protections are integrated into the framework through a combination of the Security Library, input filtering mechanisms, and helper functions. The primary goal is to provide tools for both preventing malicious data from being submitted and for safely rendering user-provided content.
The framework's approach emphasizes filtering data at the point of input or output, rather than relying solely on global, automatic filters. While some global protections exist, the recommended practice is to be explicit about security, especially for XSS protection, by cleaning data just before it is used. CSRF protection, on the other hand, is implemented as a filter that runs for all POST, PUT, PATCH, and DELETE requests to prevent unauthorized commands from being executed on behalf of an authenticated user.
Sources: user_guide_src/source/general/security.rst:1-19, user_guide_src/source/libraries/security.rst:1-10
Cross-Site Request Forgery (CSRF) Protection
CSRF protection in CodeIgniter 4 works by adding a hidden token to all forms, which is then validated upon submission. This ensures that the request originated from the application itself and not from a malicious external site. This protection is enabled by default for all POST, PUT, PATCH, and DELETE requests.
Sources: user_guide_src/source/general/security.rst:21-27
Enabling CSRF Protection
CSRF protection is managed by the CSRF filter, which is enabled by default in the $globals property of app/Config/Filters.php.
public array $globals = [
'before' => [
// 'honeypot',
'csrf',
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];
To disable it, you can remove 'csrf' from the before array.
Sources: user_guide_src/source/general/security.rst:32-49
Configuration
CSRF settings are configured in the app/Config/Security.php file.
| Property | Type | Default | Description |
|---|---|---|---|
$tokenName | string | 'csrf_token_name' | The name of the CSRF token. |
$headerName | string | 'X-CSRF-TOKEN' | The name of the HTTP header for AJAX requests. |
$cookieName | string | 'csrf_cookie_name' | The name of the cookie that stores the token. |
$expires | int | 7200 | The number of seconds the token is valid for (2 hours). |
$regenerate | bool | true | Whether to regenerate the token on every submission. |
$redirect | bool | false | Whether to redirect on failure. If false, a SecurityException is thrown. |
$samesite | string | 'Lax' | The SameSite setting for the CSRF cookie ('Lax', 'Strict', or 'None'). |
Sources: user_guide_src/source/installation/app_settings.rst:139-160, user_guide_src/source/general/security.rst:104-110
Implementation in Forms
To add the CSRF token to your HTML forms, use the csrf_field() function from the Form Helper. This function generates a hidden input field with the current CSRF token.
<form action="/foo/bar" method="post">
<?= csrf_field() ?>
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
This will render the following HTML:
<input type="hidden" name="csrf_token_name" value="813a4e703871a484a3f83355554de33c">
For AJAX requests, the token can be fetched from the CSRF cookie and sent in the X-CSRF-TOKEN header.
Sources: user_guide_src/source/helpers/form_helper.rst:117-124, user_guide_src/source/general/security.rst:51-68
CSRF Protection Flow
The following diagram illustrates the sequence of events for CSRF validation.
This diagram shows how a token is generated for a form, sent to the user, and then validated on a subsequent POST request.
Sources: user_guide_src/source/general/security.rst:21-27, 85-91
Cross-Site Scripting (XSS) Protection
XSS protection involves filtering user-submitted data to remove malicious scripts before it is displayed. CodeIgniter provides the Security library for this purpose. The framework's philosophy is to filter data on output, not on input, to maintain the integrity of the original data.
Sources: user_guide_src/source/general/security.rst:120-129
The Security Library
The Security library contains methods to help sanitize data. The primary method for XSS filtering is clean().
You can access the library through the Services class:
$security = \Config\Services::security();
To filter a piece of data, pass it to the clean() method:
$data = $security->clean($data);
The clean() method can handle strings, arrays, and objects, recursively cleaning all elements.
Sources: user_guide_src/source/libraries/security.rst:1-25
XSS Filtering Process
The clean() method performs several actions to neutralize potential XSS attacks:
- Converts special HTML characters (
&,<,>,",') to entities. - Removes invisible characters.
- Strips
<img>tags of any non-essential attributes. - Filters out dangerous keywords like
javascript,expression,eval, etc.
The following diagram shows the data flow for XSS cleaning.
This flowchart illustrates how the clean() method processes input to produce safe output.
Sources: user_guide_src/source/libraries/security.rst:12-25
General Input Data Handling
CodeIgniter's IncomingRequest class provides a secure way to access input data like $_POST, $_GET, and $_SERVER. It is recommended to use the request object's methods instead of accessing superglobals directly.
Sources: user_guide_src/source/incoming/incomingrequest.rst:1-12
Retrieving Input
The getVar() method is the primary way to fetch input data. It can retrieve data from $_POST, $_GET, $_COOKIE, and php://input.
$request = \Config\Services::request();
// Get a value from $_REQUEST
$foo = $request->getVar('foo');
// Get a value from $_POST only
$bar = $request->getPost('bar');
// Get a value from $_GET only
$baz = $request->getGet('baz');
Sources: user_guide_src/source/incoming/incomingrequest.rst:134-158
Filtering Input Data
The getVar() method allows for data filtering as a second argument. This uses PHP's native filter_var() function.
$request = \Config\Services::request();
// Get a sanitized email address
$email = $request->getVar('email', FILTER_SANITIZE_EMAIL);
// Get an integer
$id = $request->getVar('id', FILTER_SANITIZE_NUMBER_INT);
This provides a convenient way to sanitize data at the point of retrieval.
| Filter | Description |
|---|---|
FILTER_SANITIZE_EMAIL | Removes all characters except letters, digits and !#$%&'*+-/=?^_{ |
FILTER_SANITIZE_ENCODED | URL-encodes string, optionally strips or encodes special characters. |
FILTER_SANITIZE_NUMBER_FLOAT | Remove all characters except digits, +- and optionally .,eE. |
FILTER_SANITIZE_NUMBER_INT | Remove all characters except digits, plus and minus sign. |
FILTER_SANITIZE_SPECIAL_CHARS | HTML-escapes ' " < > & and characters with ASCII value less than 32. |
FILTER_SANITIZE_STRING | (Deprecated in PHP 8) Strips tags and HTML-encodes special characters. |
FILTER_SANITIZE_URL | Remove all characters except letters, digits and `$-_.+!*'(),{} |
Sources: user_guide_src/source/incoming/incomingrequest.rst:175-195
Conclusion
CodeIgniter 4 provides a multi-layered approach to input and data security. CSRF protection is enabled by default and seamlessly integrated into the framework's request lifecycle. For XSS, the framework encourages a deliberate, context-aware filtering strategy using the Security library on output. Combined with the secure input retrieval methods of the IncomingRequest class, developers have a powerful toolkit to build secure web applications and mitigate common vulnerabilities.
Sources: user_guide_src/source/general/security.rst, user_guide_src/source/libraries/security.rst