T07 · Tool Hijacking and Spoofing
- Location
scripts/guard_and_run.py:117- Finding
Executable Allowlist Bypass Through PATH Shadowing
- Content
View full analysis
Vulnerability Details
File Location:
scripts/guard_and_run.py:117-150andscripts/guard_and_run.py:633-638
Vulnerability Type: Executable spoofing and allowlist bypass
Risk Level: HighVulnerable 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 FalseThe 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
View remediation
Remediation Suggestions
- Require absolute executable paths in production allowlists.
- Before authorization, resolve the executable with
shutil.which()when a basename is supplied. - Canonicalize the resolved path with
Path.resolve(strict=True)and compare that canonical path against canonical absolute allowlist entries. - Execute the resolved and validated absolute path rather than the original basename.
- Use a fixed, minimal trusted
PATHinstead of preserving the caller-controlled value. - Reject executables located in directories writable by untrusted users or groups.
- Prefer exact path matching over wildcard and regex rules. If patterns remain supported, apply them only to canonical absolute paths.
- Where feasible, verify executable ownership, permissions, and an expected file digest before execution.
- 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.
