From 7fc065e10ea84ddfb6d60bd06f7e8bca82f59fd8 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Wed, 13 Aug 2025 22:26:34 -0400 Subject: [PATCH] Install visualization plugins to config/plugins before staging Move npm package installation back from static/plugins to config/plugins to improve security by following the principle of least exposure. With the recent change from 25.0, entire npm packages were installed directly to the web-served static directory, exposing package metadata, source files, and potentially sensitive content to web access. This swaps us back to: - Install npm visualization packages to config/plugins/visualizations/ - Stage only /static subdirectories to the served location - Maintain separation between installation (private) and serving (public) locations This brings back a reduced attack surface by ensuring only intended static assets are web-accessible, while keeping package contents, build artifacts, and metadata in non-served directories. --- client/gulpfile.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/client/gulpfile.js b/client/gulpfile.js index d533d544d89..458273e876e 100644 --- a/client/gulpfile.js +++ b/client/gulpfile.js @@ -63,26 +63,11 @@ function stagePlugins(callback) { // Flatten the glob patterns to actual directory paths const dirs = [...globSync(visualizationDirs)]; - // Get list of installed visualization plugin names to filter out - const installedVisualizationNames = Object.keys(VISUALIZATION_PLUGINS); - // Process each directory const copyPromises = dirs.map((sourceDir) => { // Get the relative path from the plugin base dir const relativeDir = path.relative(PATHS.pluginBaseDir, sourceDir); - // Extract the plugin name from the path (e.g., "visualizations/myvis/static" -> "myvis") - const pathParts = relativeDir.split(path.sep); - const pluginName = pathParts[1]; // visualizations/[pluginName]/static - - // Skip if this is an installed visualization plugin - if (installedVisualizationNames.includes(pluginName)) { - console.log(`Skipping plugin staging for '${pluginName}' (already installed via npm package)`); - return Promise.resolve(); - } else { - console.log(`Staging filesystem plugin '${pluginName}' from ${sourceDir}`); - } - // The target should preserve the full path including 'static' const targetDir = path.join(staticPluginDir, relativeDir); @@ -117,7 +102,7 @@ function stagePlugins(callback) { * Produce plugins from fully self-contained npm packages */ async function installVisualizations(callback, forceReinstall = false) { - const visualizationsDir = path.join(staticPluginDir, "visualizations"); + const visualizationsDir = path.join(PATHS.pluginBaseDir, "visualizations"); fs.ensureDirSync(visualizationsDir); for (const pluginName of Object.keys(VISUALIZATION_PLUGINS)) { const { package: pluginPackage, version } = VISUALIZATION_PLUGINS[pluginName];