"I just escape quotes": why your code is vulnerable
\n\nIf you've ever Googled "How can I sanitize user input with PHP?", you're not alone. This question on Stack Overflow has gathered hundreds of thousands of views. And it's no surprise: the topic of security is one of the hottest in web development.
\n\nBut here's the paradox: most answers to that question are either outdated or dangerous. Developers still write something like mysql_real_escape_string() (which hasn't existed for 10 years) or simply remove "dangerous" characters. Spoiler: it doesn't work.
In this article, we'll break down the top 5 mistakes in sanitizing user input in PHP that turn your site into a sieve, and show you how to fix them once and for all.
\n\nMistake #1: Blind faith in "sanitization" as a universal cure-all
\n\nThe biggest mistake is thinking there is one function that will "clean" any data. Here's typical beginner code:
\n\n<?php\n$name = $_POST['name'];\n$name = strip_tags($name);\n$name = addslashes($name);\n// Is the data safe now? No!\n?>\n\nThe problem is that different contexts require different processing. Validation (format checking) and sanitization (cleaning) are not the same thing. And there's also output escaping, which happens in a completely different place.
\n\nWhat to do: Determine what you are doing with the data at each stage. One thing for the database, another for HTML, and a third for JSON.
\n\nMistake #2: Using outdated functions (or using them incorrectly)
\n\nLet's go through the "dinosaurs" of PHP security:
\n\n- \n
mysql_real_escape_string()— removed in PHP 7.0. Forget it. \n addslashes()— does not protect against all SQL injections, especially with multi-byte encodings. \n strip_tags()— removes tags but does not escape output. XSS is still possible via attributes. \n
Example of dangerous code that is still found:
\n\n<?php\n$id = $_GET['id'];\n$id = addslashes($id);\n$query = "SELECT * FROM users WHERE id = '$id'";\n// If id = 1 OR 1=1 -- you've been hacked\n?>\n\nWhat to do: Use prepared statements. This is the only reliable way to protect against SQL injections.
\n\n<?php\n$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");\n$stmt->execute(['id' => $_GET['id']]);\n?>\n\nSee? No sanitization for SQL. Just parameters. The database itself will figure out what is data and what is a command.
\n\nMistake #3: Confusing validation and sanitization
\n\nMany think: "I'll remove all suspicious characters, and it will be safe." But this breaks the application logic. Imagine a user entered the password P@ssw0rd!, and you removed the @ and ! characters. The password becomes Pssw0rd — and the user can no longer log in.
Validation — checks if the input matches the expected format (email, number, URL). If not — reject it.
\n\nSanitization — removes or modifies unwanted characters, but only when it's really necessary (e.g., for a filename).
\n\nExample of correct email validation:
\n\n<?php\n$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);\nif ($email === false) {\n // Email is invalid — do not save, do not output\n echo "Enter a valid email";\n exit;\n}\n// Now $email is a safe string for any purpose\n?>\n\nGolden rule: If you expect a number — check that it's a number. If an email — check the format. Everything else — reject it.
\n\nMistake #4: Ignoring the output context (XSS)
\n\nYou saved the data to the database using prepared statements. Hooray, no SQL injections. But