/** * Input sanitization utilities. * Prevents XSS, command injection, and path traversal attacks. */ /** Shell metacharacters that must not appear in RCON commands sent to the OS. */ const SHELL_UNSAFE = /[;&|`$(){}[\]<>\\'"*?!#~]/; /** * Validate a Minecraft RCON command. * Commands go to the MC RCON protocol (not a shell), but we still strip * shell metacharacters as a defense-in-depth measure. */ export function sanitizeRconCommand(cmd: string): string { if (typeof cmd !== "string") throw new Error("Command must be a string"); const trimmed = cmd.trim(); if (trimmed.length === 0) throw new Error("Command cannot be empty"); if (trimmed.length > 32767) throw new Error("Command too long"); // RCON commands start with / or a bare word — never allow OS-level metacharacters if (SHELL_UNSAFE.test(trimmed)) { throw new Error("Command contains forbidden characters"); } return trimmed; } /** * Validate and normalize a file system path relative to a base directory. * Prevents path traversal (e.g. "../../etc/passwd"). */ export function sanitizeFilePath( inputPath: string, baseDir: string, ): string { const path = require("node:path"); const resolved = path.resolve(baseDir, inputPath); if (!resolved.startsWith(path.resolve(baseDir))) { throw new Error("Path traversal detected"); } return resolved; } /** * Strip HTML tags from user-provided strings to prevent stored XSS. * Use this before storing free-text fields in the database. */ export function stripHtml(input: string): string { return input.replace(/<[^>]*>/g, ""); } /** Validate a Minecraft UUID (8-4-4-4-12 hex). */ export function isValidMcUuid(uuid: string): boolean { return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test( uuid, ); } /** Validate a Minecraft username (3-16 chars, alphanumeric + underscore). */ export function isValidMcUsername(name: string): boolean { return /^[a-zA-Z0-9_]{3,16}$/.test(name); }