quantum-ai-v3/docs/SECURITY_IMPLEMENTATION_GUIDE.md
2025-07-19 08:06:31 +05:30

35 KiB

Security Implementation Guide

Comprehensive security requirements and implementation patterns for agent templates.

Security Principles

1. Defense in Depth

  • Multiple layers of protection at different levels
  • Input validation at client and server side
  • Output encoding for all dynamic content
  • Access control at every endpoint

2. Least Privilege

  • Minimal permissions for each component
  • Restricted access to sensitive data
  • Limited functionality exposure

3. Secure by Default

  • Safe defaults for all configurations
  • Explicit security rather than assumed
  • Fail-safe mechanisms when security fails

Input Validation and Sanitization

Client-Side Input Validation

// Input Sanitization Utilities
const InputValidator = {
    // Basic HTML sanitization
    sanitizeHTML(input) {
        return input
            .replace(/&/g, '&')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#x27;')
            .replace(/\//g, '&#x2F;');
    },
    
    // File upload validation
    validateFile(file, allowedTypes = [], maxSize = 10 * 1024 * 1024) {
        const errors = [];
        
        // Check file type
        if (allowedTypes.length > 0) {
            const fileType = file.type.toLowerCase();
            const fileName = file.name.toLowerCase();
            
            const isValidType = allowedTypes.some(type => {
                if (type.includes('*')) {
                    return fileType.startsWith(type.replace('*', ''));
                }
                return fileType === type || fileName.endsWith(type);
            });
            
            if (!isValidType) {
                errors.push(`File type not allowed. Allowed types: ${allowedTypes.join(', ')}`);
            }
        }
        
        // Check file size
        if (file.size > maxSize) {
            errors.push(`File too large. Maximum size: ${(maxSize / (1024 * 1024)).toFixed(1)}MB`);
        }
        
        // Check for dangerous file extensions
        const dangerousExtensions = ['.exe', '.bat', '.cmd', '.scr', '.pif', '.vbs', '.js', '.jar'];
        const fileName = file.name.toLowerCase();
        
        if (dangerousExtensions.some(ext => fileName.endsWith(ext))) {
            errors.push('Potentially dangerous file type detected');
        }
        
        return {
            isValid: errors.length === 0,
            errors
        };
    },
    
    // Text input validation
    validateText(input, options = {}) {
        const {
            required = false,
            minLength = 0,
            maxLength = Infinity,
            pattern = null,
            allowHTML = false
        } = options;
        
        const errors = [];
        
        // Check required
        if (required && (!input || input.trim().length === 0)) {
            errors.push('This field is required');
        }
        
        if (input && input.length > 0) {
            // Check length
            if (input.length < minLength) {
                errors.push(`Minimum length is ${minLength} characters`);
            }
            
            if (input.length > maxLength) {
                errors.push(`Maximum length is ${maxLength} characters`);
            }
            
            // Check pattern
            if (pattern && !pattern.test(input)) {
                errors.push('Invalid format');
            }
            
            // Check for HTML if not allowed
            if (!allowHTML && /<[^>]*>/.test(input)) {
                errors.push('HTML tags are not allowed');
            }
        }
        
        return {
            isValid: errors.length === 0,
            errors,
            sanitized: allowHTML ? input : this.sanitizeHTML(input)
        };
    },
    
    // Email validation
    validateEmail(email) {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        const isValid = emailRegex.test(email);
        
        return {
            isValid,
            errors: isValid ? [] : ['Please enter a valid email address'],
            sanitized: this.sanitizeHTML(email)
        };
    },
    
    // URL validation
    validateURL(url) {
        try {
            const urlObj = new URL(url);
            
            // Check for allowed protocols
            const allowedProtocols = ['http:', 'https:'];
            if (!allowedProtocols.includes(urlObj.protocol)) {
                return {
                    isValid: false,
                    errors: ['Only HTTP and HTTPS URLs are allowed'],
                    sanitized: ''
                };
            }
            
            return {
                isValid: true,
                errors: [],
                sanitized: urlObj.toString()
            };
        } catch (error) {
            return {
                isValid: false,
                errors: ['Please enter a valid URL'],
                sanitized: ''
            };
        }
    }
};

Advanced HTML Sanitization

// Advanced HTML Sanitization
const HTMLSanitizer = {
    // Allowed tags and attributes
    allowedTags: ['p', 'br', 'strong', 'em', 'u', 'ol', 'ul', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
    allowedAttributes: {
        'a': ['href', 'title'],
        'img': ['src', 'alt', 'width', 'height'],
        'all': ['class', 'id']
    },
    
    // Comprehensive sanitization
    sanitize(html) {
        if (!html || typeof html !== 'string') {
            return '';
        }
        
        // Create temporary container
        const temp = document.createElement('div');
        temp.innerHTML = html;
        
        // Remove dangerous elements
        this.removeDangerousElements(temp);
        
        // Sanitize allowed elements
        this.sanitizeAllowedElements(temp);
        
        return temp.innerHTML;
    },
    
    removeDangerousElements(container) {
        const dangerousTags = [
            'script', 'style', 'iframe', 'object', 'embed', 'form', 'input',
            'button', 'textarea', 'select', 'option', 'meta', 'link', 'base'
        ];
        
        dangerousTags.forEach(tag => {
            const elements = container.querySelectorAll(tag);
            elements.forEach(el => el.remove());
        });
        
        // Remove comments
        const walker = document.createTreeWalker(
            container,
            NodeFilter.SHOW_COMMENT,
            null,
            false
        );
        
        const comments = [];
        let node;
        while (node = walker.nextNode()) {
            comments.push(node);
        }
        
        comments.forEach(comment => comment.remove());
    },
    
    sanitizeAllowedElements(container) {
        const allElements = container.querySelectorAll('*');
        
        allElements.forEach(el => {
            const tagName = el.tagName.toLowerCase();
            
            // Remove disallowed tags
            if (!this.allowedTags.includes(tagName)) {
                el.remove();
                return;
            }
            
            // Clean attributes
            const allowedAttrs = [
                ...(this.allowedAttributes[tagName] || []),
                ...(this.allowedAttributes.all || [])
            ];
            
            // Remove dangerous attributes
            Array.from(el.attributes).forEach(attr => {
                const attrName = attr.name.toLowerCase();
                
                // Remove event handlers
                if (attrName.startsWith('on')) {
                    el.removeAttribute(attrName);
                    return;
                }
                
                // Remove javascript: URLs
                if (attr.value && attr.value.toLowerCase().includes('javascript:')) {
                    el.removeAttribute(attrName);
                    return;
                }
                
                // Remove data attributes (except specific ones)
                if (attrName.startsWith('data-') && !['data-id', 'data-value'].includes(attrName)) {
                    el.removeAttribute(attrName);
                    return;
                }
                
                // Remove non-allowed attributes
                if (!allowedAttrs.includes(attrName)) {
                    el.removeAttribute(attrName);
                }
            });
        });
    },
    
    // Safe content setting
    safeSetHTML(element, content) {
        if (!element || !content) return;
        
        const sanitizedContent = this.sanitize(content);
        element.innerHTML = sanitizedContent;
    },
    
    // Safe content appending
    safeAppendHTML(element, content) {
        if (!element || !content) return;
        
        const sanitizedContent = this.sanitize(content);
        element.insertAdjacentHTML('beforeend', sanitizedContent);
    }
};

XSS Prevention

Content Security Policy (CSP)

<!-- Add to base template head -->
<meta http-equiv="Content-Security-Policy" content="
    default-src 'self';
    script-src 'self' 'unsafe-inline';
    style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
    font-src 'self' https://fonts.gstatic.com;
    img-src 'self' data: https:;
    connect-src 'self';
    frame-ancestors 'none';
    base-uri 'self';
    form-action 'self';
">

Django Template Security

<!-- Django template security patterns -->

<!-- Always use autoescape -->
{% autoescape on %}
    {{ user_content }}
{% endautoescape %}

<!-- For JSON data -->
<script>
    const userData = {{ user_data|escapejs }};
</script>

<!-- For HTML content that must allow some tags -->
{% load custom_filters %}
{{ user_content|safe_html }}

<!-- For URLs -->
<a href="{{ user_url|urlencode }}">Link</a>

<!-- For attributes -->
<div class="{{ css_class|escape }}">Content</div>

JavaScript XSS Prevention

// XSS Prevention Utilities
const XSSProtection = {
    // Escape content for HTML context
    escapeHTML(str) {
        const div = document.createElement('div');
        div.textContent = str;
        return div.innerHTML;
    },
    
    // Escape content for JavaScript context
    escapeJS(str) {
        return str
            .replace(/\\/g, '\\\\')
            .replace(/'/g, "\\'")
            .replace(/"/g, '\\"')
            .replace(/\r/g, '\\r')
            .replace(/\n/g, '\\n')
            .replace(/\t/g, '\\t')
            .replace(/\f/g, '\\f')
            .replace(/\v/g, '\\v')
            .replace(/\0/g, '\\0');
    },
    
    // Escape content for CSS context
    escapeCSS(str) {
        return str.replace(/[<>"'&]/g, function(match) {
            return '\\' + match.charCodeAt(0).toString(16) + ' ';
        });
    },
    
    // Escape content for URL context
    escapeURL(str) {
        return encodeURIComponent(str);
    },
    
    // Safe DOM manipulation
    safeSetText(element, text) {
        if (element && typeof text === 'string') {
            element.textContent = text;
        }
    },
    
    safeSetAttribute(element, name, value) {
        if (element && typeof name === 'string' && typeof value === 'string') {
            // Prevent dangerous attributes
            const dangerousAttrs = ['onclick', 'onload', 'onerror', 'onmouseover'];
            if (dangerousAttrs.includes(name.toLowerCase())) {
                return false;
            }
            
            element.setAttribute(name, value);
            return true;
        }
        return false;
    }
};

CSRF Protection

Django CSRF Implementation

# Django settings for CSRF protection
CSRF_COOKIE_SECURE = True  # Use HTTPS only
CSRF_COOKIE_HTTPONLY = True  # Prevent JavaScript access
CSRF_COOKIE_SAMESITE = 'Strict'  # Prevent cross-site requests
CSRF_TRUSTED_ORIGINS = ['https://yourdomain.com']

JavaScript CSRF Handling

// CSRF Token Management
const CSRFManager = {
    // Get CSRF token from cookie
    getTokenFromCookie() {
        const cookies = document.cookie.split(';');
        for (let cookie of cookies) {
            const [name, value] = cookie.trim().split('=');
            if (name === 'csrftoken') {
                return decodeURIComponent(value);
            }
        }
        return null;
    },
    
    // Get CSRF token from form
    getTokenFromForm() {
        const tokenInput = document.querySelector('[name=csrfmiddlewaretoken]');
        return tokenInput ? tokenInput.value : null;
    },
    
    // Get CSRF token from meta tag
    getTokenFromMeta() {
        const metaTag = document.querySelector('meta[name="csrf-token"]');
        return metaTag ? metaTag.getAttribute('content') : null;
    },
    
    // Get CSRF token (try multiple sources)
    getToken() {
        return this.getTokenFromForm() || 
               this.getTokenFromCookie() || 
               this.getTokenFromMeta();
    },
    
    // Add CSRF token to headers
    addToHeaders(headers = {}) {
        const token = this.getToken();
        if (token) {
            headers['X-CSRFToken'] = token;
        }
        return headers;
    },
    
    // Add CSRF token to FormData
    addToFormData(formData) {
        const token = this.getToken();
        if (token) {
            formData.append('csrfmiddlewaretoken', token);
        }
        return formData;
    }
};

// Usage with fetch
async function secureRequest(url, options = {}) {
    const headers = CSRFManager.addToHeaders(options.headers || {});
    
    return fetch(url, {
        ...options,
        headers,
        credentials: 'same-origin'  // Include cookies
    });
}

File Upload Security

Client-Side File Validation

// Secure File Upload Handler
const SecureFileUpload = {
    // Allowed file types
    allowedTypes: {
        'image': ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'],
        'document': ['application/pdf', 'text/plain', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
        'data': ['text/csv', 'application/json', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
    },
    
    // Maximum file sizes (in bytes)
    maxSizes: {
        'image': 5 * 1024 * 1024,      // 5MB
        'document': 10 * 1024 * 1024,  // 10MB
        'data': 25 * 1024 * 1024       // 25MB
    },
    
    // Validate file
    validateFile(file, category = 'document') {
        const errors = [];
        
        // Check file exists
        if (!file || !file.name) {
            errors.push('No file selected');
            return { isValid: false, errors };
        }
        
        // Check file size
        const maxSize = this.maxSizes[category];
        if (file.size > maxSize) {
            errors.push(`File too large. Maximum size: ${(maxSize / (1024 * 1024)).toFixed(1)}MB`);
        }
        
        // Check file type
        const allowedTypes = this.allowedTypes[category];
        if (!allowedTypes.includes(file.type)) {
            errors.push(`Invalid file type. Allowed types: ${allowedTypes.join(', ')}`);
        }
        
        // Check file name
        const fileName = file.name.toLowerCase();
        const dangerousExtensions = ['.exe', '.bat', '.cmd', '.scr', '.pif', '.vbs', '.js', '.jar', '.php', '.asp', '.aspx'];
        
        if (dangerousExtensions.some(ext => fileName.endsWith(ext))) {
            errors.push('Potentially dangerous file type detected');
        }
        
        // Check for null bytes
        if (file.name.includes('\0')) {
            errors.push('Invalid file name');
        }
        
        // Check file name length
        if (file.name.length > 255) {
            errors.push('File name too long');
        }
        
        return {
            isValid: errors.length === 0,
            errors
        };
    },
    
    // Secure file upload
    async uploadFile(file, endpoint, category = 'document') {
        // Validate file
        const validation = this.validateFile(file, category);
        if (!validation.isValid) {
            throw new Error(validation.errors.join(', '));
        }
        
        // Create FormData
        const formData = new FormData();
        formData.append('file', file);
        formData.append('category', category);
        
        // Add CSRF token
        CSRFManager.addToFormData(formData);
        
        // Upload with progress tracking
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            
            xhr.upload.addEventListener('progress', (e) => {
                if (e.lengthComputable) {
                    const percentComplete = (e.loaded / e.total) * 100;
                    this.updateProgress(percentComplete);
                }
            });
            
            xhr.addEventListener('load', () => {
                if (xhr.status === 200) {
                    try {
                        const response = JSON.parse(xhr.responseText);
                        resolve(response);
                    } catch (error) {
                        reject(new Error('Invalid response format'));
                    }
                } else {
                    reject(new Error(`Upload failed: ${xhr.status}`));
                }
            });
            
            xhr.addEventListener('error', () => {
                reject(new Error('Upload failed'));
            });
            
            xhr.addEventListener('timeout', () => {
                reject(new Error('Upload timeout'));
            });
            
            xhr.timeout = 30000; // 30 second timeout
            xhr.open('POST', endpoint);
            xhr.send(formData);
        });
    },
    
    updateProgress(percent) {
        const progressBar = document.querySelector('.upload-progress');
        if (progressBar) {
            progressBar.style.width = `${percent}%`;
        }
    }
};

Content Filtering

Input Content Filtering

// Content Filter for User Input
const ContentFilter = {
    // Profanity and inappropriate content filter
    inappropriateTerms: [
        // Add terms as needed (consider using external service)
    ],
    
    // Spam detection patterns
    spamPatterns: [
        /(.)\1{4,}/g,                    // Repeated characters
        /http[s]?:\/\/[^\s]+/gi,         // URLs
        /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g, // Phone numbers
        /[A-Z]{3,}/g,                    // Excessive caps
        /(.{1,})\1{3,}/g                 // Repeated words/phrases
    ],
    
    // Filter content
    filterContent(content) {
        if (!content || typeof content !== 'string') {
            return { isValid: true, filtered: content, warnings: [] };
        }
        
        const warnings = [];
        let filtered = content;
        
        // Check for inappropriate terms
        const inappropriateFound = this.inappropriateTerms.some(term => 
            content.toLowerCase().includes(term.toLowerCase())
        );
        
        if (inappropriateFound) {
            warnings.push('Content contains inappropriate language');
        }
        
        // Check for spam patterns
        let spamScore = 0;
        this.spamPatterns.forEach(pattern => {
            const matches = content.match(pattern);
            if (matches) {
                spamScore += matches.length;
            }
        });
        
        if (spamScore > 3) {
            warnings.push('Content appears to be spam');
        }
        
        // Check content length
        if (content.length > 10000) {
            warnings.push('Content is very long');
        }
        
        // Basic content sanitization
        filtered = content.trim();
        
        return {
            isValid: warnings.length === 0,
            filtered,
            warnings,
            spamScore
        };
    },
    
    // Rate limiting for content submission
    submissionTimes: new Map(),
    
    checkRateLimit(userId, maxSubmissions = 5, timeWindow = 60000) {
        const now = Date.now();
        const userSubmissions = this.submissionTimes.get(userId) || [];
        
        // Remove old submissions
        const recentSubmissions = userSubmissions.filter(time => 
            now - time < timeWindow
        );
        
        if (recentSubmissions.length >= maxSubmissions) {
            return {
                allowed: false,
                message: 'Too many submissions. Please wait before submitting again.'
            };
        }
        
        // Add current submission
        recentSubmissions.push(now);
        this.submissionTimes.set(userId, recentSubmissions);
        
        return {
            allowed: true,
            remaining: maxSubmissions - recentSubmissions.length
        };
    }
};

Secure Communication

API Security

// Secure API Communication
const SecureAPI = {
    // Base configuration
    config: {
        baseURL: '/api/v1',
        timeout: 30000,
        retryAttempts: 3,
        retryDelay: 1000
    },
    
    // Make secure request
    async request(endpoint, options = {}) {
        const url = `${this.config.baseURL}${endpoint}`;
        
        // Default security headers
        const headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            ...options.headers
        };
        
        // Add CSRF token
        CSRFManager.addToHeaders(headers);
        
        const config = {
            method: 'GET',
            headers,
            credentials: 'same-origin',
            timeout: this.config.timeout,
            ...options
        };
        
        let lastError;
        
        // Retry logic
        for (let attempt = 0; attempt < this.config.retryAttempts; attempt++) {
            try {
                const response = await this.makeRequest(url, config);
                
                // Check if response is valid
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                // Validate response content type
                const contentType = response.headers.get('content-type');
                if (!contentType || !contentType.includes('application/json')) {
                    throw new Error('Invalid response content type');
                }
                
                const data = await response.json();
                
                // Validate response structure
                if (!this.validateResponse(data)) {
                    throw new Error('Invalid response structure');
                }
                
                return data;
                
            } catch (error) {
                lastError = error;
                
                // Don't retry on client errors
                if (error.status && error.status >= 400 && error.status < 500) {
                    throw error;
                }
                
                // Wait before retry
                if (attempt < this.config.retryAttempts - 1) {
                    await this.delay(this.config.retryDelay * (attempt + 1));
                }
            }
        }
        
        throw lastError;
    },
    
    // Make actual request with timeout
    async makeRequest(url, config) {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), config.timeout);
        
        try {
            const response = await fetch(url, {
                ...config,
                signal: controller.signal
            });
            
            clearTimeout(timeoutId);
            return response;
            
        } catch (error) {
            clearTimeout(timeoutId);
            throw error;
        }
    },
    
    // Validate response structure
    validateResponse(data) {
        // Basic response validation
        if (!data || typeof data !== 'object') {
            return false;
        }
        
        // Check for required fields
        const requiredFields = ['status', 'data'];
        return requiredFields.every(field => field in data);
    },
    
    // Delay utility
    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    },
    
    // Secure file upload
    async uploadFile(endpoint, file, additionalData = {}) {
        const formData = new FormData();
        formData.append('file', file);
        
        // Add additional data
        Object.entries(additionalData).forEach(([key, value]) => {
            formData.append(key, value);
        });
        
        // Add CSRF token
        CSRFManager.addToFormData(formData);
        
        return this.request(endpoint, {
            method: 'POST',
            body: formData,
            headers: {
                // Don't set Content-Type for FormData
            }
        });
    }
};

