feat(security): enhance input validation and security measures across various routes
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m38s

This commit is contained in:
2026-03-04 08:39:29 +01:00
parent ba096a31a2
commit e22a895672
13 changed files with 222 additions and 29 deletions

View File

@@ -30,13 +30,25 @@ const rawTrustProxy = process.env.TRUST_PROXY ?? 'loopback';
const trustProxy = /^\d+$/.test(rawTrustProxy) ? parseInt(rawTrustProxy, 10) : rawTrustProxy;
app.set('trust proxy', trustProxy);
// ── Security headers ───────────────────────────────────────────────────────
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
if (process.env.NODE_ENV === 'production') {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
next();
});
// Middleware
// M10: restrict CORS in production; allow all in development
// M10: restrict CORS in production; deny cross-origin by default
const corsOptions = process.env.APP_URL
? { origin: process.env.APP_URL, credentials: true }
: {};
: { origin: false };
app.use(cors(corsOptions));
app.use(express.json());
app.use(express.json({ limit: '100kb' }));
// Request/Response logging (filters sensitive fields)
app.use(requestResponseLogger);
@@ -45,9 +57,10 @@ async function start() {
await initDatabase();
initMailer();
// Serve uploaded files (avatars, presentations)
// Serve uploaded files (avatars, branding only — presentations require auth)
const uploadsPath = path.join(__dirname, '..', 'uploads');
app.use('/uploads', express.static(uploadsPath));
app.use('/uploads/avatars', express.static(path.join(uploadsPath, 'avatars')));
app.use('/uploads/branding', express.static(path.join(uploadsPath, 'branding')));
// API Routes
app.use('/api/auth', authRoutes);