Docs

21.1-Security-Fundamentals

21.1 Security Fundamentals

Overview

Web security is critical for protecting users and data. This section covers the most common JavaScript security vulnerabilities and how to prevent them.

The Security Landscape

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Web Application Threats                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                  β”‚
β”‚                           β”‚   Attacker   β”‚                                  β”‚
β”‚                           β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β”‚                                  β”‚                                          β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚           β”‚                      β”‚                      β”‚                   β”‚
β”‚           β–Ό                      β–Ό                      β–Ό                   β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚    β”‚     XSS     β”‚       β”‚    CSRF     β”‚       β”‚  Injection  β”‚             β”‚
β”‚    β”‚  Cross-Site β”‚       β”‚   Request   β”‚       β”‚   Attacks   β”‚             β”‚
β”‚    β”‚  Scripting  β”‚       β”‚   Forgery   β”‚       β”‚             β”‚             β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚           β”‚                      β”‚                      β”‚                   β”‚
β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                                  β”‚                                          β”‚
β”‚                                  β–Ό                                          β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚                    β”‚     Your Application      β”‚                           β”‚
β”‚                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                           β”‚
β”‚                    β”‚  β”‚    User Data        β”‚  β”‚                           β”‚
β”‚                    β”‚  β”‚    Sessions         β”‚  β”‚                           β”‚
β”‚                    β”‚  β”‚    Credentials      β”‚  β”‚                           β”‚
β”‚                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                           β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Cross-Site Scripting (XSS)

XSS Attack Types

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                            XSS Attack Types                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Type        β”‚ Description                                                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Stored XSS  β”‚ Malicious script stored in database, served to all users     β”‚
β”‚             β”‚ Example: Comment with <script> tag stored in forum           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Reflected   β”‚ Script in URL parameter reflected in page response           β”‚
β”‚ XSS         β”‚ Example: Search query displayed without escaping             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ DOM-based   β”‚ Client-side script modifies DOM unsafely                     β”‚
β”‚ XSS         β”‚ Example: innerHTML with user input                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

XSS Attack Flow

Stored XSS:

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      POST /comment     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Attacker β”‚ ───────────────────► β”‚   Server     β”‚
  β”‚          β”‚   <script>evil()</    β”‚              β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   script>              β”‚  Stores in  β”‚
                                      β”‚  Database   β”‚
                                      β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                             β”‚
                                             β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      GET /comments     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Victim  β”‚ ◄─────────────────── β”‚   Server     β”‚
  β”‚          β”‚   Returns page with   β”‚              β”‚
  β”‚ Browser  β”‚   malicious script    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  β”‚ executes β”‚
  β”‚  script! β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

XSS Prevention

// ❌ VULNERABLE - Direct HTML insertion
element.innerHTML = userInput;

// βœ“ SAFE - Use textContent for text
element.textContent = userInput;

// βœ“ SAFE - Escape HTML entities
function escapeHTML(str) {
  const div = document.createElement('div');
  div.textContent = str;
  return div.innerHTML;
}

// βœ“ SAFE - Use DOM APIs
const link = document.createElement('a');
link.href = sanitizedUrl;
link.textContent = userText;
container.appendChild(link);

Cross-Site Request Forgery (CSRF)

CSRF Attack Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           CSRF Attack Flow                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1. User logs into Bank.com
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   User   β”‚ ──────► β”‚  Bank.com   β”‚
   β”‚          β”‚ ◄────── β”‚ (logged in) β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Cookie  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. User visits malicious site
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   User   β”‚ ──────► β”‚  Evil.com   β”‚
   β”‚          β”‚         β”‚  Contains:  β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚  <img src=  β”‚
                        β”‚  "bank.com/ β”‚
                        β”‚  transfer?  β”‚
                        β”‚  to=hacker  β”‚
                        β”‚  &amt=1000">β”‚
                        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
3. Browser auto-sends cookie   β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  Browser β”‚ β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”€β”€β–Ί β”‚  Bank.com   β”‚
   β”‚ (victim) β”‚  GET /transfer?... β”‚ Thinks it's β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  + session cookie  β”‚ the user!   β”‚
                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CSRF Prevention

