From 1dc3032171364447dad2f2316de6362fc48ffd77 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 8 Feb 2026 16:18:56 +0100 Subject: [PATCH] allow environment variables in cors urls (#4033) and centralize and optimize replace regex. Another follow up to #4029 With this PR you can use secrets in urls in browser modules if you use the cors proxy. --- js/node_helper.js | 5 ++--- js/server_functions.js | 18 +++++++++++++++++- tests/unit/functions/server_functions_spec.js | 19 ++++++++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/js/node_helper.js b/js/node_helper.js index 952db968..89106999 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -1,6 +1,7 @@ const express = require("express"); const Log = require("logger"); const Class = require("./class"); +const { replaceSecretPlaceholder } = require("#server_functions"); const NodeHelper = Class.extend({ init () { @@ -90,9 +91,7 @@ const NodeHelper = Class.extend({ socket.onAny((notification, payload) => { if (config.hideConfigSecrets && payload && typeof payload === "object") { try { - const payloadStr = JSON.stringify(payload).replaceAll(/\*\*(SECRET_.*)\*\*/g, (match, group) => { - return process.env[group]; - }); + const payloadStr = replaceSecretPlaceholder(JSON.stringify(payload)); this.socketNotificationReceived(notification, JSON.parse(payloadStr)); } catch (e) { Log.error("Error substituting variables in payload: ", e); diff --git a/js/server_functions.js b/js/server_functions.js index a2f0ea05..063e9cfe 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -13,6 +13,17 @@ function getStartup (req, res) { res.send(startUp); } +/** + * A method that replaces the secret placeholders `**SECRET_ABC**` with the environment variable SECRET_ABC + * @param {string} input - the input string + * @returns {string} the input with real variable content + */ +function replaceSecretPlaceholder (input) { + return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => { + return process.env[group]; + }); +} + /** * A method that forwards HTTP Get-methods to the internet to avoid CORS-errors. * @@ -35,6 +46,11 @@ async function cors (req, res) { return res.status(400).send(url); } else { url = match[1]; + if (typeof config !== "undefined") { + if (config.hideConfigSecrets) { + url = replaceSecretPlaceholder(url); + } + } const headersToSend = getHeadersToSend(req.url); const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url); @@ -186,4 +202,4 @@ function getConfigFilePath () { return path.resolve(global.configuration_file || `${global.root_path}/config/config.js`); } -module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath }; +module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder }; diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 75965773..c0953d48 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,6 +1,23 @@ -const { cors, getUserAgent } = require("#server_functions"); +const { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions"); describe("server_functions tests", () => { + describe("The replaceSecretPlaceholder method", () => { + it("Calls string without secret placeholder", () => { + const teststring = "test string without secret placeholder"; + const result = replaceSecretPlaceholder(teststring); + expect(result).toBe(teststring); + }); + + it("Calls string with 2 secret placeholders", () => { + const teststring = "test string with secret1=**SECRET_ONE** and secret2=**SECRET_TWO**"; + process.env.SECRET_ONE = "secret1"; + process.env.SECRET_TWO = "secret2"; + const resultstring = `test string with secret1=${process.env.SECRET_ONE} and secret2=${process.env.SECRET_TWO}`; + const result = replaceSecretPlaceholder(teststring); + expect(result).toBe(resultstring); + }); + }); + describe("The cors method", () => { let fetchResponse; let fetchResponseHeadersGet;