Security

Fundamental Security in Frontend Engineering

Security is not just a backend concern. Frontend engineers make security-critical decisions on every feature they build. Learn the essential vulnerabilities, attack vectors, and defenses every frontend developer must know.

July 8, 202610 min read
Fundamental Security in Frontend Engineering

Fundamental Security in Frontend Engineering

Security is often treated as a backend problem. It is not.

Frontend engineers make security-relevant decisions dozens of times per day — where to store a token, how to render user content, what to include in a third-party script. A single misstep can expose user data, allow account takeover, or enable an attacker to execute arbitrary code on behalf of your users.

This article covers the security fundamentals that every frontend engineer must internalize.


1. Cross-Site Scripting (XSS)

XSS is the most prevalent web vulnerability. An attacker injects malicious scripts into your application, which then execute in other users' browsers — stealing cookies, hijacking sessions, or exfiltrating data.

Types of XSS

Stored XSS: Malicious script is saved in your database (e.g., in a comment or profile bio) and served to every user who visits that page.

Reflected XSS: Malicious script is embedded in a URL parameter and reflected back in the response (common in search results pages).

DOM-based XSS: The attack happens entirely in the browser — your JavaScript reads from a dangerous source (like location.hash) and writes it to the DOM.

Defense

// ❌ Never do this — dangerouslySetInnerHTML without sanitization
<div dangerouslySetInnerHTML={{ __html: userInput }} />

// ✅ Sanitize before rendering untrusted HTML
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

// ✅ Or better — render as text, not HTML
<p>{userInput}</p>

React's JSX escapes string output by default. The dangerous path is dangerouslySetInnerHTML — treat it as exactly as dangerous as its name implies.


2. Content Security Policy (CSP)

A Content Security Policy is an HTTP header that tells the browser which sources are trusted for scripts, styles, images, and other resources. It's one of the most powerful XSS mitigations available.

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self' https://cdn.trusted.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.yourdomain.com;

A strict CSP blocks inline scripts and limits external script sources — even if an attacker manages to inject a <script> tag, it won't execute if it violates your policy.

Avoid unsafe-inline and unsafe-eval unless absolutely necessary. They significantly weaken your policy.


3. Cross-Site Request Forgery (CSRF)

CSRF tricks an authenticated user's browser into sending an unwanted request to your server. A malicious page submits a form that targets your API — and because the browser includes the user's cookies automatically, your server may accept it.

Defense

  • Same-Site cookies: Set your auth cookies with SameSite=Lax or SameSite=Strict. This prevents cross-site requests from including your cookies.
Set-Cookie: session=abc123; SameSite=Lax; Secure; HttpOnly
  • CSRF tokens: For state-changing operations, include a server-generated random token in the request (as a header or form field) that the server verifies.
  • Check the Origin header: Reject requests whose Origin doesn't match your domain.

4. Secure Token Storage

Where you store authentication tokens matters enormously.

Storage XSS vulnerable CSRF vulnerable Accessible via JS
localStorage ✅ Yes ❌ No ✅ Yes
sessionStorage ✅ Yes ❌ No ✅ Yes
HttpOnly Cookie ❌ No ✅ Yes (mitigated by SameSite) ❌ No

The recommendation: Store session tokens in HttpOnly, Secure, SameSite=Lax cookies. They are immune to JavaScript-based theft, and CSRF is mitigated by SameSite.

Avoid storing JWTs in localStorage. An XSS vulnerability anywhere on your domain exposes every token stored there.


5. Third-Party Scripts & Supply Chain Risk

Every third-party script you include is a potential attack vector. A compromised analytics library, ad network, or chat widget can execute arbitrary code in your users' browsers.

Mitigations:

  • Subresource Integrity (SRI): When loading scripts from a CDN, include an integrity hash. The browser won't execute the script if it doesn't match.
<script 
  src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous">
</script>
  • Audit your dependencies: Run npm audit regularly and use tools like Snyk or Dependabot.
  • Minimize third-party scripts: Every script you add is a trust decision. Be deliberate.

6. Sensitive Data in the Frontend

Never include secrets in frontend code. Environment variables prefixed with NEXT_PUBLIC_ (or exposed to the browser in any framework) are visible to every user who opens DevTools.

// ❌ This is sent to the browser — anyone can see it
const secret = process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY;

// ✅ Keep secrets on the server only
// Call your own API route that uses the secret server-side

Public keys (Stripe publishable key, Supabase anon key) are designed to be public. Secret keys never belong in browser-accessible code.


7. Dependency on dangerouslySetInnerHTML, eval, and innerHTML

These are the three highest-risk APIs in frontend JavaScript:

  • innerHTML / outerHTML — parses and renders HTML, including scripts
  • dangerouslySetInnerHTML — React's wrapper, equally dangerous
  • eval() / new Function() — executes arbitrary code strings

Treat these as security code reviews. Any usage should be documented, justified, and sanitized.


Final Thoughts

Security is a mindset before it's a skillset. The question to ask on every feature is: "What's the worst thing a malicious user could do here?"

Frontend security is not about paranoia — it's about making the secure path the easy path. Sanitize by default, store tokens safely, audit your dependencies, and write code that assumes untrusted input at every boundary.

SecurityXSSCSRFFrontendWeb SecurityBest Practices
Sule Malik

Written by

Sule Malik

Frontend Engineer & SaaS Builder