// Server generates CSRF token
const csrfToken = crypto.randomBytes(32).toString('hex');
// Store in session and embed in forms

// HTML Form
<form action="/transfer" method="POST">
    <input type="hidden" name="csrf_token" value="{{csrfToken}}">
    <input type="text" name="amount">
    <button>Transfer</button>
</form>

// Fetch with CSRF token
fetch('/api/transfer', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': csrfToken
    },
    body: JSON.stringify({ amount: 100 })
});

// Server validation
function validateCSRF(req, res, next) {
    const token = req.headers['x-csrf-token'] || req.body.csrf_token;

    if (!token || token !== req.session.csrfToken) {
        return res.status(403).json({ error: 'Invalid CSRF token' });
    }

    next();
}

Content Security Policy (CSP)

CSP Header Configuration

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Content Security Policy Directives                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Directive          β”‚ Purpose                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ default-src        β”‚ Default fallback for other directives                  β”‚
β”‚ script-src         β”‚ Valid sources for JavaScript                           β”‚
β”‚ style-src          β”‚ Valid sources for stylesheets                          β”‚
β”‚ img-src            β”‚ Valid sources for images                               β”‚
β”‚ connect-src        β”‚ Valid sources for fetch, XHR, WebSocket               β”‚
β”‚ font-src           β”‚ Valid sources for fonts                                β”‚
β”‚ frame-src          β”‚ Valid sources for iframes                              β”‚
β”‚ object-src         β”‚ Valid sources for plugins                              β”‚
β”‚ report-uri         β”‚ URL to send CSP violation reports                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CSP Examples

// Strict CSP (recommended for new projects)
Content-Security-Policy:
    default-src 'self';
    script-src 'self' 'nonce-abc123';
    style-src 'self' 'unsafe-inline';
    img-src 'self' data: https:;
    connect-src 'self' https://api.example.com;
    frame-ancestors 'none';
    base-uri 'self';
    form-action 'self';

// Using nonces for inline scripts
<script nonce="abc123">
    // This script is allowed
    console.log('Allowed by CSP');
</script>

<script>
    // This script is BLOCKED by CSP
    // No nonce attribute
</script>

Injection Attacks

Types of Injection

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          Injection Attack Types                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Type             β”‚ Example & Prevention                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ SQL Injection    β”‚ Input: "1 OR 1=1" breaks query logic                    β”‚
β”‚                  β”‚ Fix: Use parameterized queries                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ NoSQL Injection  β”‚ Input: {"$gt": ""} bypasses filters                     β”‚
β”‚                  β”‚ Fix: Validate input types, sanitize                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Command Inject   β”‚ Input: "; rm -rf /" executes system commands            β”‚
β”‚                  β”‚ Fix: Avoid shell, use safe APIs                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Code Injection   β”‚ Input to eval() executes arbitrary code                 β”‚
β”‚                  β”‚ Fix: Never eval() user input                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Path Traversal   β”‚ Input: "../../../etc/passwd" accesses files             β”‚
β”‚                  β”‚ Fix: Validate, normalize, restrict paths                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Injection Prevention

// ❌ SQL Injection vulnerable
const query = `SELECT * FROM users WHERE id = ${userId}`;

// βœ“ Parameterized query (safe)
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);

// ❌ Command injection vulnerable
exec(`echo ${userInput}`);

// βœ“ Safe alternative
spawn('echo', [userInput], { shell: false });

// ❌ Code injection vulnerable
eval(userCode);
new Function(userCode)();

// βœ“ Safe alternative: use sandbox or avoid entirely
const vm = require('vm');
const sandbox = { result: null };
vm.createContext(sandbox);
vm.runInContext('result = 1 + 1', sandbox, { timeout: 100 });

Security Headers

Essential Security Headers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Essential Security Headers                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Header                   β”‚ Purpose                                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Strict-Transport-Securityβ”‚ Force HTTPS connections                          β”‚
β”‚ X-Content-Type-Options   β”‚ Prevent MIME type sniffing                       β”‚
β”‚ X-Frame-Options          β”‚ Prevent clickjacking                             β”‚
β”‚ X-XSS-Protection         β”‚ Enable browser XSS filter (legacy)               β”‚
β”‚ Referrer-Policy          β”‚ Control referrer information                     β”‚
β”‚ Permissions-Policy       β”‚ Control browser features                         β”‚
β”‚ Content-Security-Policy  β”‚ Control resource loading                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Express.js Security Headers

