All Articles

Web Security, XSS & CSRF Mitigation. Adding security headers to your application.

Cross-site scripting (XSS) and cross-site request forgery (CSRF) are two of the most common security issues in modern web applications. Both exploit weaknesses in how user input is handled or how browser requests are trusted. Mitigating these risks involves a mix of input validation, session control, and proper HTTP headers.

Web application firewall concept

What is XSS?

XSS happens when an attacker injects malicious scripts into web pages viewed by other users. If the application doesn’t sanitize input properly, the script runs in the browser of anyone who loads the page.

Common Example

A blog comment section that doesn’t escape <script> tags may allow someone to submit this:

<script>
  alert("Hacked!")
</script>

When another user loads the page, the script runs in their browser.

How to Prevent XSS

  • Always encode or escape user input.
  • Use libraries or frameworks that auto-escape HTML (like React or Django templates).
  • Set the Content-Security-Policy (CSP) header to restrict allowed sources of scripts.

What is CSRF?

CSRF tricks users into submitting unintended requests. For example, if a user is logged into a banking app, an attacker could get them to click a hidden form that transfers money without their knowledge.

Common Example

A malicious site could embed this HTML:

<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="amount" value="1000" />
  <input type="hidden" name="to" value="attacker_account" />
  <input type="submit" />
</form>

If the user is logged in, the browser may send cookies with the request, making it look legitimate.

How to Prevent CSRF

  • Use anti-CSRF tokens in forms.
  • Validate the Origin and Referer headers.
  • Set cookies with the SameSite attribute (SameSite=Lax or SameSite=Strict).

Adding Security Headers

HTTP security headers provide an extra layer of defense. They are sent with responses and tell the browser how to behave.

  • Content-Security-Policy: Controls which scripts can run.
  • X-Content-Type-Options: nosniff: Stops MIME-type sniffing.
  • X-Frame-Options: DENY: Prevents clickjacking.
  • Referrer-Policy: no-referrer: Limits information leakage.
  • Strict-Transport-Security: Enforces HTTPS.

Example Configuration NGINX

add_header Content-Security-Policy "default-src 'self'";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header Referrer-Policy "no-referrer";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Final Thoughts

Web security is not just about fixing bugs. It’s about reducing attack surface. XSS and CSRF can be avoided with the right input handling and browser-side controls. Use headers to reinforce trust, and never assume browsers will protect your users by default.

Published Sep 4, 2023

Hey there! I'm Hemense, a Frontend Developer with 4 years of experience developing scalable, high-performance web applications in SaaS, fintech, ERP, and AI-driven solutions. I am skilled in building component-driven architectures, improving user engagement, reducing churn, and optimizing platform performance for revenue growth. I have experience with React, TypeScript and its ecosystem. I am passionate about data- driven development, design systems, and engineering best practices to drive impactful user experiences.