SECURITY: Eliminate complex fallback storage, enforce environment variables

Core changes:
- Remove file/database fallback storage complexity
- Enforce JWT_SECRET and DATABASE_KEY as environment variables only
- Auto-generate keys on first startup with clear user guidance
- Eliminate circular dependencies and storage layer abstractions

Security improvements:
- Single source of truth for secrets (environment variables)
- No persistent storage of secrets in files or database
- Clear deployment guidance for production environments
- Simplified attack surface by removing storage complexity

WebSocket authentication:
- Implement JWT authentication for WebSocket handshake
- Add connection limits and user tracking
- Update frontend to pass JWT tokens in WebSocket URLs
- Configure Nginx for authenticated WebSocket proxy

Additional fixes:
- Replace CORS wildcard with specific origins
- Remove password logging security vulnerability
- Streamline encryption architecture following Linus principles
This commit is contained in:
ZacharyZcR
2025-09-22 08:57:37 +08:00
parent ed11b309f4
commit dfc92428e0
6 changed files with 316 additions and 315 deletions

View File

@@ -213,7 +213,15 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
window.location.port === "5173" ||
window.location.port === "");
const wsUrl = isDev
// Get JWT token for WebSocket authentication
const jwtToken = localStorage.getItem("jwt");
if (!jwtToken) {
console.error("No JWT token available for WebSocket connection");
setConnectionStatus("disconnected");
return;
}
const baseWsUrl = isDev
? "ws://localhost:8082"
: isElectron()
? (() => {
@@ -227,6 +235,9 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
})()
: `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/ssh/websocket/`;
// Add JWT token as query parameter for authentication
const wsUrl = `${baseWsUrl}?token=${encodeURIComponent(jwtToken)}`;
const ws = new WebSocket(wsUrl);
webSocketRef.current = ws;
wasDisconnectedBySSH.current = false;
@@ -351,6 +362,24 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
if (terminal) {
terminal.clear();
}
// Handle authentication errors (code 1008)
if (event.code === 1008) {
console.error("WebSocket authentication failed:", event.reason);
setConnectionError("Authentication failed - please re-login");
setIsConnecting(false);
shouldNotReconnectRef.current = true;
// Clear invalid JWT token
localStorage.removeItem("jwt");
// Show authentication error message
toast.error("Authentication failed. Please log in again.");
// Don't attempt to reconnect on auth failure
return;
}
setIsConnecting(true);
if (
!wasDisconnectedBySSH.current &&