T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/version_tool.py:148
- Finding
- Cross-Workspace Snapshot Disclosure, Restoration, and Deletion## Vulnerability Details **File Location**: `scripts/version_tool.py:23-27, 148-162, 393, 467, 547, 652`; documented in `SKILL.md:144` **Vulnerability Type**: Missing workspace authorization and isolation **Risk Level**: High ### Vulnerable 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 None ``` The 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 workspaces ``` ### Technical 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
- ## Remediation Suggestions 1. Remove implicit cross-workspace fallback from `_find_file_key_by_rel_path()`. Only return a key that belongs to the active workspace. 2. Partition storage and indexes by a stable workspace identifier rather than maintaining one unrestricted global namespace. 3. Store a canonical workspace identifier in every index entry and snapshot file. Verify it before listing, loading, restoring, diffing, or deleting a snapshot. 4. 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. 5. During restoration, validate both the destination workspace path and source snapshot ownership. 6. During cleanup, reject records whose workspace identifier does not exactly match the active workspace. 7. Add regression tests covering identical relative paths in separate workspaces and verify that all read and destructive operations remain isolated.
