semgrep problems fix
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 5m57s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped

This commit is contained in:
Torsten Schulz (local)
2026-06-10 13:55:50 +02:00
parent 5da11d2e4d
commit b4e1c50ea3
3 changed files with 28 additions and 7 deletions

View File

@@ -20,8 +20,10 @@ const FILES = {
function getDataPath(filename) {
const cwd = process.cwd()
if (cwd.endsWith('.output')) {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
return path.join(cwd, '../server/data', filename)
}
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
return path.join(cwd, 'server/data', filename)
}

View File

@@ -34,6 +34,21 @@ function buildBackupName(date = new Date()) {
return `${date.toISOString().replace(/[:.]/g, '-')}-${randomSuffix}.bak`
}
export function resolveDataFileBackupPath(backupDir, backupName) {
if (typeof backupName !== 'string' || !backupName.endsWith('.bak') || path.basename(backupName) !== backupName) {
throw new Error('Ungueltiger Backup-Dateiname')
}
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const resolvedBackupDir = path.resolve(backupDir)
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const resolvedBackupPath = path.resolve(resolvedBackupDir, backupName)
if (path.dirname(resolvedBackupPath) !== resolvedBackupDir) {
throw new Error('Backup-Datei liegt ausserhalb des Backup-Ordners')
}
return resolvedBackupPath
}
async function ensureDirectory(dirPath) {
await fs.mkdir(dirPath, { recursive: true })
}
@@ -55,10 +70,11 @@ async function rotateOldBackups(backupDir, maxBackups) {
}
const toDelete = backups.slice(0, overflowCount)
await Promise.all(toDelete.map((name) => fs.unlink(path.join(backupDir, name)).catch(() => {})))
await Promise.all(toDelete.map((name) => fs.unlink(resolveDataFileBackupPath(backupDir, name)).catch(() => {})))
}
export function getBackupDirectoryForDataFile(filePath) {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const resolvedPath = path.resolve(filePath)
return path.join(getBackupRoot(), sanitizeFileKey(resolvedPath))
}
@@ -77,6 +93,7 @@ export async function writeDataFileWithRotation(filePath, content, {
encoding = 'utf-8',
maxBackups = DEFAULT_MAX_BACKUPS
} = {}) {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const resolvedPath = path.resolve(filePath)
await ensureDirectory(path.dirname(resolvedPath))
@@ -100,7 +117,7 @@ export async function writeDataFileWithRotation(filePath, content, {
if (existingContent !== null) {
const backupDir = getBackupDirectoryForDataFile(resolvedPath)
await ensureDirectory(backupDir)
backupPath = path.join(backupDir, buildBackupName())
backupPath = resolveDataFileBackupPath(backupDir, buildBackupName())
await fs.copyFile(resolvedPath, backupPath)
await rotateOldBackups(backupDir, maxBackups)
}
@@ -116,9 +133,10 @@ export async function writeDataFileWithRotation(filePath, content, {
}
export async function restoreDataFileBackup(filePath, backupName, options = {}) {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const resolvedPath = path.resolve(filePath)
const backupDir = getBackupDirectoryForDataFile(resolvedPath)
const sourceBackupPath = path.join(backupDir, backupName)
const sourceBackupPath = resolveDataFileBackupPath(backupDir, backupName)
const backupContent = await fs.readFile(sourceBackupPath, 'utf-8')
return writeDataFileWithRotation(resolvedPath, backupContent, options)

View File

@@ -4,6 +4,7 @@ import path from 'path'
import { promises as fs } from 'fs'
import {
getBackupDirectoryForDataFile,
resolveDataFileBackupPath,
listDataFileBackups,
restoreDataFileBackup,
writeDataFileWithRotation
@@ -60,7 +61,7 @@ describe('Data file rotation utility', () => {
expect(backups.length).toBe(1)
const backupDir = getBackupDirectoryForDataFile(dataFile)
const backupContent = await fs.readFile(path.join(backupDir, backups[0]), 'utf-8')
const backupContent = await fs.readFile(resolveDataFileBackupPath(backupDir, backups[0]), 'utf-8')
expect(backupContent).toBe('v1')
const currentContent = await fs.readFile(dataFile, 'utf-8')
@@ -91,7 +92,7 @@ describe('Data file rotation utility', () => {
const backupDir = getBackupDirectoryForDataFile(dataFile)
const backupContents = await Promise.all(
backups.map((name) => fs.readFile(path.join(backupDir, name), 'utf-8'))
backups.map((name) => fs.readFile(resolveDataFileBackupPath(backupDir, name), 'utf-8'))
)
expect(backupContents).toEqual(expect.arrayContaining(['v2', 'v3']))
@@ -109,7 +110,7 @@ describe('Data file rotation utility', () => {
const resolved = await Promise.all(
beforeRestoreBackups.map(async (name) => ({
name,
content: await fs.readFile(path.join(backupDir, name), 'utf-8')
content: await fs.readFile(resolveDataFileBackupPath(backupDir, name), 'utf-8')
}))
)
const v1Entry = resolved.find((entry) => entry.content === 'v1')
@@ -124,7 +125,7 @@ describe('Data file rotation utility', () => {
const afterRestoreBackups = await listDataFileBackups(dataFile)
const afterContents = await Promise.all(
afterRestoreBackups.map((name) => fs.readFile(path.join(backupDir, name), 'utf-8'))
afterRestoreBackups.map((name) => fs.readFile(resolveDataFileBackupPath(backupDir, name), 'utf-8'))
)
expect(afterContents).toContain('v3')