Files
harheimertc/server/utils/path-security.js
2025-12-20 10:49:20 +01:00

76 lines
2.4 KiB
JavaScript

import path from 'path'
/**
* Validiert und normalisiert einen Dateinamen, um Path-Traversal zu verhindern
* @param {string} filename - Der zu validierende Dateiname
* @param {string[]} allowedExtensions - Erlaubte Dateiendungen (z.B. ['.jpg', '.png'])
* @returns {string} - Der validierte Dateiname
* @throws {Error} - Wenn der Dateiname ungültig ist
*/
export function sanitizeFilename(filename, allowedExtensions = []) {
if (!filename || typeof filename !== 'string') {
throw new Error('Ungültiger Dateiname')
}
// Entferne Path-Traversal-Versuche
const normalized = path.normalize(filename)
// Prüfe auf Path-Traversal (.., /, \)
if (normalized.includes('..') || normalized.startsWith('/') || normalized.startsWith('\\')) {
throw new Error('Ungültiger Dateiname: Path-Traversal erkannt')
}
// Extrahiere nur den Dateinamen (ohne Pfad)
const basename = path.basename(normalized)
// Prüfe auf leeren Dateinamen
if (!basename || basename === '.' || basename === '..') {
throw new Error('Ungültiger Dateiname')
}
// Prüfe Dateiendung falls angegeben
if (allowedExtensions.length > 0) {
const ext = path.extname(basename).toLowerCase()
if (!allowedExtensions.includes(ext)) {
throw new Error(`Ungültige Dateiendung. Erlaubt: ${allowedExtensions.join(', ')}`)
}
}
return basename
}
/**
* Validiert eine UUID
* @param {string} id - Die zu validierende ID
* @returns {boolean} - True wenn gültige UUID
*/
export function isValidUUID(id) {
if (!id || typeof id !== 'string') {
return false
}
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
return uuidRegex.test(id)
}
/**
* Validiert einen Dateinamen mit UUID-Präfix
* @param {string} filename - Der zu validierende Dateiname
* @param {string[]} allowedExtensions - Erlaubte Dateiendungen
* @returns {boolean} - True wenn gültig
*/
export function isValidUUIDFilename(filename, allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']) {
if (!filename || typeof filename !== 'string') {
return false
}
const ext = path.extname(filename).toLowerCase()
if (allowedExtensions.length > 0 && !allowedExtensions.includes(ext)) {
return false
}
const basename = path.basename(filename, ext)
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
return uuidRegex.test(basename)
}