Search code examples
phpcodeignitercodeigniter-4sanitization

Best practice when sanitizing HTML form user input in PHP / CodeIgniter 4


I have a simple app programmed in PHP using CodeIgniter 4 framework and, as a web application, it has some HTML forms for user input.

I am doing two things:

  1. In my Views, all variables from the database that come from user input are sanitized using CodeIgniter 4's esc() function.

  2. In my Controllers, when reading HTTP POST data, I am using PHP filters:

    $data = trim($this->request->getPost('field', FILTER_SANITIZE_SPECIAL_CHARS));

I am not sure if sanitizing both when reading data from POST and when printing/displaying to HTML is a good practice or if it should only be sanitized once.

In addition, FILTER_SANITIZE_SPECIAL_CHARS is not working as I need. I want my HTML form text input to prevent users from attacking with HTML but I want to keep some 'line breaks' my database has from the previous application.

FILTER_SANITIZE_SPECIAL_CHARS will NOT delete HTML tags, it will just store them in the database, not as HTML, but it is also changing my 'line breaks'. Is there a filter that doesn't remove HTML tags (only stores them with proper condification) but that respects \n 'line breaks'?


Solution

  • You don't need to sanitize User input data as explained in the question below:

    How can I sanitize user input with PHP?

    It's a common misconception that user input can be filtered. PHP even has a (now deprecated) "feature", called magic-quotes, that builds on this idea. It's nonsense. Forget about filtering (or cleaning, or whatever people call it).

    In addition, you don't need to use FILTER_SANITIZE_SPECIAL_CHARS, htmlspecialchars(...), htmlentities(...), or esc(...) either for most use cases:

    -Comment from OP (user1314836)

    I definitely think that I don't need to sanitize user-input data because I am not writing SQL directly but rather using CodeIgniter 4's functions to create SQL safe queries. On the other hand, I do definitely need to esc() that same information when showing to avoid showing html where just text is expected.

    The reason why you don't need the esc() method for most use cases is:

    Most User form input in an application doesn't expect a User to submit/post HTML, CSS, or JavaScript that you plan on displaying/running later on.

    If the expected User input is just plain text (username, age, birth date, etc), images, or files, use form validation instead to disallow unexpected data.

    I.e: Available Rules and Creating Custom Rules

    By using the Query Builder for your database queries and rejecting unexpected User input data using validation rules (alpha, alpha_numeric_punct, numeric, exact_length, min_length[8], valid_date, regex_match[/regex/], uploaded, etc), you can avoid most potential security holes i.e: SQL injections and XSS attacks.