T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/version_tool.py:148- Finding
Cross-Workspace Snapshot Disclosure, Restoration, and Deletion
- Content
View full analysis
Vulnerability Details
File Location:
scripts/version_tool.py:23-27, 148-162, 393, 467, 547, 652; documented inSKILL.md:144
Vulnerability Type: Missing workspace authorization and isolation
Risk Level: HighVulnerable Code
python def __init__(self, workspace_path: Optional[str] = None): self.workspace_path = Path(workspace_path or os.getcwd()).resolve() self.storage_path = Path.home() / ".workbuddy" / "versions" / "version-master" self.storage_path.mkdir(parents=True, exist_ok=True) # Global index file self.index_file = self.storage_path / "index.json" self._load_index()python def _find_file_key_by_rel_path(self, rel_path: str) -> Optional[str]: """Find file_key by rel_path, including cross-workspace matching.""" current_key = self._file_key(rel_path) if current_key in self.index.get("files", {}): return current_key # Search every workspace by relative path normalized = rel_path.replace("\\", "/") for key, data in self.index.get("files", {}).items(): if data.get("rel_path", "").replace("\\", "/") == normalized: return key return NoneThe unsafe lookup is used by security-sensitive operations:
python # Listing file_key = self._find_file_key_by_rel_path(rel_path) # Restoration file_key = self._find_file_key_by_rel_path(file_path) # Diffing file_key = self._find_file_key_by_rel_path(file_path) # Deletion file_key = self._find_file_key_by_rel_path(file_path)The behavior is also explicitly documented in
SKILL.md:markdown - All workspaces share the same storage directory, version snapshots are accessible across workspacesTechnical Analysis
Every workspace uses the same storage directory and global index. When the current workspace has no exact key for a requested relative path,
_find_file_key_by_rel_path()searches all indexed wo ...[truncated 2149 chars]- Remediation
View remediation
Remediation Suggestions
- Remove implicit cross-workspace fallback from
_find_file_key_by_rel_path(). Only return a key that belongs to the active workspace. - Partition storage and indexes by a stable workspace identifier rather than maintaining one unrestricted global namespace.
- Store a canonical workspace identifier in every index entry and snapshot file. Verify it before listing, loading, restoring, diffing, or deleting a snapshot.
- If cross-workspace sharing is required, implement an explicit import/export or sharing mechanism with clear authorization and user confirmation. Do not infer authorization from a matching relative path.
- During restoration, validate both the destination workspace path and source snapshot ownership.
- During cleanup, reject records whose workspace identifier does not exactly match the active workspace.
- Add regression tests covering identical relative paths in separate workspaces and verify that all read and destructive operations remain isolated.
- Remove implicit cross-workspace fallback from
