Files
BetterDesk/web-nodejs/middleware/security.js
T
UNITRONIX f239f791fd Enhance diagnostics, API checks, TOTP updates
betterdesk.sh: Improve diagnostics and DB visibility by detecting DB type (SQLite vs PostgreSQL), masking passwords in DATABASE_URL, and reporting PostgreSQL counts via psql when available. Add clearer messages when SQLite file is missing and list DB type in diagnostics. Detect Go server TLS via systemd service args, switch API health checks to /api/health, default API port to 21114, and warn about TLS/HTTP mismatches between server and console. Also update service identifier strings in port definitions.

web-nodejs/middleware/security.js: Add browsing-topics to Permissions-Policy header to suppress Chrome warnings.

web-nodejs/routes/auth.routes.js: Fix async handling by awaiting authService methods (verifyRecoveryCode, verifyTotpCode, isTotpEnabled, verifyAndEnableTotp, disableTotp) and replace direct bcrypt compare with authService.verifyPassword to support multiple hash schemes. Make TOTP status endpoint async with error handling.

Overall: adds better runtime diagnostics, TLS mismatch detection, and fixes asynchronous/auth verification bugs.
Co-Authored-By: MrBrodacz - Design <215021251+MrBrodacz2025@users.noreply.github.com>
Co-Authored-By: boruto79 <176351662+boruto79@users.noreply.github.com>
2026-03-05 01:22:40 +01:00

80 lines
2.6 KiB
JavaScript

/**
* BetterDesk Console - Security Middleware
* Configures Helmet and custom security headers
*/
const helmet = require('helmet');
const config = require('../config/config');
/**
* Build CSP connect-src based on HTTPS mode
* When HTTPS is enabled, also allow wss:// for future WebSocket connections
*/
const connectSources = config.httpsEnabled
? ["'self'", "wss:"]
: ["'self'"];
/**
* Configure Helmet with appropriate CSP for our app
* Security policies adjust automatically based on HTTPS mode
*/
const helmetMiddleware = helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"], // unsafe-eval required by protobuf.js codegen
scriptSrcAttr: ["'unsafe-inline'"], // Allow inline event handlers (onclick etc.)
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
imgSrc: ["'self'", "data:", "blob:"],
mediaSrc: ["'self'", "blob:"], // blob: required by JMuxer MSE video decoding
connectSrc: connectSources,
frameSrc: ["'none'"],
objectSrc: ["'none'"],
baseUri: ["'self'"],
formAction: ["'self'"],
upgradeInsecureRequests: config.httpsEnabled ? [] : null
}
},
crossOriginEmbedderPolicy: false,
crossOriginResourcePolicy: false,
crossOriginOpenerPolicy: config.httpsEnabled ? { policy: 'same-origin' } : false,
originAgentCluster: config.httpsEnabled,
strictTransportSecurity: config.httpsEnabled
? { maxAge: 31536000, includeSubDomains: true, preload: false }
: false
});
/**
* Custom security headers
*/
function customSecurityHeaders(req, res, next) {
// Prevent clickjacking
res.setHeader('X-Frame-Options', 'DENY');
// Prevent MIME type sniffing
res.setHeader('X-Content-Type-Options', 'nosniff');
// XSS Protection (disabled for modern browsers, can cause issues in legacy)
res.setHeader('X-XSS-Protection', '0');
// Referrer policy
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
// Permissions policy (includes browsing-topics to suppress Chrome warnings)
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=(), browsing-topics=()');
next();
}
/**
* Combined security middleware
*/
function securityMiddleware(req, res, next) {
helmetMiddleware(req, res, () => {
customSecurityHeaders(req, res, next);
});
}
module.exports = securityMiddleware;