T07 · Tool Hijacking and Spoofing
Error
- Location
- scripts/guard_and_run.py:117
- Finding
- Executable Allowlist Bypass Through PATH Shadowing## Vulnerability Details **File Location**: `scripts/guard_and_run.py:117-150` and `scripts/guard_and_run.py:633-638` **Vulnerability Type**: Executable spoofing and allowlist bypass **Risk Level**: High ### Vulnerable Code ```python def _is_allowed(command: list[str], allowed: list[str]) -> bool: if not allowed: return True target = command[0] target_name = Path(target).name target_lower = target.lower() target_name_lower = target_name.lower() for pattern in allowed: if not pattern: continue pattern = pattern.strip() if not pattern: continue candidate = pattern.lower() if candidate.startswith("regex:"): expr = candidate.split(":", 1)[1] try: if re.fullmatch(expr, target_lower): return True except re.error as exc: raise RuntimeError(f"Invalid regex allowlist pattern '{pattern}': {exc}") from exc continue if fnmatch.fnmatch(target_lower, candidate) or fnmatch.fnmatch(target_name_lower, candidate): return True if Path(pattern).is_absolute(): try: if Path(target).resolve() == Path(pattern).resolve(): return True except OSError: if target_lower == pattern.lower(): return True elif target_lower == pattern.lower() or target_name_lower == pattern.lower(): return True return False ``` The validated command is subsequently executed as follows: ```python env = None if args.sanitize_env: env = _sanitize_env(args.keep_env, args.keep_env_prefix) try: proc = subprocess.run(command, check=False, env=env, timeout=args.command_timeout) ``` ### Technical Analysis The command allowlist can authorize an executable solely ...[truncated 2289 chars]
- Remediation
- ## Remediation Suggestions 1. Require absolute executable paths in production allowlists. 2. Before authorization, resolve the executable with `shutil.which()` when a basename is supplied. 3. Canonicalize the resolved path with `Path.resolve(strict=True)` and compare that canonical path against canonical absolute allowlist entries. 4. Execute the resolved and validated absolute path rather than the original basename. 5. Use a fixed, minimal trusted `PATH` instead of preserving the caller-controlled value. 6. Reject executables located in directories writable by untrusted users or groups. 7. Prefer exact path matching over wildcard and regex rules. If patterns remain supported, apply them only to canonical absolute paths. 8. Where feasible, verify executable ownership, permissions, and an expected file digest before execution. 9. Add regression tests that create a fake allowed executable in a temporary directory, prepend that directory to `PATH`, and confirm that the wrapper rejects it.
