{"id":195,"date":"2025-08-26T14:59:13","date_gmt":"2025-08-26T14:59:13","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=195"},"modified":"2025-08-26T14:59:14","modified_gmt":"2025-08-26T14:59:14","slug":"how-to-prevent-csrf-xss-and-sql-injection-in-laravel-apps","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/how-to-prevent-csrf-xss-and-sql-injection-in-laravel-apps\/","title":{"rendered":"How to Prevent CSRF, XSS, and SQL Injection in Laravel Apps"},"content":{"rendered":"\n<p>Every modern web application faces security threats. Three of the most common and dangerous ones are <strong>CSRF (Cross-Site Request Forgery)<\/strong>, <strong>XSS (Cross-Site Scripting)<\/strong>, and <strong>SQL Injection<\/strong>. If left unprotected, attackers can hijack sessions, steal data, or even take control of your application.<\/p>\n\n\n\n<p>The good news: <strong>Laravel 12 comes with built-in protection<\/strong> against these attacks. In this article, we\u2019ll break down what each attack means, why it\u2019s dangerous, and how to prevent it in Laravel step by step. You\u2019ll also see code examples and best practices so you can secure your apps confidently.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1 &#8211; What is CSRF (Cross-Site Request Forgery)?<\/strong><\/h2>\n\n\n\n<p><strong>CSRF<\/strong> happens when an attacker tricks a logged-in user into making an unwanted request to your app. For example, they might embed a hidden form on a malicious website that submits a <code>POST<\/code> request to your app\u2019s <code>\/delete-account<\/code> endpoint. If the user is logged in, the request could succeed \u2014 unless you protect against it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How Laravel Prevents CSRF<\/strong><\/h3>\n\n\n\n<p>Laravel includes a CSRF token with every form. This unique token must match the one stored in the session; otherwise, the request is rejected.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!-- Example Blade form with CSRF protection --&gt;\n&lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"\/profile\/update\"<\/span>&gt;\n    @csrf\n    &lt;input type=<span class=\"hljs-string\">\"text\"<\/span> name=<span class=\"hljs-string\">\"name\"<\/span>&gt;\n    &lt;button type=<span class=\"hljs-string\">\"submit\"<\/span>&gt;Save&lt;\/button&gt;\n&lt;\/form&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>@csrf<\/code> directive generates a hidden token field. Laravel validates this automatically, protecting you from CSRF attacks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Best Practices for CSRF Protection<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always include <code>@csrf<\/code> in forms.<\/li>\n<li>For SPAs, send the CSRF token in the <code>X-CSRF-TOKEN<\/code> or <code>X-XSRF-TOKEN<\/code> header.<\/li>\n<li>Do not disable CSRF middleware unless absolutely necessary.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2 &#8211; What is XSS (Cross-Site Scripting)?<\/strong><\/h2>\n\n\n\n<p><strong>XSS<\/strong> allows attackers to inject malicious JavaScript into your app. For example, if you display user-submitted comments without escaping, an attacker could inject:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"actionscript\">alert(<span class=\"hljs-string\">'Hacked!'<\/span>)<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If another user loads the page, the script executes in their browser. This could be used to steal cookies, capture keystrokes, or redirect users to malicious sites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How Laravel Prevents XSS<\/strong><\/h3>\n\n\n\n<p>By default, Laravel escapes all Blade output. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">{{ $comment }}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If <code>$comment<\/code> contains <code>&lt;script&gt;alert('XSS')&lt;\/script&gt;<\/code>, Laravel will escape it to:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-symbol\">&amp;lt;<\/span>script<span class=\"hljs-symbol\">&amp;gt;<\/span>alert('XSS')<span class=\"hljs-symbol\">&amp;lt;<\/span>\/script<span class=\"hljs-symbol\">&amp;gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This prevents execution. If you want to render HTML, you must explicitly use <code>{!! $comment !!}<\/code> \u2014 but do this only with trusted content.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Best Practices for XSS Protection<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keep default escaping (use <code>{{ }}<\/code> not <code>{!! !!}<\/code>).<\/li>\n<li>Sanitize user input before displaying it.<\/li>\n<li>Use libraries like <code>DOMPurify<\/code> on frontend if you must allow limited HTML.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3 &#8211; What is SQL Injection?<\/strong><\/h2>\n\n\n\n<p><strong>SQL Injection<\/strong> happens when user input is inserted directly into SQL queries without proper escaping. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ \u274c Vulnerable raw query<\/span>\n$user = DB::select(<span class=\"hljs-string\">\"SELECT * FROM users WHERE email = '$email'\"<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If an attacker sets <code>$email<\/code> to <code>' OR 1=1 --<\/code>, the query becomes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">SELECT * FROM users WHERE email = <span class=\"hljs-string\">''<\/span> OR <span class=\"hljs-number\">1<\/span>=<span class=\"hljs-number\">1<\/span> --<span class=\"hljs-string\">'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This would return all users \u2014 a catastrophic data leak.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How Laravel Prevents SQL Injection<\/strong><\/h3>\n\n\n\n<p>Laravel\u2019s <strong>Eloquent ORM<\/strong> and <strong>Query Builder<\/strong> use PDO parameter binding, which automatically escapes input values:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ \u2705 Safe query with parameter binding<\/span>\n$user = DB::table(<span class=\"hljs-string\">'users'<\/span>)\n          -&gt;where(<span class=\"hljs-string\">'email'<\/span>, $email)\n          -&gt;first();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures user input never breaks SQL syntax, eliminating SQL injection risks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Best Practices for SQL Injection Prevention<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always use Eloquent or Query Builder instead of raw queries.<\/li>\n<li>If raw queries are unavoidable, use bindings: <code>DB::select('... where email = ?', [$email])<\/code>.<\/li>\n<li>Validate and sanitize inputs before using them in queries.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>We covered the three most common web attacks: CSRF, XSS, and SQL Injection. Laravel 12 protects you against these by default, but only if you use its features correctly. Always include <code>@csrf<\/code> in forms, let Blade escape your output, and stick to Eloquent or Query Builder for database access. Combine these best practices, and your app will already be resilient against many real-world threats.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/how-to-expire-user-sessions-automatically-in-laravel\">How to Expire User Sessions Automatically in Laravel<\/a> \u2014 strengthen security with session timeouts.<\/li>\n<li><a href=\"\/blog\/implementing-two-factor-authentication-in-laravel\">Implementing Two-Factor Authentication in Laravel<\/a> \u2014 add another layer of login protection.<\/li>\n<li><a href=\"\/blog\/best-practices-for-storing-api-keys-securely-in-laravel\">Best Practices for Storing API Keys Securely in Laravel<\/a> \u2014 handle secrets the right way.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Every modern web application faces security threats. Three of the most common and dangerous ones are CSRF (Cross-Site Request Forgery), XSS (Cross-Site Scripting), and SQL Injection. If left unprotected, attackers can hijack sessions, steal data, or even take control of your application. The good news: Laravel 12 comes with built-in protection against these attacks. In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":199,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[27,22,26,28],"class_list":["post-195","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-csrf","tag-security","tag-sql-injection","tag-xss"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=195"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/195\/revisions"}],"predecessor-version":[{"id":198,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/195\/revisions\/198"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/199"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}