fix(plugins): harden path traversal and respect enabled state

Use realpathSync to canonicalize paths before the plugin asset
boundary check, preventing symlink-based traversal bypasses that
could escape the plugin directory.

PluginTabContent now guards on plugin.enabled before mounting the
plugin module, and re-mounts when the enabled state changes so
toggling a plugin takes effect without a page reload.

PluginIcon safely handles a missing iconFile prop and skips
processing non-OK fetch responses instead of attempting to parse
error bodies as SVG.

Register 'plugins' as a known main tab so the settings router
preserves the tab on navigation.
This commit is contained in:
simosmik
2026-03-09 06:49:51 +00:00
parent a7e8b12ef4
commit efdee162c9
9 changed files with 29 additions and 18 deletions

View File

@@ -143,14 +143,16 @@ export function resolvePluginAssetPath(name, assetPath) {
const resolved = path.resolve(pluginDir, assetPath);
// Prevent path traversal — resolved path must be within plugin directory
if (!resolved.startsWith(pluginDir + path.sep) && resolved !== pluginDir) {
// Prevent path traversal — canonicalize via realpath to defeat symlink bypasses
if (!fs.existsSync(resolved)) return null;
const realResolved = fs.realpathSync(resolved);
const realPluginDir = fs.realpathSync(pluginDir);
if (!realResolved.startsWith(realPluginDir + path.sep) && realResolved !== realPluginDir) {
return null;
}
if (!fs.existsSync(resolved)) return null;
return resolved;
return realResolved;
}
export function installPluginFromGit(url) {