Files
BetterDesk/web-nodejs/middleware/security.js
T
UNITRONIX a957f3fe2a Add CDAP gateway & redesign devices UI
Introduce full CDAP subsystem and devices UI overhaul. Adds a new CDAP WebSocket gateway (cdap/gateway.go) with auth, connection lifecycle, message loop, heartbeat monitor and APIs (cdap/api.go, cdap/auth.go, cdap/handler.go, cdap/manifest.go, cdap/messages.go). Wire CDAP into the server (api/server.go + handlers in api/cdap_handlers.go) exposing REST endpoints for status, device list, info, manifest, state and sending commands. Enhance peer handling: CDAP-connected overlay in peer list/get, device revocation/cascade support in handleDeletePeer (blocklist, connection teardown, events + audit), and new audit action ActionPeerRevoked. Frontend updates include CDAP device page, widgets, commands, styles and services; major devices page UI redesign (responsive folder chips, toolbar, slim table, kebab menu) plus related CSS/JS/views, translations, docs and assets. Overall adds CDAP features, revocation workflow, and a responsive devices UI.
2026-03-20 02:01:48 +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: ["'self'"],
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;