Files
harheimertc/scripts/verify-no-public-writes.js
Torsten Schulz (local) b69130c2b2
All checks were successful
Code Analysis and Production Deploy / analyze (push) Successful in 5m56s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Successful in 2m36s
Fixed semgrep error
2026-06-14 21:29:53 +02:00

53 lines
1.6 KiB
JavaScript

import fs from 'fs'
import path from 'path'
const repoRoot = process.cwd()
const scanRoots = ['server']
const sourceExtensions = new Set(['.js', '.mjs', '.ts'])
const publicWritePattern = /\b(writeFile|appendFile|copyFile|rename|mkdir)\s*\([^)]*(public[/\\](?:data|uploads)|['"`]public['"`]\s*,\s*['"`](?:data|uploads)['"`])/s
function childPath(dir, name) {
if (name !== path.basename(name) || name.includes('/') || name.includes('\\')) {
throw new Error(`Ungueltiger Dateiname beim Scannen: ${name}`)
}
return `${dir}${path.sep}${name}`
}
function walk(dir) {
const entries = fs.readdirSync(dir, { withFileTypes: true })
return entries.flatMap((entry) => {
const fullPath = childPath(dir, entry.name)
if (entry.isDirectory()) return walk(fullPath)
return [fullPath]
})
}
const findings = []
for (const root of scanRoots) {
const absoluteRoot = path.join(repoRoot, root)
if (!fs.existsSync(absoluteRoot)) continue
for (const filePath of walk(absoluteRoot)) {
if (!sourceExtensions.has(path.extname(filePath))) continue
const content = fs.readFileSync(filePath, 'utf8')
if (!publicWritePattern.test(content)) continue
const relativePath = path.relative(repoRoot, filePath)
findings.push(relativePath)
}
}
if (findings.length > 0) {
console.error('Runtime-Schreibzugriffe nach public/data oder public/uploads gefunden:')
for (const finding of findings) {
console.error(`- ${finding}`)
}
console.error('Bitte stattdessen server/data bzw. server/data/public-data verwenden.')
process.exit(1)
}
console.log('OK: keine serverseitigen Runtime-Schreibzugriffe nach public/data oder public/uploads gefunden.')