Fix 5 critical security vulnerabilities
1. WebSocket exec auth bypass (exec.js): Require valid JWT or API key before accepting WebSocket upgrade. Reject unauthenticated requests with 401 before the upgrade completes. 2. Shell injection in router auto-login (session-handlers.js): Validate baseUrl against safe hostname pattern before embedding in wget shell command. Reject with null session if invalid. 3. Path traversal in credentials routes (services.js): Add explicit serviceId validation (alphanumeric + dash/underscore/dot, max 100 chars) to all three credential endpoints. Removed redundant try/catch wrapper. 4. execSync injection in CA CSR generation (ca.js): Add sanitize step replacing any non-alphanumeric domain chars with underscore before interpolation into shell subj argument. Redundant with existing validation but provides defense-in-depth. 5. Auth bypass when TOTP disabled (middleware.js): Split the logic cleanly — disabled TOTP means no auth (initial setup state), enabled TOTP means all auth methods checked (session/JWT/API key). Removed the sessionDuration:never conflating shortcut.
This commit is contained in:
@@ -180,7 +180,9 @@ module.exports = function(ctx) {
|
||||
if (needsRegeneration) {
|
||||
execSync(`openssl genrsa -out "${keyFile}" 2048`, { stdio: 'pipe' });
|
||||
|
||||
const subject = `/CN=${domain}`;
|
||||
// Sanitize domain for safe use in shell arguments — defensive, since validation already restricts input
|
||||
const safeDomain = domain.replace(/[^a-zA-Z0-9.-]/g, '_');
|
||||
const subject = `/CN=${safeDomain}`;
|
||||
execSync(`openssl req -new -key "${keyFile}" -out "${csrFile}" -subj "${subject}"`, { stdio: 'pipe' });
|
||||
|
||||
const configContent = `[req]
|
||||
@@ -189,7 +191,7 @@ req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
CN = ${domain}
|
||||
CN = ${safeDomain}
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment, digitalSignature
|
||||
@@ -197,8 +199,8 @@ extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = ${domain}
|
||||
${domain.includes('.') ? `DNS.2 = *.${domain}` : ''}`;
|
||||
DNS.1 = ${safeDomain}
|
||||
${safeDomain.includes('.') ? `DNS.2 = *.${safeDomain}` : ''}`;
|
||||
|
||||
const configFile = path.join(domainDir, 'openssl.cnf');
|
||||
await fsp.writeFile(configFile, configContent);
|
||||
|
||||
Reference in New Issue
Block a user