UNPKG

prisma-zod-generator

Version:

Prisma 2+ generator to emit Zod schemas from your Prisma schema

168 lines 5.33 kB
"use strict"; /** * Security utilities for safe file operations and input sanitization */ Object.defineProperty(exports, "__esModule", { value: true }); exports.sanitizeFileName = sanitizeFileName; exports.safeJoin = safeJoin; exports.sanitizeModelName = sanitizeModelName; exports.sanitizeFieldName = sanitizeFieldName; exports.validateTemplateInput = validateTemplateInput; const path_1 = require("path"); /** * Sanitize a filename to prevent path traversal attacks */ function sanitizeFileName(fileName) { if (!fileName || typeof fileName !== 'string') { throw new Error('Invalid filename provided'); } // Remove any path separators and dangerous characters const sanitized = fileName .replace(/[\/\\:*?"<>|]/g, '') // Remove path separators and special chars .replace(/\.\./g, '') // Remove parent directory references .replace(/^\.+/, '') // Remove leading dots .trim(); if (!sanitized) { throw new Error('Filename becomes empty after sanitization'); } if (sanitized.length > 255) { throw new Error('Filename too long'); } return sanitized; } /** * Safely join paths ensuring they stay within the base directory */ function safeJoin(basePath, ...pathSegments) { if (!basePath || typeof basePath !== 'string') { throw new Error('Invalid base path provided'); } // Sanitize all path segments const sanitizedSegments = pathSegments .map((segment) => { if (!segment || typeof segment !== 'string') { throw new Error('Invalid path segment provided'); } // Remove dangerous characters and path traversal attempts return segment .replace(/[\/\\:*?"<>|]/g, '_') // Replace dangerous chars with underscore .replace(/\.\./g, '') // Remove parent directory references .replace(/^\.+/, '') // Remove leading dots .trim(); }) .filter((segment) => segment.length > 0); if (sanitizedSegments.length === 0) { return basePath; } const fullPath = (0, path_1.join)(basePath, ...sanitizedSegments); const resolvedBasePath = (0, path_1.resolve)(basePath); const resolvedFullPath = (0, path_1.resolve)(fullPath); // Ensure the resolved path is within the base directory const relativePath = (0, path_1.relative)(resolvedBasePath, resolvedFullPath); if (relativePath.startsWith('..') || relativePath === '..') { throw new Error('Path traversal attempt detected'); } return fullPath; } /** * Sanitize model name for safe use in code generation */ function sanitizeModelName(modelName) { if (!modelName || typeof modelName !== 'string') { throw new Error('Invalid model name provided'); } // Ensure valid TypeScript identifier const sanitized = modelName .replace(/[^a-zA-Z0-9_$]/g, '') // Only allow valid identifier chars .replace(/^[0-9]/, '_$&'); // Prefix with underscore if starts with number if (!sanitized || sanitized.length === 0) { throw new Error('Model name becomes empty after sanitization'); } // Check against reserved keywords const reservedKeywords = [ 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'null', 'return', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', ]; if (reservedKeywords.includes(sanitized.toLowerCase())) { return `${sanitized}_Model`; } return sanitized; } /** * Sanitize field name for safe use in code generation */ function sanitizeFieldName(fieldName) { if (!fieldName || typeof fieldName !== 'string') { throw new Error('Invalid field name provided'); } // Ensure valid property name const sanitized = fieldName .replace(/[^a-zA-Z0-9_$]/g, '') // Only allow valid property chars .replace(/^[0-9]/, '_$&'); // Prefix with underscore if starts with number if (!sanitized || sanitized.length === 0) { throw new Error('Field name becomes empty after sanitization'); } return sanitized; } /** * Validate that a string contains only safe characters for templates */ function validateTemplateInput(input) { if (!input || typeof input !== 'string') { throw new Error('Invalid template input provided'); } // Check for potential code injection patterns const dangerousPatterns = [ /<script/i, /javascript:/i, /on\w+\s*=/i, /eval\s*\(/i, /function\s*\(/i, /=>\s*\{/, /\$\{.*\}/, /`.*`/, /<!--.*-->/, ]; for (const pattern of dangerousPatterns) { if (pattern.test(input)) { throw new Error('Potentially dangerous content detected in template input'); } } return input; } //# sourceMappingURL=securityUtils.js.map