ExamplesJavaScript

.1 Security Fundamentals

Module 21 Security Best Practices / .1 Security Fundamentals

Code Walkthrough
Advanced
18 min

Learning Objective

Study worked examples for .1 Security Fundamentals until you can trace the idea without guessing.

Why It Matters

Reading and running code turns the idea into behavior you can debug, modify, and reuse.

SecurityFundamentalsDemonstratesVulnerabilitiesPrevention
Private notes
0/8000

Notes stay private to your browser until account sync is configured.

Examples
examples.js
/**
 * 21.1 Security Fundamentals - Examples
 *
 * Demonstrates common security vulnerabilities and prevention techniques
 * WARNING: These examples show vulnerable code for educational purposes.
 * Never use vulnerable patterns in production!
 */

// ============================================
// XSS (CROSS-SITE SCRIPTING) EXAMPLES
// ============================================

console.log('=== XSS Prevention Examples ===\n');

/**
 * HTML Escaping - Prevents XSS by encoding special characters
 */
const HTMLEscaper = {
  // Character entity map
  entities: {
    '&': '&',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '/': '&#x2F;',
    '`': '&#x60;',
    '=': '&#x3D;',
  },

  // Escape HTML special characters
  escape(str) {
    if (typeof str !== 'string') return str;
    return str.replace(/[&<>"'`=/]/g, (char) => this.entities[char]);
  },

  // Unescape HTML entities
  unescape(str) {
    if (typeof str !== 'string') return str;

    const reverseEntities = {};
    for (const [char, entity] of Object.entries(this.entities)) {
      reverseEntities[entity] = char;
    }

    return str.replace(
      /&(?:amp|lt|gt|quot|#x27|#x2F|#x60|#x3D);/g,
      (entity) => reverseEntities[entity] || entity
    );
  },
};

// Demo
console.log('HTML Escaping:');
const maliciousInput = '<script>alert("XSS")</script>';
console.log('  Original:', maliciousInput);
console.log('  Escaped:', HTMLEscaper.escape(maliciousInput));
console.log('');

/**
 * Safe DOM manipulation utilities
 */
const SafeDOM = {
  // Create text node (always safe)
  createText(text) {
    return document.createTextNode(text);
  },

  // Set element text content safely
  setText(element, text) {
    element.textContent = text;
    return element;
  },

  // Create element with safe attributes
  createElement(tag, attributes = {}, textContent = '') {
    const element = document.createElement(tag);

    for (const [key, value] of Object.entries(attributes)) {
      // Validate attribute names
      if (!/^[a-zA-Z][\w-]*$/.test(key)) {
        throw new Error(`Invalid attribute name: ${key}`);
      }

      // Handle special attributes
      if (key === 'href' || key === 'src') {
        if (!this.isValidUrl(value)) {
          throw new Error(`Invalid URL for ${key}`);
        }
      }

      // Handle event handlers - reject them
      if (key.startsWith('on')) {
        throw new Error('Event handler attributes not allowed');
      }

      element.setAttribute(key, value);
    }

    if (textContent) {
      element.textContent = textContent;
    }

    return element;
  },

  // Validate URL (prevent javascript: protocol)
  isValidUrl(url) {
    if (!url) return false;

    try {
      const parsed = new URL(url, 'https://example.com');
      return ['http:', 'https:', 'mailto:'].includes(parsed.protocol);
    } catch {
      // Relative URLs are OK
      return !url.toLowerCase().includes('javascript:');
    }
  },

  // Sanitize HTML (very basic - use DOMPurify in production)
  sanitizeHTML(html) {
    // Remove script tags
    let clean = html.replace(
      /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
      ''
    );

    // Remove event handlers
    clean = clean.replace(/\s*on\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/gi, '');

    // Remove javascript: URLs
    clean = clean.replace(/javascript\s*:/gi, '');

    return clean;
  },
};

console.log('Safe URL Validation:');
console.log(
  '  https://example.com:',
  SafeDOM.isValidUrl('https://example.com')
);
console.log(
  '  javascript:alert(1):',
  SafeDOM.isValidUrl('javascript:alert(1)')
);
console.log('  /relative/path:', SafeDOM.isValidUrl('/relative/path'));
console.log('');

// ============================================
// CSRF PROTECTION EXAMPLES
// ============================================

console.log('=== CSRF Protection Examples ===\n');

/**
 * CSRF Token Generator and Validator
 */
class CSRFProtection {
  constructor() {
    this.tokens = new Map();
    this.tokenLifetime = 3600000; // 1 hour
  }

  // Generate secure random token
  generateToken() {
    // In browser, use crypto.getRandomValues
    // In Node.js, use crypto.randomBytes
    const array = new Uint8Array(32);

    if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
      crypto.getRandomValues(array);
    } else {
      // Fallback for Node.js without webcrypto
      const nodeCrypto = require('crypto');
      const buffer = nodeCrypto.randomBytes(32);
      array.set(buffer);
    }

    return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join(
      ''
    );
  }

  // Create token for a session
  createToken(sessionId) {
    const token = this.generateToken();
    const expiry = Date.now() + this.tokenLifetime;

    this.tokens.set(sessionId, { token, expiry });

    return token;
  }

  // Validate token
  validateToken(sessionId, token) {
    const stored = this.tokens.get(sessionId);

    if (!stored) {
      return { valid: false, reason: 'No token found for session' };
    }

    if (Date.now() > stored.expiry) {
      this.tokens.delete(sessionId);
      return { valid: false, reason: 'Token expired' };
    }

    // Constant-time comparison to prevent timing attacks
    if (!this.timingSafeEqual(token, stored.token)) {
      return { valid: false, reason: 'Token mismatch' };
    }

    return { valid: true };
  }

  // Constant-time string comparison
  timingSafeEqual(a, b) {
    if (typeof a !== 'string' || typeof b !== 'string') {
      return false;
    }

    if (a.length !== b.length) {
      return false;
    }

    let result = 0;
    for (let i = 0; i < a.length; i++) {
      result |= a.charCodeAt(i) ^ b.charCodeAt(i);
    }

    return result === 0;
  }

  // Rotate token (call after successful validation)
  rotateToken(sessionId) {
    if (this.tokens.has(sessionId)) {
      return this.createToken(sessionId);
    }
    return null;
  }

  // Cleanup expired tokens
  cleanup() {
    const now = Date.now();
    for (const [sessionId, data] of this.tokens) {
      if (now > data.expiry) {
        this.tokens.delete(sessionId);
      }
    }
  }
}

// Demo CSRF protection
const csrf = new CSRFProtection();
const sessionId = 'user-123';
const token = csrf.createToken(sessionId);

console.log('CSRF Token generated:', token.substring(0, 20) + '...');
console.log('Validate correct token:', csrf.validateToken(sessionId, token));
console.log(
  'Validate wrong token:',
  csrf.validateToken(sessionId, 'invalid-token')
);
console.log('');

/**
 * Fetch wrapper with CSRF protection
 */
function createSecureFetch(csrfToken) {
  return async function secureFetch(url, options = {}) {
    const isModifyingMethod = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(
      options.method?.toUpperCase()
    );

    if (isModifyingMethod) {
      options.headers = {
        ...options.headers,
        'X-CSRF-Token': csrfToken,
      };
    }

    // Include credentials for same-origin requests
    options.credentials = options.credentials || 'same-origin';

    return fetch(url, options);
  };
}

console.log('Secure fetch wrapper created with CSRF token');
console.log('');

// ============================================
// INPUT VALIDATION AND SANITIZATION
// ============================================

console.log('=== Input Validation Examples ===\n');

/**
 * Comprehensive input validator
 */
class InputValidator {
  // Validate email
  static isValidEmail(email) {
    if (typeof email !== 'string') return false;
    // RFC 5322 simplified regex
    const emailRegex =
      /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
    return emailRegex.test(email) && email.length <= 254;
  }

  // Validate URL
  static isValidUrl(url, allowedProtocols = ['http:', 'https:']) {
    try {
      const parsed = new URL(url);
      return allowedProtocols.includes(parsed.protocol);
    } catch {
      return false;
    }
  }

  // Validate integer
  static isValidInteger(value, min = -Infinity, max = Infinity) {
    const num = Number(value);
    return Number.isInteger(num) && num >= min && num <= max;
  }

  // Validate string length
  static isValidLength(str, minLen = 0, maxLen = Infinity) {
    return (
      typeof str === 'string' && str.length >= minLen && str.length <= maxLen
    );
  }

  // Validate alphanumeric
  static isAlphanumeric(str) {
    return typeof str === 'string' && /^[a-zA-Z0-9]+$/.test(str);
  }

  // Validate against whitelist
  static isInWhitelist(value, whitelist) {
    return whitelist.includes(value);
  }

  // Validate JSON
  static isValidJSON(str) {
    try {
      JSON.parse(str);
      return true;
    } catch {
      return false;
    }
  }

  // Validate file extension
  static isValidFileExtension(filename, allowedExtensions) {
    const ext = filename.toLowerCase().split('.').pop();
    return allowedExtensions.includes(ext);
  }

  // Validate path (no traversal)
  static isValidPath(path) {
    if (typeof path !== 'string') return false;
    // Check for path traversal
    const normalized = path.replace(/\\/g, '/');
    return !normalized.includes('..') && !normalized.startsWith('/');
  }
}

console.log('Input Validation:');
console.log('  Valid email:', InputValidator.isValidEmail('user@example.com'));
console.log('  Invalid email:', InputValidator.isValidEmail('not-an-email'));
console.log('  Valid URL:', InputValidator.isValidUrl('https://example.com'));
console.log(
  '  JavaScript URL:',
  InputValidator.isValidUrl('javascript:alert(1)')
);
console.log(
  '  Path traversal:',
  InputValidator.isValidPath('../../../etc/passwd')
);
console.log('  Safe path:', InputValidator.isValidPath('uploads/image.jpg'));
console.log('');

/**
 * Input sanitizer
 */
class InputSanitizer {
  // Remove control characters
  static removeControlChars(str) {
    if (typeof str !== 'string') return str;
    // eslint-disable-next-line no-control-regex
    return str.replace(/[\x00-\x1F\x7F]/g, '');
  }

  // Trim and normalize whitespace
  static normalizeWhitespace(str) {
    if (typeof str !== 'string') return str;
    return str.trim().replace(/\s+/g, ' ');
  }

  // Remove null bytes
  static removeNullBytes(str) {
    if (typeof str !== 'string') return str;
    return str.replace(/\0/g, '');
  }

  // Truncate string
  static truncate(str, maxLength) {
    if (typeof str !== 'string') return str;
    return str.slice(0, maxLength);
  }

  // Sanitize filename
  static sanitizeFilename(filename) {
    if (typeof filename !== 'string') return '';

    // Remove path components
    filename = filename.split(/[\\/]/).pop() || '';

    // Remove dangerous characters
    filename = filename.replace(/[<>:"/\\|?*\x00-\x1F]/g, '');

    // Remove leading dots
    filename = filename.replace(/^\.+/, '');

    // Truncate
    filename = filename.slice(0, 255);

    return filename || 'unnamed';
  }

  // Sanitize for SQL LIKE clause
  static escapeSqlLike(str) {
    if (typeof str !== 'string') return str;
    return str.replace(/[%_\\]/g, '\\$&');
  }

  // Sanitize for regex
  static escapeRegex(str) {
    if (typeof str !== 'string') return str;
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  }
}

console.log('Input Sanitization:');
console.log(
  '  Control chars removed:',
  InputSanitizer.removeControlChars('Hello\x00World\x1F!')
);
console.log(
  '  Filename sanitized:',
  InputSanitizer.sanitizeFilename('../../../etc/passwd')
);
console.log(
  '  Dangerous filename:',
  InputSanitizer.sanitizeFilename('<script>alert("xss")</script>.js')
);
console.log('  SQL LIKE escaped:', InputSanitizer.escapeSqlLike('100%'));
console.log('');

// ============================================
// INJECTION PREVENTION
// ============================================

console.log('=== Injection Prevention Examples ===\n');

/**
 * SQL Query Builder (parameterized)
 */
class SafeQueryBuilder {
  constructor() {
    this.query = '';
    this.params = [];
    this.paramIndex = 0;
  }

  // Start SELECT
  select(...columns) {
    const safeColumns = columns.map((col) => {
      // Only allow valid column names
      if (!/^[\w.]+$/.test(col)) {
        throw new Error(`Invalid column name: ${col}`);
      }
      return col;
    });

    this.query = `SELECT ${safeColumns.join(', ')}`;
    return this;
  }

  // FROM clause
  from(table) {
    // Validate table name
    if (!/^\w+$/.test(table)) {
      throw new Error(`Invalid table name: ${table}`);
    }
    this.query += ` FROM ${table}`;
    return this;
  }

  // WHERE clause with parameterized values
  where(column, operator, value) {
    // Validate column
    if (!/^[\w.]+$/.test(column)) {
      throw new Error(`Invalid column name: ${column}`);
    }

    // Validate operator
    const allowedOperators = [
      '=',
      '!=',
      '<>',
      '>',
      '<',
      '>=',
      '<=',
      'LIKE',
      'IN',
    ];
    if (!allowedOperators.includes(operator.toUpperCase())) {
      throw new Error(`Invalid operator: ${operator}`);
    }

    // Use parameterized value
    this.paramIndex++;
    const placeholder = `$${this.paramIndex}`;

    this.query += ` WHERE ${column} ${operator} ${placeholder}`;
    this.params.push(value);

    return this;
  }

  // AND clause
  and(column, operator, value) {
    if (!/^[\w.]+$/.test(column)) {
      throw new Error(`Invalid column name: ${column}`);
    }

    this.paramIndex++;
    const placeholder = `$${this.paramIndex}`;

    this.query += ` AND ${column} ${operator} ${placeholder}`;
    this.params.push(value);

    return this;
  }

  // Build final query
  build() {
    return {
      query: this.query,
      params: this.params,
    };
  }
}

// Demo safe query building
const queryBuilder = new SafeQueryBuilder();
const result = queryBuilder
  .select('id', 'username', 'email')
  .from('users')
  .where('username', '=', 'john')
  .and('active', '=', true)
  .build();

console.log('Safe Query Builder:');
console.log('  Query:', result.query);
console.log('  Params:', result.params);
console.log('');

/**
 * Command execution sanitizer
 */
class SafeCommand {
  // Escape shell argument
  static escapeShellArg(arg) {
    if (typeof arg !== 'string') {
      arg = String(arg);
    }

    // In Unix: wrap in single quotes and escape single quotes
    return `'${arg.replace(/'/g, "'\\''")}'`;
  }

  // Validate command name against whitelist
  static isAllowedCommand(cmd, whitelist) {
    return whitelist.includes(cmd);
  }

  // Build safe command with arguments
  static buildCommand(cmd, args, whitelist) {
    if (!this.isAllowedCommand(cmd, whitelist)) {
      throw new Error(`Command not allowed: ${cmd}`);
    }

    const escapedArgs = args.map((arg) => this.escapeShellArg(arg));
    return `${cmd} ${escapedArgs.join(' ')}`;
  }
}

console.log('Safe Command Execution:');
const allowedCommands = ['ls', 'cat', 'echo'];
try {
  const safeCmd = SafeCommand.buildCommand(
    'echo',
    ['Hello; rm -rf /', '$(whoami)'],
    allowedCommands
  );
  console.log('  Safe command:', safeCmd);
} catch (e) {
  console.log('  Error:', e.message);
}
console.log('');

// ============================================
// CONTENT SECURITY POLICY BUILDER
// ============================================

console.log('=== Content Security Policy Builder ===\n');

/**
 * CSP Header Builder
 */
class CSPBuilder {
  constructor() {
    this.directives = new Map();
  }

  // Add directive
  addDirective(name, ...values) {
    const existing = this.directives.get(name) || [];
    this.directives.set(name, [...existing, ...values]);
    return this;
  }

  // Common presets
  defaultSrc(...values) {
    return this.addDirective('default-src', ...values);
  }

  scriptSrc(...values) {
    return this.addDirective('script-src', ...values);
  }

  styleSrc(...values) {
    return this.addDirective('style-src', ...values);
  }

  imgSrc(...values) {
    return this.addDirective('img-src', ...values);
  }

  connectSrc(...values) {
    return this.addDirective('connect-src', ...values);
  }

  fontSrc(...values) {
    return this.addDirective('font-src', ...values);
  }

  frameSrc(...values) {
    return this.addDirective('frame-src', ...values);
  }

  frameAncestors(...values) {
    return this.addDirective('frame-ancestors', ...values);
  }

  formAction(...values) {
    return this.addDirective('form-action', ...values);
  }

  baseUri(...values) {
    return this.addDirective('base-uri', ...values);
  }

  objectSrc(...values) {
    return this.addDirective('object-src', ...values);
  }

  reportUri(uri) {
    return this.addDirective('report-uri', uri);
  }

  upgradeInsecureRequests() {
    return this.addDirective('upgrade-insecure-requests');
  }

  // Generate nonce
  static generateNonce() {
    const array = new Uint8Array(16);
    if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
      crypto.getRandomValues(array);
    } else {
      const nodeCrypto = require('crypto');
      const buffer = nodeCrypto.randomBytes(16);
      array.set(buffer);
    }
    return Buffer.from(array).toString('base64');
  }

  // Build header value
  build() {
    const parts = [];

    for (const [directive, values] of this.directives) {
      if (values.length === 0) {
        parts.push(directive);
      } else {
        parts.push(`${directive} ${values.join(' ')}`);
      }
    }

    return parts.join('; ');
  }

  // Common secure presets
  static strict() {
    const nonce = CSPBuilder.generateNonce();

    return {
      policy: new CSPBuilder()
        .defaultSrc("'self'")
        .scriptSrc("'self'", `'nonce-${nonce}'`)
        .styleSrc("'self'", "'unsafe-inline'")
        .imgSrc("'self'", 'data:', 'https:')
        .fontSrc("'self'")
        .connectSrc("'self'")
        .frameAncestors("'none'")
        .baseUri("'self'")
        .formAction("'self'")
        .objectSrc("'none'")
        .build(),
      nonce,
    };
  }
}

// Demo CSP Builder
const cspBuilder = new CSPBuilder()
  .defaultSrc("'self'")
  .scriptSrc("'self'", "'nonce-abc123'")
  .styleSrc("'self'", "'unsafe-inline'")
  .imgSrc("'self'", 'data:', 'https://cdn.example.com')
  .connectSrc("'self'", 'https://api.example.com')
  .frameAncestors("'none'")
  .baseUri("'self'");

console.log('CSP Header:');
console.log('  ' + cspBuilder.build());
console.log('');

// ============================================
// SECURITY HEADERS CONFIGURATION
// ============================================

console.log('=== Security Headers Configuration ===\n');

/**
 * Security headers configuration for different environments
 */
const SecurityHeaders = {
  // Production headers (strict)
  production: {
    'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY',
    'X-XSS-Protection': '1; mode=block',
    'Referrer-Policy': 'strict-origin-when-cross-origin',
    'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
    'Content-Security-Policy': CSPBuilder.strict().policy,
  },

  // Development headers (relaxed)
  development: {
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'SAMEORIGIN',
  },

  // Apply headers to response
  apply(res, env = 'production') {
    const headers = this[env] || this.production;

    for (const [key, value] of Object.entries(headers)) {
      res.setHeader(key, value);
    }
  },

  // Generate middleware
  middleware(env = 'production') {
    const headers = this[env] || this.production;

    return (req, res, next) => {
      for (const [key, value] of Object.entries(headers)) {
        res.setHeader(key, value);
      }
      next();
    };
  },
};

console.log('Production Security Headers:');
for (const [header, value] of Object.entries(SecurityHeaders.production)) {
  const displayValue =
    value.length > 60 ? value.substring(0, 60) + '...' : value;
  console.log(`  ${header}: ${displayValue}`);
}
console.log('');

// ============================================
// SECURE DATA HANDLING
// ============================================

console.log('=== Secure Data Handling ===\n');

/**
 * Secure data masking for logs
 */
class DataMasker {
  static patterns = {
    email: {
      regex: /([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g,
      mask: (match, local, domain) => {
        const maskedLocal = local[0] + '*'.repeat(local.length - 1);
        return `${maskedLocal}@${domain}`;
      },
    },
    creditCard: {
      regex: /\b(\d{4})[\s-]?(\d{4})[\s-]?(\d{4})[\s-]?(\d{4})\b/g,
      mask: (match, g1, g2, g3, g4) => `****-****-****-${g4}`,
    },
    ssn: {
      regex: /\b(\d{3})[-\s]?(\d{2})[-\s]?(\d{4})\b/g,
      mask: () => '***-**-****',
    },
    phone: {
      regex: /\b(\+\d{1,3}[-\s]?)?(\(?\d{3}\)?[-\s]?)(\d{3}[-\s]?)(\d{4})\b/g,
      mask: (match, country, area, mid, last) =>
        `${country || ''}***-***-${last}`,
    },
    ipv4: {
      regex: /\b(\d{1,3}\.\d{1,3})\.\d{1,3}\.\d{1,3}\b/g,
      mask: (match, first) => `${first}.xxx.xxx`,
    },
  };

  static mask(text, types = Object.keys(this.patterns)) {
    let masked = text;

    for (const type of types) {
      const pattern = this.patterns[type];
      if (pattern) {
        masked = masked.replace(pattern.regex, pattern.mask);
      }
    }

    return masked;
  }

  static maskObject(
    obj,
    sensitiveFields = ['password', 'token', 'secret', 'key', 'auth']
  ) {
    if (typeof obj !== 'object' || obj === null) {
      return obj;
    }

    const masked = Array.isArray(obj) ? [] : {};

    for (const [key, value] of Object.entries(obj)) {
      const lowerKey = key.toLowerCase();

      // Check if field name indicates sensitive data
      const isSensitive = sensitiveFields.some((field) =>
        lowerKey.includes(field.toLowerCase())
      );

      if (isSensitive) {
        masked[key] = '[REDACTED]';
      } else if (typeof value === 'object' && value !== null) {
        masked[key] = this.maskObject(value, sensitiveFields);
      } else if (typeof value === 'string') {
        masked[key] = this.mask(value);
      } else {
        masked[key] = value;
      }
    }

    return masked;
  }
}

console.log('Data Masking:');
const sensitiveText = `
User: john@example.com
Card: 4111-1111-1111-1234
SSN: 123-45-6789
Phone: +1 (555) 123-4567
IP: 192.168.1.100
`;

console.log('Original:', sensitiveText);
console.log('Masked:', DataMasker.mask(sensitiveText));

const sensitiveObject = {
  user: 'john@example.com',
  password: 'secret123',
  apiKey: 'sk_live_1234567890',
  profile: {
    name: 'John Doe',
    authToken: 'bearer xyz123',
  },
};

console.log(
  '\nMasked Object:',
  JSON.stringify(DataMasker.maskObject(sensitiveObject), null, 2)
);
console.log('');

// ============================================
// SUMMARY
// ============================================

console.log('=== Security Fundamentals Summary ===\n');

console.log('Key Security Components Demonstrated:');
console.log('1. HTML Escaping - Prevent XSS attacks');
console.log('2. CSRF Protection - Token-based request validation');
console.log('3. Input Validation - Whitelist and type checking');
console.log('4. Input Sanitization - Clean and normalize input');
console.log('5. Injection Prevention - Parameterized queries');
console.log('6. CSP Builder - Content Security Policy configuration');
console.log('7. Security Headers - HTTP security headers');
console.log('8. Data Masking - Protect sensitive data in logs');

console.log('\nRemember: Security is a process, not a feature!');

// Export for testing
if (typeof module !== 'undefined' && module.exports) {
  module.exports = {
    HTMLEscaper,
    SafeDOM,
    CSRFProtection,
    InputValidator,
    InputSanitizer,
    SafeQueryBuilder,
    SafeCommand,
    CSPBuilder,
    SecurityHeaders,
    DataMasker,
  };
}

Skill Check

Test this lesson

Answer 4 quick questions to lock in the lesson and feed your adaptive practice queue.

--
Score
0/4
Answered
Not attempted
Status
1

Which module does this lesson belong to?

2

Which section is covered in this lesson content?

3

Which term is most central to this lesson?

4

What is the best way to use this lesson for real learning?

Your answers save locally first, then sync when account storage is available.
Practice queue