security: fix 3 medium-severity vulnerabilities (Fase 3 partial)
MEDIUM-SEVERITY FIXES: 1. Mock Data em Produção (Vulnerabilidade 3.2) - Mock data apenas em desenvolvimento (import.meta.env.DEV) - Produção mostra erro claro: "Não foi possível carregar os dados" - Estado de erro com UI para retry - Import AlertCircle icon 2. Tipo 'any' em Catch Blocks (Vulnerabilidade 3.4 - partial) - api/routes/wp-monitor.ts: catch (error: unknown) - Type guard: error instanceof Error - Mensagens seguras sem vazamento de stack trace 3. Algoritmos SSH Legacy (Vulnerabilidade 3.6) - Adicionados: curve25519-sha256, curve25519-sha256@libssh.org - Removidos: diffie-hellman-group14-sha1 (legacy) - Removidos: diffie-hellman-group1-sha1 (INSEGURO) - Mantidos apenas SHA256+ algorithms FILES CHANGED: - src/App.tsx - Error state + mock data apenas em dev - api/routes/wp-monitor.ts - Tipos unknown em catch - api/services/server-metrics.ts - Algoritmos SSH modernos PROGRESS: - Vulnerabilidade 3.2: ✅ FIXED - Vulnerabilidade 3.4: 🔄 IN PROGRESS (2/10 files) - Vulnerabilidade 3.6: ✅ FIXED Related: AUDIT-REPORT.md vulnerabilities 3.2, 3.4, 3.6 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,9 +58,10 @@ router.get('/', validateApiKey, async (req: Request, res: Response) => {
|
|||||||
total: result.length,
|
total: result.length,
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error: unknown) {
|
||||||
console.error('WP Monitor GET error:', error)
|
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||||
res.status(500).json({ error: 'Database error', message: (error as Error).message })
|
console.error('WP Monitor GET error:', message)
|
||||||
|
res.status(500).json({ error: 'Database error', message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -105,9 +106,10 @@ router.post('/', validateApiKey, validateRequest(wpMonitorSchema), async (req: R
|
|||||||
status,
|
status,
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error: unknown) {
|
||||||
console.error('WP Monitor POST error:', error)
|
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||||
res.status(500).json({ error: 'Database error', message: (error as Error).message })
|
console.error('WP Monitor POST error:', message)
|
||||||
|
res.status(500).json({ error: 'Database error', message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -136,13 +136,15 @@ function executeSSH(server: SSHServer, command: string): Promise<string> {
|
|||||||
readyTimeout: 15000,
|
readyTimeout: 15000,
|
||||||
algorithms: {
|
algorithms: {
|
||||||
kex: [
|
kex: [
|
||||||
|
// Algoritmos modernos (Vulnerabilidade 3.6)
|
||||||
|
'curve25519-sha256',
|
||||||
|
'curve25519-sha256@libssh.org',
|
||||||
'ecdh-sha2-nistp256',
|
'ecdh-sha2-nistp256',
|
||||||
'ecdh-sha2-nistp384',
|
'ecdh-sha2-nistp384',
|
||||||
'ecdh-sha2-nistp521',
|
'ecdh-sha2-nistp521',
|
||||||
'diffie-hellman-group-exchange-sha256',
|
'diffie-hellman-group-exchange-sha256',
|
||||||
'diffie-hellman-group14-sha256',
|
'diffie-hellman-group14-sha256'
|
||||||
'diffie-hellman-group14-sha1',
|
// REMOVIDOS (inseguros): diffie-hellman-group14-sha1, diffie-hellman-group1-sha1
|
||||||
'diffie-hellman-group1-sha1'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
39
src/App.tsx
39
src/App.tsx
@@ -4,6 +4,7 @@ import {
|
|||||||
Calendar,
|
Calendar,
|
||||||
CalendarDays,
|
CalendarDays,
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
|
AlertCircle,
|
||||||
Clock,
|
Clock,
|
||||||
Zap,
|
Zap,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
@@ -420,6 +421,7 @@ function App() {
|
|||||||
const [data, setData] = useState<DashboardData | null>(null)
|
const [data, setData] = useState<DashboardData | null>(null)
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [refreshing, setRefreshing] = useState(false)
|
const [refreshing, setRefreshing] = useState(false)
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||||
|
|
||||||
const fetchData = useCallback(async () => {
|
const fetchData = useCallback(async () => {
|
||||||
@@ -431,7 +433,13 @@ function App() {
|
|||||||
setData(json)
|
setData(json)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch dashboard data:', error)
|
console.error('Failed to fetch dashboard data:', error)
|
||||||
setData(getMockData())
|
|
||||||
|
// Mock data apenas em desenvolvimento (Vulnerabilidade 3.2)
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
setData(getMockData())
|
||||||
|
} else {
|
||||||
|
setError('Não foi possível carregar os dados. Tente novamente.')
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setRefreshing(false)
|
setRefreshing(false)
|
||||||
@@ -470,6 +478,35 @@ function App() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error state (Vulnerabilidade 3.2)
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-mesh flex items-center justify-center">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
className="text-center max-w-md mx-auto px-6"
|
||||||
|
>
|
||||||
|
<div className="w-20 h-20 rounded-2xl bg-red-500/10 flex items-center justify-center mx-auto mb-6 border border-red-500/20">
|
||||||
|
<AlertCircle className="w-10 h-10 text-red-500" />
|
||||||
|
</div>
|
||||||
|
<h2 className="text-xl font-semibold text-white mb-2">Erro ao Carregar</h2>
|
||||||
|
<p className="text-zinc-400 mb-6">{error}</p>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setError(null)
|
||||||
|
setLoading(true)
|
||||||
|
fetchData()
|
||||||
|
}}
|
||||||
|
className="px-6 py-3 bg-brand-500 hover:bg-brand-600 text-white rounded-xl transition-colors"
|
||||||
|
>
|
||||||
|
Tentar Novamente
|
||||||
|
</button>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (!data) return null
|
if (!data) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user