mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
fix(securite): lock down the two unauthenticated emergency endpoints
- POST /api/emergency-admin-reset accepted a fallback secret hardcoded in the repository, letting anyone who read the source reset the production admin account to admin/admin (EMERGENCY_SECRET is not set in the shipped docker-compose, so the fallback was live). The route now returns 404 unless EMERGENCY_SECRET is explicitly configured, and invalid attempts are logged. - POST /api/admin/emergency-migration ran database migrations with no authentication at all; it now requires an authenticated admin. A sweep of the remaining API surface found no other unauthenticated mutation or read routes beyond /api/health. .env.example documents EMERGENCY_SECRET and ENCRYPTION_KEY. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FHdE9nEh8zHhQNGpCgrtYe
This commit is contained in:
3 files changed
+28
-7
No files matched your search
+9
-1
@@ -21,4 +21,12 @@ POSTGRES_PORT=5434
|
||||
|
||||
# Note de sécurité:
|
||||
# Les identifiants sont préconfigurés pour simplifier le déploiement.
|
||||
# En production, vous pouvez les modifier si nécessaire.
|
||||
# En production, vous pouvez les modifier si nécessaire.
|
||||
# Chiffrement des secrets en base (mots de passe SMTP, jetons NocoDB).
|
||||
# Repli sur SESSION_SECRET si absent. ATTENTION : changer cette clé rend
|
||||
# les secrets déjà chiffrés illisibles.
|
||||
ENCRYPTION_KEY=
|
||||
|
||||
# Route de secours POST /api/emergency-admin-reset : désactivée si vide.
|
||||
# Ne définir qu'en cas de besoin, puis retirer.
|
||||
EMERGENCY_SECRET=
|
||||
@@ -74,14 +74,21 @@ async function registerProductionRoutes(app: Express): Promise<void> {
|
||||
});
|
||||
});
|
||||
|
||||
// Emergency admin reset endpoint (production only)
|
||||
// Emergency admin reset endpoint (production only)
|
||||
// SÉCURITÉ : n'existe que si EMERGENCY_SECRET est défini dans l'environnement.
|
||||
// L'ancien secret par défaut était codé en dur dans ce fichier, donc lisible
|
||||
// par quiconque accède au dépôt — n'importe qui pouvait réinitialiser le
|
||||
// compte admin en production.
|
||||
app.post('/api/emergency-admin-reset', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const emergencySecret = process.env.EMERGENCY_SECRET;
|
||||
if (!emergencySecret) {
|
||||
return res.status(404).json({ error: 'Not found' });
|
||||
}
|
||||
|
||||
const { secret } = req.body;
|
||||
|
||||
// Require emergency secret
|
||||
const emergencySecret = process.env.EMERGENCY_SECRET || 'logiflow-admin-reset-2025';
|
||||
if (secret !== emergencySecret) {
|
||||
if (!secret || secret !== emergencySecret) {
|
||||
console.warn('🚨 Tentative de reset admin avec un secret invalide');
|
||||
return res.status(403).json({ error: 'Invalid emergency secret' });
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -5558,8 +5558,14 @@ RÉSUMÉ DU SCAN
|
||||
});
|
||||
|
||||
// Emergency migration route for SAV priority column
|
||||
app.post('/api/admin/emergency-migration', async (req, res) => {
|
||||
// SÉCURITÉ : réservée aux administrateurs authentifiés (était accessible sans login)
|
||||
app.post('/api/admin/emergency-migration', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
|
||||
if (!user || user.role !== 'admin') {
|
||||
return res.status(403).json({ message: "Insufficient permissions" });
|
||||
}
|
||||
|
||||
console.log('🚨 EMERGENCY: Forcing SAV migration execution...');
|
||||
|
||||
// Import migration function
|
||||
|
||||
Reference in new issue
Block a user