feat: Enhance security and validation in backend
- Added helmet for security headers and configured content security policy - Implemented CORS with a whitelist for allowed origins - Introduced express-validator for input validation in API endpoints - Set request size limits to prevent DoS attacks - Added global error handling and 404 response - Updated TypeScript configuration to use node16 module resolution - Improved Docker Compose configuration for security and resource limits - Created a comprehensive .env.example for environment configuration - Implemented automated security scans in CI/CD with Trivy - Added cleanup script for debugging ports - Established a detailed security policy document
This commit is contained in:
59
.vscode/cleanup-ports.sh
vendored
Normal file
59
.vscode/cleanup-ports.sh
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Debug Port Cleanup Script
|
||||
# Stellt sicher, dass die Debug-Ports frei sind und beendet laufende Prozesse
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PORTS=("3000" "3001" "9229" "5173" "9222")
|
||||
|
||||
echo "🧹 Prüfe und bereinige Debug-Ports (${PORTS[*]})..."
|
||||
|
||||
have_lsof=false
|
||||
have_fuser=false
|
||||
have_ss=false
|
||||
|
||||
command -v lsof >/dev/null 2>&1 && have_lsof=true
|
||||
command -v fuser >/dev/null 2>&1 && have_fuser=true
|
||||
command -v ss >/dev/null 2>&1 && have_ss=true
|
||||
|
||||
if [ "$have_lsof" = false ] && [ "$have_fuser" = false ] && [ "$have_ss" = false ]; then
|
||||
echo "⚠️ Weder lsof noch fuser/ss verfügbar. Ports können nicht geprüft/gekilled werden."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for PORT in "${PORTS[@]}"; do
|
||||
PIDS=""
|
||||
|
||||
if [ "$have_lsof" = true ]; then
|
||||
PIDS=$({ lsof -ti :"$PORT" 2>/dev/null || true; } | tr '\n' ' ')
|
||||
elif [ "$have_fuser" = true ]; then
|
||||
# fuser listet PIDs, -n tcp beschränkt auf TCP
|
||||
PIDS=$({ fuser -n tcp "$PORT" 2>/dev/null || true; } | tr '\n' ' ')
|
||||
elif [ "$have_ss" = true ]; then
|
||||
# ss fallback, extrahiere pid=... aus der letzten Spalte
|
||||
PIDS=$({ ss -ltnp "sport = :$PORT" 2>/dev/null || true; } | awk 'NR>1 {split($NF,pid,"pid="); split(pid[2],p,","); if(p[1]!=""){print p[1]}}' | tr '\n' ' ')
|
||||
fi
|
||||
|
||||
if [ -n "$PIDS" ]; then
|
||||
echo " ✓ Beende Prozesse auf Port $PORT (PID: $PIDS)"
|
||||
if [ "$have_fuser" = true ]; then
|
||||
fuser -k -n tcp "$PORT" 2>/dev/null || true
|
||||
else
|
||||
kill -9 $PIDS 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
echo " ○ Port $PORT ist frei"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "✅ Port-Bereinigung abgeschlossen."
|
||||
echo ""
|
||||
echo "Belegte Debug-Ports aktuell:"
|
||||
if [ "$have_lsof" = true ]; then
|
||||
lsof -i :3000 -i :3001 -i :9229 -i :5173 -i :9222 2>/dev/null || echo " Alle Debug-Ports sind frei ✓"
|
||||
elif [ "$have_ss" = true ]; then
|
||||
ss -ltnp "( sport = :3000 or sport = :3001 or sport = :9229 or sport = :5173 or sport = :9222 )" 2>/dev/null || echo " Alle Debug-Ports sind frei ✓"
|
||||
else
|
||||
echo " Port-Status nicht prüfbar (lsof/ss fehlen), Cleanup wurde dennoch ausgeführt."
|
||||
fi
|
||||
86
.vscode/launch.json
vendored
86
.vscode/launch.json
vendored
@@ -2,71 +2,49 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "🚀 Debug Backend",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "npx",
|
||||
"runtimeArgs": [
|
||||
"ts-node-dev",
|
||||
"--respawn",
|
||||
"--transpile-only",
|
||||
"--no-notify"
|
||||
],
|
||||
"args": ["src/index.ts"],
|
||||
"cwd": "${workspaceFolder}/backend",
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"sourceMaps": true,
|
||||
"restart": true,
|
||||
"outputCapture": "std",
|
||||
"presentation": {
|
||||
"group": "fullstack",
|
||||
"panel": "new"
|
||||
},
|
||||
"postDebugTask": "🛑 Terminate All Development Processes"
|
||||
},
|
||||
{
|
||||
"name": "🌐 Debug Frontend (Chrome)",
|
||||
"name": "Debug Vite",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}/frontend/src",
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
"webRoot": "${workspaceFolder}/Client",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"preLaunchTask": "Start Vite (after backend ready)"
|
||||
},
|
||||
{
|
||||
"name": "🔧 Debug Frontend (Edge)",
|
||||
"type": "msedge",
|
||||
"name": "Debug Backend",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}/frontend/src",
|
||||
"runtimeExecutable": "npx",
|
||||
"args": ["tsx", "watch", "--inspect=9229", "./src/index.ts"],
|
||||
"cwd": "${workspaceFolder}/Server",
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"preLaunchTask": "Clean Debug Ports",
|
||||
"envFile": "${workspaceFolder}/Server/.env",
|
||||
"env": {
|
||||
"PORT": "3001"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "Debug Jest Tests",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/Server/node_modules/jest/bin/jest.js",
|
||||
"args": [
|
||||
"--config=Server/tests/jest.config.cjs",
|
||||
"--runInBand"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "🚀🌐 Debug Full Stack (Chrome)",
|
||||
"preLaunchTask": "🌐 Frontend",
|
||||
"configurations": ["🚀 Debug Backend", "🌐 Debug Frontend (Chrome)"],
|
||||
"stopAll": true,
|
||||
"presentation": {
|
||||
"hidden": false,
|
||||
"group": "fullstack",
|
||||
"order": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "🚀🔧 Debug Full Stack (Edge)",
|
||||
"preLaunchTask": "🌐 Frontend",
|
||||
"configurations": ["🚀 Debug Backend", "🔧 Debug Frontend (Edge)"],
|
||||
"stopAll": true,
|
||||
"presentation": {
|
||||
"hidden": false,
|
||||
"group": "fullstack",
|
||||
"order": 2
|
||||
}
|
||||
"name": "Compound Debug",
|
||||
"configurations": ["Debug Vite", "Debug Backend"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
35
.vscode/settings.json
vendored
35
.vscode/settings.json
vendored
@@ -1,28 +1,9 @@
|
||||
{
|
||||
"typescript.preferences.includePackageJsonAutoImports": "auto",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/dist": true,
|
||||
"**/.git": true,
|
||||
"**/.DS_Store": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/dist": true
|
||||
},
|
||||
"typescript.updateImportsOnFileMove.enabled": "always",
|
||||
"emmet.includeLanguages": {
|
||||
"typescript": "typescriptreact"
|
||||
},
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"debug.node.autoAttach": "on",
|
||||
"terminal.integrated.enablePersistentSessions": false,
|
||||
"terminal.integrated.confirmOnKill": "editor",
|
||||
"task.autoDetect": "off",
|
||||
"task.showDecorations": true
|
||||
}
|
||||
"github.copilot.chat.languageContext.inline.typescript.enabled": true,
|
||||
"github.copilot.chat.languageContext.fix.typescript.enabled": true,
|
||||
"github.copilot.chat.edits.temporalContext.enabled": true,
|
||||
"github.copilot.chat.completionContext.typescript.mode": "on",
|
||||
"github.copilot.chat.agent.thinkingTool": true,
|
||||
"github.copilot.chat.followUps": "always",
|
||||
"debug.onTaskErrors": "abort"
|
||||
}
|
||||
350
.vscode/tasks.json
vendored
350
.vscode/tasks.json
vendored
@@ -2,320 +2,80 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Install Backend Dependencies",
|
||||
"label": "Clean Debug Ports",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["install"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
}
|
||||
"command": "bash ${workspaceFolder}/.vscode/cleanup-ports.sh",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Install Frontend Dependencies",
|
||||
"label": "Wait for Backend Ready",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["install"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
}
|
||||
"command": "bash -lc 'for i in {1..120}; do if (echo > /dev/tcp/127.0.0.1/3001) >/dev/null 2>&1; then exit 0; fi; sleep 1; done; echo \"Backend not ready on :3001\"; exit 1'",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "🖥️ Backend",
|
||||
"label": "Start Backend (watch + inspect)",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["run", "dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
},
|
||||
"group": "build",
|
||||
"command": "npx tsx watch --inspect=9229 ./src/index.ts",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "dedicated",
|
||||
"group": "dev",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": {
|
||||
"pattern": {
|
||||
"regexp": "^.*$",
|
||||
"file": 1,
|
||||
"location": 2,
|
||||
"message": 3
|
||||
},
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^.*ts-node-dev.*$",
|
||||
"endsPattern": "^🚀 Backend Server läuft auf Port \\d+$"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🌐 Frontend",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["start"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend",
|
||||
"cwd": "${workspaceFolder}/Server",
|
||||
"env": {
|
||||
"BROWSER": "none"
|
||||
"PORT": "3001"
|
||||
}
|
||||
},
|
||||
"group": "build",
|
||||
"dependsOn": "Clean Debug Ports",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "backend-ready",
|
||||
"fileLocation": ["absolute"],
|
||||
"pattern": {
|
||||
"regexp": "^(.*)$",
|
||||
"message": 1
|
||||
},
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "Starte Datenbankinitialisierung|Server läuft unter http://localhost:3001",
|
||||
"endsPattern": "NotificationScheduler erfolgreich initialisiert"
|
||||
}
|
||||
}
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
"clear": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Start Vite (after backend ready)",
|
||||
"type": "npm",
|
||||
"script": "frontend",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "dedicated",
|
||||
"group": "dev",
|
||||
"showReuseMessage": false
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/Client"
|
||||
},
|
||||
"problemMatcher": {
|
||||
"owner": "custom",
|
||||
"pattern": {
|
||||
"regexp": "^.*$",
|
||||
"file": 1,
|
||||
"location": 2,
|
||||
"message": 3
|
||||
},
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^.*Starting the development server.*$",
|
||||
"endsPattern": "^.*webpack compiled.*$"
|
||||
"dependsOn": "Wait for Backend Ready",
|
||||
"dependsOrder": "sequence",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "vite",
|
||||
"fileLocation": ["relative", "${workspaceFolder}"],
|
||||
"pattern": {
|
||||
"regexp": "^(.*)$",
|
||||
"file": 1,
|
||||
"message": 1
|
||||
},
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "VITE|ready in",
|
||||
"endsPattern": "localhost:3000"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🛑 Kill Frontend Process",
|
||||
"type": "shell",
|
||||
"command": "pkill",
|
||||
"args": ["-f", "npm start"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "🛑 Kill Backend Process",
|
||||
"type": "shell",
|
||||
"command": "pkill",
|
||||
"args": ["-f", "ts-node-dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "📊 Show Development Processes Status",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"echo '📊 Aktuelle Development-Prozesse:'; echo ''; ps aux | grep -E 'npm.*start|react-scripts|ts-node-dev' | grep -v grep | awk '{print \"PID: \" $2 \" - \" $11 \" \" $12 \" \" $13}' || echo 'Keine Development-Prozesse gefunden'"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "🛑 Cleanup Development Processes",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"pkill -f 'ts-node-dev' > /dev/null 2>&1 || true; pkill -f 'npm.*start' > /dev/null 2>&1 || true; pkill -f 'react-scripts' > /dev/null 2>&1 || true"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"clear": false,
|
||||
"showReuseMessage": false,
|
||||
"close": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"isBackground": false,
|
||||
"runOptions": {
|
||||
"reevaluateOnRerun": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🧹 Post Debug Cleanup",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": ["-c", "/workspace/scripts/post-debug-cleanup.sh"],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "new",
|
||||
"clear": false,
|
||||
"showReuseMessage": false,
|
||||
"close": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"isBackground": false,
|
||||
"runOptions": {
|
||||
"reevaluateOnRerun": true,
|
||||
"runOn": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🔄 Force Kill All Dev Processes",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"RANDOM_ID=$RANDOM; echo \"Cleanup ID: $RANDOM_ID\" > /dev/null; pkill -9 -f 'ts-node-dev' > /dev/null 2>&1 || true; pkill -9 -f 'npm.*start' > /dev/null 2>&1 || true; pkill -9 -f 'react-scripts' > /dev/null 2>&1 || true"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"clear": false,
|
||||
"showReuseMessage": false,
|
||||
"close": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "🛑 Terminate All Development Processes",
|
||||
"type": "shell",
|
||||
"command": "/workspace/scripts/kill-dev-processes.sh",
|
||||
"args": [],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"clear": false,
|
||||
"showReuseMessage": false,
|
||||
"close": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"runOptions": {
|
||||
"runOn": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🛑 Terminate All Development Processes (Verbose)",
|
||||
"type": "shell",
|
||||
"command": "/workspace/scripts/kill-dev-processes.sh",
|
||||
"args": [],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "dedicated",
|
||||
"clear": true,
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "🚀 Start Full Stack (Split Terminal)",
|
||||
"dependsOrder": "parallel",
|
||||
"dependsOn": ["🖥️ Backend", "🌐 Frontend"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "🔄 Restart Full Stack",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"/workspace/scripts/kill-dev-processes.sh && sleep 2 && echo '🚀 Starte Full Stack...' && code --command 'workbench.action.tasks.runTask' 'shell: 🚀 Start Full Stack (Split Terminal)'"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"clear": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Build Backend",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["run", "build"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": ["$tsc"]
|
||||
},
|
||||
{
|
||||
"label": "Build Frontend",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": ["run", "build"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
"clear": false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user