From a45d7704abb7f5141db27d75a14cdc29046dcf12 Mon Sep 17 00:00:00 2001 From: OpenClaw Deployer Date: Wed, 18 Feb 2026 13:33:26 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20relax=20CSP=20for=20/docs=20page=20?= =?UTF-8?q?=E2=80=94=20allow=20unsafe-eval=20for=20Swagger=20UI=205.x=20(a?= =?UTF-8?q?jv)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swagger UI 5.x uses new Function() via ajv for JSON schema validation. Helmet default CSP (script-src self) blocks this in Firefox, causing TypeError: NetworkError when attempting to fetch resource on Try It. Override CSP on /docs route to allow unsafe-eval. --- dist/index.js | 3 +++ dist/services/email.js | 22 ++++++++++++++++------ src/index.ts | 5 +++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3a92255..e20ad0f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -182,6 +182,9 @@ app.use(express.static(path.join(__dirname, "../public"), { })); // Docs page (clean URL) app.get("/docs", (_req, res) => { + // Swagger UI 5.x uses new Function() (via ajv) for JSON schema validation. + // Override helmet's default CSP to allow 'unsafe-eval' + blob: for Swagger UI. + res.setHeader("Content-Security-Policy", "default-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' https: 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' https: data:;connect-src 'self';worker-src 'self' blob:;base-uri 'self';form-action 'self';frame-ancestors 'self';object-src 'none'"); res.setHeader('Cache-Control', 'public, max-age=86400'); res.sendFile(path.join(__dirname, "../public/docs.html")); }); diff --git a/dist/services/email.js b/dist/services/email.js index d7efdf2..ce66697 100644 --- a/dist/services/email.js +++ b/dist/services/email.js @@ -1,18 +1,28 @@ import nodemailer from "nodemailer"; import logger from "./logger.js"; -const transporter = nodemailer.createTransport({ - host: process.env.SMTP_HOST || "host.docker.internal", - port: Number(process.env.SMTP_PORT || 25), - secure: false, +const smtpUser = process.env.SMTP_USER; +const smtpPass = process.env.SMTP_PASS; +const smtpHost = process.env.SMTP_HOST || "host.docker.internal"; +const smtpPort = Number(process.env.SMTP_PORT || 25); +const smtpFrom = process.env.SMTP_FROM || "DocFast "; +const smtpSecure = smtpPort === 465; +const transportConfig = { + host: smtpHost, + port: smtpPort, + secure: smtpSecure, connectionTimeout: 5000, greetingTimeout: 5000, socketTimeout: 10000, tls: { rejectUnauthorized: false }, -}); +}; +if (smtpUser && smtpPass) { + transportConfig.auth = { user: smtpUser, pass: smtpPass }; +} +const transporter = nodemailer.createTransport(transportConfig); export async function sendVerificationEmail(email, code) { try { const info = await transporter.sendMail({ - from: "DocFast ", + from: smtpFrom, to: email, subject: "DocFast - Verify your email", text: `Your DocFast verification code is: ${code}\n\nThis code expires in 15 minutes.\n\nIf you didn't request this, ignore this email.`, diff --git a/src/index.ts b/src/index.ts index fd75976..6a401a4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -199,6 +199,11 @@ app.use(express.static(path.join(__dirname, "../public"), { // Docs page (clean URL) app.get("/docs", (_req, res) => { + // Swagger UI 5.x uses new Function() (via ajv) for JSON schema validation. + // Override helmet's default CSP to allow 'unsafe-eval' + blob: for Swagger UI. + res.setHeader("Content-Security-Policy", + "default-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' https: 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' https: data:;connect-src 'self';worker-src 'self' blob:;base-uri 'self';form-action 'self';frame-ancestors 'self';object-src 'none'" + ); res.setHeader('Cache-Control', 'public, max-age=86400'); res.sendFile(path.join(__dirname, "../public/docs.html")); });