fix(plugins): reject plugin names that resolve to the plugins root
Reject "." as a plugin name — it resolves to the plugins directory itself, which in force-install flows causes shutil.rmtree to wipe the entire plugins tree. - reject "." early with a clear error message - explicit check for target == plugins_resolved (raise instead of allow) - switch boundary check from string-prefix to Path.relative_to() - add regression tests for sanitizer + install flow Co-authored-by: Dusk1e <yusufalweshdemir@gmail.com>
This commit is contained in:
@@ -41,6 +41,11 @@ def _sanitize_plugin_name(name: str, plugins_dir: Path) -> Path:
|
||||
if not name:
|
||||
raise ValueError("Plugin name must not be empty.")
|
||||
|
||||
if name in (".", ".."):
|
||||
raise ValueError(
|
||||
f"Invalid plugin name '{name}': must not reference the plugins directory itself."
|
||||
)
|
||||
|
||||
# Reject obvious traversal characters
|
||||
for bad in ("/", "\\", ".."):
|
||||
if bad in name:
|
||||
@@ -49,10 +54,14 @@ def _sanitize_plugin_name(name: str, plugins_dir: Path) -> Path:
|
||||
target = (plugins_dir / name).resolve()
|
||||
plugins_resolved = plugins_dir.resolve()
|
||||
|
||||
if (
|
||||
not str(target).startswith(str(plugins_resolved) + os.sep)
|
||||
and target != plugins_resolved
|
||||
):
|
||||
if target == plugins_resolved:
|
||||
raise ValueError(
|
||||
f"Invalid plugin name '{name}': resolves to the plugins directory itself."
|
||||
)
|
||||
|
||||
try:
|
||||
target.relative_to(plugins_resolved)
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
f"Invalid plugin name '{name}': resolves outside the plugins directory."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user