Skip to content

Commit a2f03ce

Browse files
committed
fix: lexical symlink containment, assert project_root consistency
- uninstall() now uses os.path.normpath for lexical containment check instead of resolve(), so in-project symlinks pointing outside are still properly removed - setup() asserts manifest.project_root matches the passed project_root to prevent path mismatches between file operations and manifest recording
1 parent 7ccbf69 commit a2f03ce

2 files changed

Lines changed: 10 additions & 3 deletions

File tree

src/specify_cli/integrations/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ def setup(
120120
return created
121121

122122
project_root_resolved = project_root.resolve()
123+
if manifest.project_root != project_root_resolved:
124+
raise ValueError(
125+
f"manifest.project_root ({manifest.project_root}) does not match "
126+
f"project_root ({project_root_resolved})"
127+
)
123128
subdir = self.config.get("commands_subdir", "commands")
124129
dest = (project_root / folder / subdir).resolve()
125130
# Ensure destination stays within the project root

src/specify_cli/integrations/manifest.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import hashlib
1212
import json
13+
import os
1314
from datetime import datetime, timezone
1415
from pathlib import Path
1516
from typing import Any
@@ -147,10 +148,11 @@ def uninstall(
147148
# Use non-resolved path for deletion so symlinks themselves
148149
# are removed, not their targets.
149150
path = root / rel
150-
# Validate containment via the resolved path
151+
# Validate containment lexically (without following symlinks)
152+
# by collapsing .. segments via Path resolution on the string parts.
151153
try:
152-
resolved = path.resolve()
153-
resolved.relative_to(root)
154+
normed = Path(os.path.normpath(path))
155+
normed.relative_to(root)
154156
except (ValueError, OSError):
155157
continue
156158
if not path.exists():

0 commit comments

Comments
 (0)