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.
This commit is contained in:
Karsten Hassel
2026-02-08 16:18:56 +01:00
committed by GitHub
parent 172ca18178
commit 1dc3032171
3 changed files with 37 additions and 5 deletions

View File

@@ -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);

View File

@@ -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 };

View File

@@ -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;