diff --git a/server/monitor-types/real-browser-monitor-type.js b/server/monitor-types/real-browser-monitor-type.js index 0a4f1f719..f3e5695f8 100644 --- a/server/monitor-types/real-browser-monitor-type.js +++ b/server/monitor-types/real-browser-monitor-type.js @@ -7,9 +7,60 @@ const childProcess = require("child_process"); const path = require("path"); const Database = require("../database"); const jwt = require("jsonwebtoken"); +const config = require("../config"); let browser = null; +let allowedList = []; +let lastAutoDetectChromeExecutable = null; + +if (process.platform === "win32") { + allowedList.push(process.env.LOCALAPPDATA + "\\Google\\Chrome\\Application\\chrome.exe"); + allowedList.push(process.env.PROGRAMFILES + "\\Google\\Chrome\\Application\\chrome.exe"); + allowedList.push(process.env["ProgramFiles(x86)"] + "\\Google\\Chrome\\Application\\chrome.exe"); + + // Allow Chromium too + allowedList.push(process.env.LOCALAPPDATA + "\\Chromium\\Application\\chrome.exe"); + allowedList.push(process.env.PROGRAMFILES + "\\Chromium\\Application\\chrome.exe"); + allowedList.push(process.env["ProgramFiles(x86)"] + "\\Chromium\\Application\\chrome.exe"); + + // For Loop A to Z + for (let i = 65; i <= 90; i++) { + let drive = String.fromCharCode(i); + allowedList.push(drive + ":\\Program Files\\Google\\Chrome\\Application\\chrome.exe"); + allowedList.push(drive + ":\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"); + } + +} else if (process.platform === "linux") { + allowedList = [ + "chromium", + "chromium-browser", + "google-chrome", + + "/usr/bin/chromium", + "/usr/bin/chromium-browser", + "/usr/bin/google-chrome", + ]; +} else if (process.platform === "darwin") { + // TODO: Generated by GitHub Copilot, but not sure if it's correct + allowedList = [ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + "/Applications/Chromium.app/Contents/MacOS/Chromium", + ]; +} + +log.debug("chrome", allowedList); + +async function isAllowedChromeExecutable(executablePath) { + console.log(config.args); + if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") { + return true; + } + + // Check if the executablePath is in the list of allowed executables + return allowedList.includes(executablePath); +} + async function getBrowser() { if (!browser) { let executablePath = await Settings.get("chromeExecutable"); @@ -27,6 +78,7 @@ async function getBrowser() { async function prepareChromeExecutable(executablePath) { // Special code for using the playwright_chromium if (typeof executablePath === "string" && executablePath.toLocaleLowerCase() === "#playwright_chromium") { + // Set to undefined = use playwright_chromium executablePath = undefined; } else if (!executablePath) { if (process.env.UPTIME_KUMA_IS_CONTAINER) { @@ -56,30 +108,30 @@ async function prepareChromeExecutable(executablePath) { }); } - } else if (process.platform === "win32") { - executablePath = findChrome([ - "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", - "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", - "D:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", - "D:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", - "E:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", - "E:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", - ]); - } else if (process.platform === "linux") { - executablePath = findChrome([ - "chromium-browser", - "chromium", - "google-chrome", - ]); + } else { + executablePath = findChrome(allowedList); + } + } else { + // User specified a path + // Check if the executablePath is in the list of allowed + if (!await isAllowedChromeExecutable(executablePath)) { + throw new Error("This Chromium executable path is not allowed by default. If you are sure this is safe, please add an environment variable UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC=1 to allow it."); } - // TODO: Mac?? } return executablePath; } function findChrome(executables) { + // Use the last working executable, so we don't have to search for it again + if (lastAutoDetectChromeExecutable) { + if (commandExistsSync(lastAutoDetectChromeExecutable)) { + return lastAutoDetectChromeExecutable; + } + } + for (let executable of executables) { if (commandExistsSync(executable)) { + lastAutoDetectChromeExecutable = executable; return executable; } }