T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/bastion.py:1218
- Finding
- Workspace confinement bypass permits moving arbitrary accessible files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/bastion.py:1218-1254` **Vulnerability Type**: Unrestricted path handling and unauthorized file relocation **Risk Level**: High ### Technical Analysis The `quarantine` command accepts an absolute path without requiring it to be located under the configured workspace. Failure of `relative_to(workspace)` merely changes the displayed name; it does not reject the path. The command also moves the target even when the scanner finds no injection patterns. Therefore, any regular file accessible to the Bastion process can be removed from its original location and moved into the workspace quarantine directory. ```python def cmd_quarantine(workspace: Path, filepath: str): """ Move a file with injection patterns to .quarantine/bastion/ with evidence metadata. """ target_path = Path(filepath) if not target_path.is_absolute(): target_path = workspace / target_path if not target_path.is_file(): print(f"ERROR: File not found: {filepath}", file=sys.stderr) return 2 try: rel = target_path.relative_to(workspace).as_posix() except ValueError: rel = target_path.name # Scan for evidence findings = scan_file(target_path, rel) risk = compute_file_risk(findings) # Prepare quarantine destination q_dir = ensure_quarantine_dir(workspace) safe_name = rel.replace("/", "__").replace("\\", "__") q_file = q_dir / safe_name q_meta = q_dir / (safe_name + ".meta.json") # Handle name collision counter = 1 while q_file.exists(): q_file = q_dir / f"{safe_name}.{counter}" q_meta = q_dir / f"{safe_name}.{counter}.meta.json" counter += 1 # Move the file shutil.move(str(target_path), str(q_file)) ``` This violates least privilege for a workspace content scanner. The same unrestricted absolute-target pattern is also present in `cmd_block`, while `collect_scannable_files` permits expli ...[truncated 1165 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Resolve both paths before use and require the target to remain within the resolved workspace: ```python workspace_real = workspace.resolve(strict=True) target_real = target_path.resolve(strict=True) try: target_real.relative_to(workspace_real) except ValueError: raise ValueError("Target must be inside the configured workspace") ``` - Reject symlinks or verify their resolved destinations before reading or modifying them. - Apply the same confinement helper to `block`, `sanitize`, `quarantine`, `canary`, `check`, and explicit scan targets. - Refuse quarantine unless findings contain at least one eligible critical pattern. - Require explicit confirmation before moving files, with a separate `--force` option for automation. - Run modifying operations under a restricted account with access limited to the workspace. - Add regression tests for absolute paths, `..` traversal, symlink escapes, and clean files. ]]>
