Files
CubeAdmin/lib/security/sanitize.ts
2026-03-08 15:49:34 +01:00

61 lines
1.9 KiB
TypeScript

/**
* 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);
}