Error Handling Security

Secure Error Display

// Secure Error Handling
const SecureErrorHandler = {
    // Error types
    errorTypes: {
        VALIDATION: 'validation',
        AUTHENTICATION: 'authentication',
        AUTHORIZATION: 'authorization',
        SERVER: 'server',
        NETWORK: 'network',
        RATE_LIMIT: 'rate_limit'
    },
    
    // Handle errors securely
    handleError(error, context = {}) {
        console.error('Error occurred:', error, context);
        
        // Determine error type
        const errorType = this.categorizeError(error);
        
        // Get user-friendly message
        const userMessage = this.getUserMessage(errorType, error);
        
        // Log error for monitoring (don't expose sensitive info)
        this.logError(errorType, error, context);
        
        // Display error to user
        this.displayError(userMessage, errorType);
        
        // Handle specific error types
        switch (errorType) {
            case this.errorTypes.AUTHENTICATION:
                this.handleAuthError();
                break;
            case this.errorTypes.RATE_LIMIT:
                this.handleRateLimitError();
                break;
            case this.errorTypes.VALIDATION:
                this.handleValidationError(error);
                break;
        }
    },
    
    // Categorize error
    categorizeError(error) {
        if (error.status === 401) return this.errorTypes.AUTHENTICATION;
        if (error.status === 403) return this.errorTypes.AUTHORIZATION;
        if (error.status === 429) return this.errorTypes.RATE_LIMIT;
        if (error.status >= 400 && error.status < 500) return this.errorTypes.VALIDATION;
        if (error.status >= 500) return this.errorTypes.SERVER;
        if (error.name === 'NetworkError') return this.errorTypes.NETWORK;
        return this.errorTypes.SERVER;
    },
    
    // Get user-friendly message
    getUserMessage(errorType, error) {
        const messages = {
            [this.errorTypes.VALIDATION]: 'Please check your input and try again.',
            [this.errorTypes.AUTHENTICATION]: 'Please log in to continue.',
            [this.errorTypes.AUTHORIZATION]: 'You do not have permission to perform this action.',
            [this.errorTypes.SERVER]: 'Something went wrong. Please try again later.',
            [this.errorTypes.NETWORK]: 'Network connection error. Please check your connection.',
            [this.errorTypes.RATE_LIMIT]: 'Too many requests. Please wait before trying again.'
        };
        
        return messages[errorType] || 'An unexpected error occurred.';
    },
    
    // Log error for monitoring
    logError(errorType, error, context) {
        const logData = {
            type: errorType,
            message: error.message,
            status: error.status,
            timestamp: new Date().toISOString(),
            context: this.sanitizeContext(context)
        };
        
        // Send to monitoring service (implement as needed)
        // this.sendToMonitoring(logData);
    },
    
    // Sanitize context for logging
    sanitizeContext(context) {
        const sanitized = { ...context };
        
        // Remove sensitive information
        const sensitiveKeys = ['password', 'token', 'key', 'secret'];
        sensitiveKeys.forEach(key => {
            if (sanitized[key]) {
                sanitized[key] = '[REDACTED]';
            }
        });
        
        return sanitized;
    },
    
    // Display error to user
    displayError(message, type) {
        const errorContainer = document.getElementById('errorContainer');
        if (!errorContainer) return;
        
        const errorElement = document.createElement('div');
        errorElement.className = `alert alert-error alert-${type}`;
        errorElement.innerHTML = `
            <span class="alert-icon">⚠️</span>
            <span class="alert-message">${this.escapeHTML(message)}</span>
            <button type="button" class="alert-close" onclick="this.parentElement.remove()">
                &times;
            </button>
        `;
        
        errorContainer.appendChild(errorElement);
        
        // Auto-remove after 5 seconds
        setTimeout(() => {
            if (errorElement.parentNode) {
                errorElement.remove();
            }
        }, 5000);
    },
    
    // Handle authentication errors
    handleAuthError() {
        // Redirect to login page
        setTimeout(() => {
            window.location.href = '/login/';
        }, 2000);
    },
    
    // Handle rate limit errors
    handleRateLimitError() {
        // Disable submit buttons temporarily
        const submitButtons = document.querySelectorAll('[type="submit"]');
        submitButtons.forEach(button => {
            button.disabled = true;
            setTimeout(() => {
                button.disabled = false;
            }, 60000); // 1 minute
        });
    },
    
    // Handle validation errors
    handleValidationError(error) {
        if (error.details && typeof error.details === 'object') {
            Object.entries(error.details).forEach(([field, messages]) => {
                this.showFieldError(field, messages);
            });
        }
    },
    
    // Show field-specific error
    showFieldError(fieldName, messages) {
        const field = document.getElementById(fieldName);
        if (!field) return;
        
        field.classList.add('is-invalid');
        
        const errorElement = document.getElementById(`${fieldName}-error`);
        if (errorElement) {
            errorElement.textContent = Array.isArray(messages) ? messages.join(', ') : messages;
        }
    },
    
    // Escape HTML for safe display
    escapeHTML(str) {
        const div = document.createElement('div');
        div.textContent = str;
        return div.innerHTML;
    }
};