const helmet = require('helmet');

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "'nonce-abc123'"],
        styleSrc: ["'self'", "'unsafe-inline'"],
        imgSrc: ["'self'", 'data:', 'https:'],
      },
    },
    hsts: {
      maxAge: 31536000, // 1 year
      includeSubDomains: true,
      preload: true,
    },
    frameguard: { action: 'deny' },
    noSniff: true,
    referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
  })
);

Client-Side Security

Secure Cookie Configuration

// Setting secure cookies
document.cookie = 'session=abc123; Secure; HttpOnly; SameSite=Strict';

// Cookie attributes explained:
// Secure     - Only sent over HTTPS
// HttpOnly   - Not accessible via JavaScript (prevents XSS theft)
// SameSite   - Prevents CSRF
//   - Strict: Never sent cross-site
//   - Lax: Sent on top-level navigation
//   - None: Always sent (requires Secure)

Secure Storage

// ❌ Don't store sensitive data in localStorage
localStorage.setItem('authToken', token);  // Vulnerable to XSS

// βœ“ Use HttpOnly cookies for auth tokens
// Set by server:
Set-Cookie: authToken=abc123; HttpOnly; Secure; SameSite=Strict

// For less sensitive data, encrypt before storing
async function encryptAndStore(key, data, encryptionKey) {
    const encrypted = await encrypt(data, encryptionKey);
    sessionStorage.setItem(key, encrypted);
}

async function retrieveAndDecrypt(key, encryptionKey) {
    const encrypted = sessionStorage.getItem(key);
    return await decrypt(encrypted, encryptionKey);
}

Security Checklist

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Security Checklist                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚ XSS Prevention:                                                            β”‚
β”‚ β–‘ Never use innerHTML with user input                                     β”‚
β”‚ β–‘ Escape all output by default                                            β”‚
β”‚ β–‘ Implement Content Security Policy                                        β”‚
β”‚ β–‘ Use textContent instead of innerHTML where possible                      β”‚
β”‚                                                                             β”‚
β”‚ CSRF Prevention:                                                           β”‚
β”‚ β–‘ Implement CSRF tokens for state-changing operations                      β”‚
β”‚ β–‘ Use SameSite cookies                                                     β”‚
β”‚ β–‘ Verify Origin/Referer headers                                           β”‚
β”‚                                                                             β”‚
β”‚ Injection Prevention:                                                       β”‚
β”‚ β–‘ Use parameterized queries                                                β”‚
β”‚ β–‘ Validate and sanitize all input                                          β”‚
β”‚ β–‘ Never use eval() with user input                                         β”‚
β”‚ β–‘ Avoid shell commands with user input                                     β”‚
β”‚                                                                             β”‚
β”‚ Authentication:                                                            β”‚
β”‚ β–‘ Use HTTPS everywhere                                                     β”‚
β”‚ β–‘ Implement secure password hashing (bcrypt)                               β”‚
β”‚ β–‘ Use HttpOnly, Secure cookies                                             β”‚
β”‚ β–‘ Implement rate limiting                                                  β”‚
β”‚                                                                             β”‚
β”‚ Headers:                                                                   β”‚
β”‚ β–‘ Enable HSTS                                                              β”‚
β”‚ β–‘ Set X-Content-Type-Options: nosniff                                     β”‚
β”‚ β–‘ Set X-Frame-Options or CSP frame-ancestors                              β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Takeaways

  1. β€’Trust no input - All user input is potentially malicious
  2. β€’Escape all output - Context-aware encoding is essential
  3. β€’Defense in depth - Multiple layers of security
  4. β€’Principle of least privilege - Minimal permissions needed
  5. β€’Keep dependencies updated - Security patches are critical
  6. β€’Monitor and log - Detect attacks early
  7. β€’Security headers - Use them all

Files in This Section

  • β€’README.md - This documentation
  • β€’examples.js - Security vulnerability demonstrations
  • β€’exercises.js - Security practice exercises
.1 Security Fundamentals - JavaScript Tutorial | DeepML