DOM-Based XSS Vulnerabilities

DOM-Based XSS Vulnerabilities

DOM-based Cross-Site Scripting (XSS) represents one of the most prevalent JavaScript security vulnerabilities. Unlike traditional XSS that occurs on the server side, DOM-based XSS happens entirely in the browser when JavaScript code improperly handles user input. These vulnerabilities are particularly insidious because they can be invisible to server-side security tools and WAFs (Web Application Firewalls).

// Vulnerable code examples and their secure alternatives

// VULNERABLE: Direct innerHTML usage with user input
function displayUserComment(comment) {
    // This allows arbitrary HTML and JavaScript injection
    document.getElementById('comments').innerHTML = comment;
}

// SECURE: Using textContent for plain text
function displayUserCommentSecure(comment) {
    document.getElementById('comments').textContent = comment;
}

// VULNERABLE: Using document.write with user input
function showWelcomeMessage() {
    // User input from URL parameter
    const name = new URLSearchParams(window.location.search).get('name');
    document.write('Welcome, ' + name + '!');  // XSS vulnerability
}

// SECURE: Using DOM methods with proper encoding
function showWelcomeMessageSecure() {
    const name = new URLSearchParams(window.location.search).get('name');
    const welcomeDiv = document.createElement('div');
    welcomeDiv.textContent = `Welcome, ${name}!`;
    document.body.appendChild(welcomeDiv);
}

// VULNERABLE: jQuery html() with user input
function updateProfilejQuery(userBio) {
    $('#user-bio').html(userBio);  // XSS vulnerability
}

// SECURE: jQuery text() or proper sanitization
function updateProfilejQuerySecure(userBio) {
    // For plain text
    $('#user-bio').text(userBio);
    
    // If HTML is needed, sanitize first
    const sanitized = DOMPurify.sanitize(userBio, {
        ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'],
        ALLOWED_ATTR: []
    });
    $('#user-bio').html(sanitized);
}

// VULNERABLE: eval() and Function constructor
function calculateFormula(formula) {
    // Never use eval with user input!
    return eval(formula);
}

// SECURE: Parse and validate expressions safely
function calculateFormulaSecure(formula) {
    // Use a proper expression parser library
    const parser = new ExpressionParser();
    
    // Whitelist allowed operations
    parser.setAllowedOperations(['+', '-', '*', '/', '(', ')']);
    parser.setAllowedVariables(['x', 'y', 'z']);
    
    try {
        return parser.evaluate(formula);
    } catch (e) {
        throw new Error('Invalid formula');
    }
}