Security Testing

Security Test Suite

// Security Testing Utilities
const SecurityTests = {
    // Test XSS prevention
    testXSSPrevention() {
        const xssPayloads = [
            '<script>alert("XSS")</script>',
            'javascript:alert("XSS")',
            '<img src=x onerror=alert("XSS")>',
            '<svg onload=alert("XSS")>',
            '"><script>alert("XSS")</script>'
        ];
        
        xssPayloads.forEach(payload => {
            const result = HTMLSanitizer.sanitize(payload);
            console.assert(
                !result.includes('<script>') && !result.includes('javascript:'),
                `XSS payload not properly sanitized: ${payload}`
            );
        });
    },
    
    // Test input validation
    testInputValidation() {
        const testCases = [
            { input: '', expected: false, message: 'Empty input should be invalid' },
            { input: 'a'.repeat(1000), expected: false, message: 'Long input should be invalid' },
            { input: '<script>alert("test")</script>', expected: false, message: 'Script tags should be invalid' },
            { input: 'Valid input', expected: true, message: 'Valid input should pass' }
        ];
        
        testCases.forEach(({ input, expected, message }) => {
            const result = InputValidator.validateText(input, { required: true, maxLength: 100 });
            console.assert(result.isValid === expected, message);
        });
    },
    
    // Test file upload security
    testFileUploadSecurity() {
        const maliciousFiles = [
            { name: 'test.exe', type: 'application/exe' },
            { name: 'script.js', type: 'text/javascript' },
            { name: 'test.php', type: 'application/php' },
            { name: 'normal.txt', type: 'text/plain' }
        ];
        
        maliciousFiles.forEach(file => {
            const mockFile = new File(['test'], file.name, { type: file.type });
            const result = SecureFileUpload.validateFile(mockFile);
            
            const shouldBeValid = file.name === 'normal.txt';
            console.assert(
                result.isValid === shouldBeValid,
                `File ${file.name} validation failed`
            );
        });
    },
    
    // Run all security tests
    runAllTests() {
        console.log('Running security tests...');
        
        this.testXSSPrevention();
        this.testInputValidation();
        this.testFileUploadSecurity();
        
        console.log('Security tests completed.');
    }
};

