UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

164 lines 5.25 kB
/** * Input Validation and Sanitization Utilities * ========================================== * * Provides comprehensive input validation to prevent injection attacks * and ensure data integrity throughout the MIRA system. */ import * as path from 'path'; /** * Validates and sanitizes file paths to prevent directory traversal attacks */ export function validateFilePath(filePath, allowedRoot) { // Remove any null bytes filePath = filePath.replace(/\0/g, ''); // Normalize the path const normalizedPath = path.normalize(filePath); // Check for directory traversal attempts if (normalizedPath.includes('..')) { throw new Error('Directory traversal attempt detected'); } // If allowedRoot is specified, ensure the path is within it if (allowedRoot) { const resolvedPath = path.resolve(normalizedPath); const resolvedRoot = path.resolve(allowedRoot); if (!resolvedPath.startsWith(resolvedRoot)) { throw new Error('Path is outside allowed directory'); } } return normalizedPath; } /** * Validates command arguments to prevent command injection */ export function validateCommandArgs(args) { return args.map(arg => { // Remove null bytes arg = arg.replace(/\0/g, ''); // Check for shell metacharacters that could lead to injection const dangerousChars = /[;&|`$<>\\]/; if (dangerousChars.test(arg)) { throw new Error(`Potentially dangerous characters in argument: ${arg}`); } return arg; }); } /** * Sanitizes user input for safe display (prevents XSS in terminal output) */ export function sanitizeForDisplay(input) { return input .replace(/\x1b\[[0-9;]*m/g, '') // Remove ANSI escape codes .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '') // Remove control characters .substring(0, 10000); // Limit length to prevent DoS } /** * Validates environment variable names */ export function validateEnvVarName(name) { // Environment variable names should only contain alphanumeric and underscore return /^[A-Z_][A-Z0-9_]*$/i.test(name); } /** * Validates and sanitizes JSON input */ export function validateJSON(input) { try { // Parse to validate structure const parsed = JSON.parse(input); // Re-stringify to remove any potential code injection return JSON.parse(JSON.stringify(parsed)); } catch (error) { throw new Error('Invalid JSON input'); } } /** * Validates Git branch/tag names */ export function validateGitRef(ref) { // Git ref name rules const invalidPatterns = [ /^\./, // Cannot start with dot /\.$/, // Cannot end with dot /\.\./, // Cannot contain .. /\/\//, // Cannot contain // /^\//, // Cannot start with / /\/$/, // Cannot end with / /@{/, // Cannot contain @{ /[~^:?*\[\]\\]/, // Cannot contain special chars ]; for (const pattern of invalidPatterns) { if (pattern.test(ref)) { throw new Error(`Invalid Git reference: ${ref}`); } } return ref; } /** * Rate limiting helper to prevent DoS attacks */ export class RateLimiter { maxRequests; windowMs; requests = new Map(); constructor(maxRequests = 100, windowMs = 60000 // 1 minute ) { this.maxRequests = maxRequests; this.windowMs = windowMs; } isAllowed(identifier) { const now = Date.now(); const requests = this.requests.get(identifier) || []; // Remove old requests outside the window const validRequests = requests.filter(time => now - time < this.windowMs); if (validRequests.length >= this.maxRequests) { return false; } validRequests.push(now); this.requests.set(identifier, validRequests); // Cleanup old entries periodically if (Math.random() < 0.01) { this.cleanup(); } return true; } cleanup() { const now = Date.now(); for (const [key, requests] of this.requests.entries()) { const validRequests = requests.filter(time => now - time < this.windowMs); if (validRequests.length === 0) { this.requests.delete(key); } else { this.requests.set(key, validRequests); } } } } /** * Validates memory content before storage */ export function validateMemoryContent(content) { // Check size limit (1MB) if (content.length > 1024 * 1024) { throw new Error('Memory content exceeds size limit (1MB)'); } // Remove any potential script tags or HTML content = content.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, ''); content = content.replace(/<[^>]+>/g, ''); return content; } /** * Validates search queries */ export function validateSearchQuery(query) { // Limit query length if (query.length > 500) { throw new Error('Search query too long'); } // Remove special regex characters that could cause ReDoS query = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return query; } //# sourceMappingURL=inputValidation.js.map