From 5c92a44e65f18108a6d0ab0dd35af2b1e69f6c45 Mon Sep 17 00:00:00 2001 From: bbassie <17990055+bbassie@users.noreply.github.com> Date: Tue, 27 Oct 2026 23:01:12 +0000 Subject: [PATCH] Limit the development server to sources and dependencies Vite serves any file under fs.allow through /@fs/, and the default allow list is the workspace root. In a clusterio checkout that is also the usual data directory, so with --dev any client that could reach the controller could fetch config-controller.json, config-ctl.json and the database without logging in. webpack-dev-middleware only served the compiled bundles. Allow the controller, web_ui, lib and dev plugin directories and the node_modules directories Node.js would resolve their imports from. Co-Authored-By: Claude Opus 5.5 --- packages/controller/src/Controller.ts | 1 - packages/web_ui/vite.mjs | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/controller/src/Controller.ts b/packages/controller/src/Controller.ts index bee2f319..ff048d3b 100644 --- a/packages/controller/src/Controller.ts +++ b/packages/controller/src/Controller.ts @@ -524,7 +524,6 @@ export default class Controller { server: { middlewareMode: true, preTransformRequests: false, - fs: { allow: [vite.searchForWorkspaceRoot(controllerDir), ...pluginDirs.values()] }, }, plugins: [webUiVite.clusterioDevPlugins(pluginDirs)], }); diff --git a/packages/web_ui/vite.mjs b/packages/web_ui/vite.mjs index 48f0bd2a..0c7b6a6e 100644 --- a/packages/web_ui/vite.mjs +++ b/packages/web_ui/vite.mjs @@ -47,6 +47,7 @@ const polyfills = { zlib: "browserify-zlib", }; const webUiPackage = fileURLToPath(new URL("./package.json", import.meta.url)); +const libPackage = createRequire(webUiPackage).resolve("@clusterio/lib/package.json"); const sharedPrefix = "\0clusterio:shared/"; const pluginPrefix = "\0clusterio:plugin/"; @@ -83,6 +84,19 @@ async function findFile(dir, candidates) { return undefined; } +// node_modules directories Node.js would search for packages imported from dir. +function nodeModulesDirs(dir) { + const dirs = []; + for (let current = dir; ; current = path.dirname(current)) { + if (path.basename(current) !== "node_modules") { + dirs.push(path.join(current, "node_modules")); + } + if (current === path.dirname(current)) { + return dirs; + } + } +} + function chunkName(name) { return name.replace(/^@/, "").replace(/[/]/g, "_"); } @@ -292,8 +306,14 @@ export function clusterioApp({ entry }) { export function clusterioDevPlugins(pluginDirs) { return { name: "clusterio:dev-plugins", - config() { + config(config) { + const root = path.resolve(config.root ?? process.cwd()); + const sources = [root, path.dirname(webUiPackage), path.dirname(libPackage), ...pluginDirs.values()]; return { + server: { + // Vite's default is the workspace root, which may be the data directory. + fs: { allow: [...sources, ...sources.flatMap(nodeModulesDirs)] }, + }, optimizeDeps: { entries: [...pluginDirs.values()].flatMap( dir => [`${dir}/index.{ts,js}`, `${dir}/web/**/*.{ts,tsx,js,jsx}`]