Security Monitoring

Security Event Logging

// Security Event Logger
const SecurityLogger = {
    // Log security events
    logEvent(eventType, details = {}) {
        const event = {
            type: eventType,
            timestamp: new Date().toISOString(),
            userAgent: navigator.userAgent,
            url: window.location.href,
            details: this.sanitizeDetails(details)
        };
        
        // Send to security monitoring service
        this.sendToSecurityService(event);
        
        // Log to console for development
        console.log('Security event:', event);
    },
    
    // Sanitize details for logging
    sanitizeDetails(details) {
        const sanitized = { ...details };
        
        // Remove sensitive information
        const sensitiveKeys = ['password', 'token', 'key', 'secret', 'creditCard'];
        sensitiveKeys.forEach(key => {
            if (sanitized[key]) {
                sanitized[key] = '[REDACTED]';
            }
        });
        
        return sanitized;
    },
    
    // Send to security monitoring service
    sendToSecurityService(event) {
        // Implement based on your monitoring solution
        // fetch('/api/security-events', {
        //     method: 'POST',
        //     headers: { 'Content-Type': 'application/json' },
        //     body: JSON.stringify(event)
        // });
    },
    
    // Log suspicious activity
    logSuspiciousActivity(description, details = {}) {
        this.logEvent('suspicious_activity', {
            description,
            ...details
        });
    },
    
    // Log failed authentication
    logFailedAuth(username, details = {}) {
        this.logEvent('failed_authentication', {
            username,
            ...details
        });
    },
    
    // Log XSS attempt
    logXSSAttempt(payload, field) {
        this.logEvent('xss_attempt', {
            payload: payload.substring(0, 100), // Limit length
            field
        });
    }
};

This comprehensive security guide ensures that all agent implementations follow security best practices and prevent common vulnerabilities.