fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide

AST-driven pass over every subprocess.run/Popen/check_output/check_call/call
with text=True (or universal_newlines=True) and no explicit encoding=:
append encoding='utf-8', errors='replace' at the kwarg site. 136 call
sites across 28 files (cli.py, hermes_cli/main.py, tools_config.py,
environments, computer_use, gateway, scripts, skills helpers, agent/*).

Together with the salvaged #55339/#60741 commits this closes out issue
#53428's bug class; the salvaged #60751 linter rule in
check-windows-footguns.py now enforces it repo-wide (verified: 807 files
scanned, zero findings).
This commit is contained in:
teknium1 2026-07-24 10:05:18 -07:00 committed by Teknium
parent 051217342b
commit d4b867cf9f
28 changed files with 138 additions and 136 deletions

View file

@ -267,7 +267,7 @@ def _install_npm(
[npm, "install", "--prefix", str(staging), "--silent", "--no-fund", "--no-audit", *install_targets],
check=False,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=300,
stdin=subprocess.DEVNULL,
creationflags=windows_hide_flags(),
@ -316,7 +316,7 @@ def _install_go(pkg: str, bin_name: str) -> Optional[str]:
[go, "install", pkg],
check=False,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=600,
env=env,
stdin=subprocess.DEVNULL,

View file

@ -706,7 +706,7 @@ def iron_proxy_version(binary: Path) -> str:
res = subprocess.run( # noqa: S603
[str(binary), "--version"],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=_RUN_TIMEOUT,
env=minimal_env,
)
@ -1052,7 +1052,7 @@ def _detect_docker_bridge_ip() -> Optional[str]:
try:
res = subprocess.run( # noqa: S603 — ip is a system binary
["ip", "-4", "-o", "addr", "show", "docker0"],
capture_output=True, text=True, timeout=2,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=2,
)
if res.returncode == 0:
for line in res.stdout.splitlines():
@ -1743,7 +1743,7 @@ def _pid_alive(pid: int) -> bool:
try:
res = subprocess.run( # noqa: S603
["ps", "-p", str(pid), "-o", "comm="],
capture_output=True, text=True, timeout=2,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=2,
)
if res.returncode == 0:
comm = (res.stdout or "").strip()

View file

@ -295,7 +295,7 @@ def run_secret_cli(
list(argv),
env=env,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=timeout,
stdin=subprocess.DEVNULL,
)

View file

@ -162,7 +162,7 @@ def build_trace_jsonl(
if cwd:
r = subprocess.run(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True, text=True, timeout=3, cwd=cwd,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=3, cwd=cwd,
)
if r.returncode == 0:
git_branch = r.stdout.strip()

48
cli.py
View file

@ -1432,7 +1432,7 @@ def _git_repo_root() -> Optional[str]:
try:
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
capture_output=True, text=True, timeout=5,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5,
)
if result.returncode == 0:
return _normalize_git_bash_path(result.stdout.strip())
@ -1479,7 +1479,7 @@ def _resolve_worktree_base(repo_root: str) -> tuple:
def _git(args, timeout=20):
return subprocess.run(
["git", *args],
capture_output=True, text=True, timeout=timeout, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=repo_root,
)
# 1. Current branch's upstream, if it tracks one.
@ -1578,7 +1578,7 @@ def _setup_worktree(repo_root: str = None, sync_base: bool = True) -> Optional[D
try:
result = subprocess.run(
["git", "worktree", "add", str(wt_path), "-b", branch_name, base_ref],
capture_output=True, text=True, timeout=30, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=30, cwd=repo_root,
)
if result.returncode != 0:
# If branching from the resolved remote ref failed for any reason
@ -1592,7 +1592,7 @@ def _setup_worktree(repo_root: str = None, sync_base: bool = True) -> Optional[D
base_ref, base_label = "HEAD", "HEAD (fallback — remote base failed)"
result = subprocess.run(
["git", "worktree", "add", str(wt_path), "-b", branch_name, base_ref],
capture_output=True, text=True, timeout=30, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=30, cwd=repo_root,
)
if result.returncode != 0:
print(f"\033[31m✗ Failed to create worktree: {result.stderr.strip()}\033[0m")
@ -1673,7 +1673,7 @@ def _setup_worktree(repo_root: str = None, sync_base: bool = True) -> Optional[D
try:
subprocess.run(
["git", "worktree", "lock", "--reason", f"hermes pid={os.getpid()}", str(wt_path)],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
logger.debug("Worktree locked: %s (pid=%s)", wt_path, os.getpid())
except Exception as e:
@ -1706,7 +1706,7 @@ def _worktree_has_unpushed_commits(worktree_path: str, timeout: int = 10) -> boo
try:
remote_refs = subprocess.run(
["git", "for-each-ref", "--format=%(refname)", "refs/remotes"],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if remote_refs.returncode != 0:
return True
@ -1715,7 +1715,7 @@ def _worktree_has_unpushed_commits(worktree_path: str, timeout: int = 10) -> boo
result = subprocess.run(
["git", "log", "--oneline", "HEAD", "--not", "--remotes"],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if result.returncode != 0:
return True
@ -1736,7 +1736,7 @@ def _worktree_is_dirty(worktree_path: str, timeout: int = 10) -> bool:
try:
result = subprocess.run(
["git", "status", "--porcelain"],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if result.returncode != 0:
return True
@ -1769,7 +1769,7 @@ def _worktree_commits_all_merged_upstream(
try:
probe = subprocess.run(
["git", "rev-parse", "--verify", "--quiet", candidate],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if probe.returncode == 0 and probe.stdout.strip():
base = candidate
@ -1782,7 +1782,7 @@ def _worktree_commits_all_merged_upstream(
try:
ahead = subprocess.run(
["git", "rev-list", "--count", f"{base}..HEAD"],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if ahead.returncode != 0:
return False
@ -1794,7 +1794,7 @@ def _worktree_commits_all_merged_upstream(
cherry = subprocess.run(
["git", "cherry", base, "HEAD"],
capture_output=True, text=True, timeout=timeout, cwd=worktree_path,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=worktree_path,
)
if cherry.returncode != 0:
return False
@ -1829,7 +1829,7 @@ def _worktree_lock_is_live(repo_root: str, worktree_path: str, timeout: int = 10
try:
result = subprocess.run(
["git", "worktree", "list", "--porcelain"],
capture_output=True, text=True, timeout=timeout, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, cwd=repo_root,
)
if result.returncode != 0:
return "live"
@ -1904,7 +1904,7 @@ def _cleanup_worktree(info: Dict[str, str] = None) -> None:
try:
subprocess.run(
["git", "worktree", "unlock", wt_path],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
except Exception as e:
logger.debug("git worktree unlock failed (non-fatal): %s", e)
@ -1912,7 +1912,7 @@ def _cleanup_worktree(info: Dict[str, str] = None) -> None:
try:
subprocess.run(
["git", "worktree", "remove", wt_path, "--force"],
capture_output=True, text=True, timeout=15, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=15, cwd=repo_root,
)
except Exception as e:
logger.debug("Failed to remove worktree: %s", e)
@ -1921,7 +1921,7 @@ def _cleanup_worktree(info: Dict[str, str] = None) -> None:
try:
subprocess.run(
["git", "branch", "-D", branch],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
except Exception as e:
logger.debug("Failed to delete branch %s: %s", branch, e)
@ -2122,7 +2122,7 @@ def _prune_stale_worktrees(repo_root: str, max_age_hours: int = 24) -> None:
try:
subprocess.run(
["git", "worktree", "unlock", str(entry)],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
except Exception as e:
logger.debug("Failed to unlock dead worktree %s: %s", entry.name, e)
@ -2131,13 +2131,13 @@ def _prune_stale_worktrees(repo_root: str, max_age_hours: int = 24) -> None:
try:
branch_result = subprocess.run(
["git", "branch", "--show-current"],
capture_output=True, text=True, timeout=5, cwd=str(entry),
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5, cwd=str(entry),
)
branch = branch_result.stdout.strip()
remove_result = subprocess.run(
["git", "worktree", "remove", str(entry), "--force"],
capture_output=True, text=True, timeout=15, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=15, cwd=repo_root,
)
if remove_result.returncode != 0:
# Removal failed — keep the branch so any commits stay
@ -2150,7 +2150,7 @@ def _prune_stale_worktrees(repo_root: str, max_age_hours: int = 24) -> None:
if branch:
subprocess.run(
["git", "branch", "-D", branch],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
logger.debug("Pruned stale worktree: %s (force=%s)", entry.name, force)
except Exception as e:
@ -2178,7 +2178,7 @@ def _prune_orphaned_branches(repo_root: str) -> None:
try:
result = subprocess.run(
["git", "branch", "--format=%(refname:short)"],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
if result.returncode != 0:
return
@ -2191,7 +2191,7 @@ def _prune_orphaned_branches(repo_root: str) -> None:
try:
wt_result = subprocess.run(
["git", "worktree", "list", "--porcelain"],
capture_output=True, text=True, timeout=10, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10, cwd=repo_root,
)
for line in wt_result.stdout.split("\n"):
if line.startswith("branch refs/heads/"):
@ -2203,7 +2203,7 @@ def _prune_orphaned_branches(repo_root: str) -> None:
try:
head_result = subprocess.run(
["git", "branch", "--show-current"],
capture_output=True, text=True, timeout=5, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5, cwd=repo_root,
)
current = head_result.stdout.strip()
if current:
@ -2227,7 +2227,7 @@ def _prune_orphaned_branches(repo_root: str) -> None:
try:
subprocess.run(
["git", "branch", "-D"] + batch,
capture_output=True, text=True, timeout=30, cwd=repo_root,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=30, cwd=repo_root,
)
except Exception as e:
logger.debug("Failed to prune orphaned branches: %s", e)
@ -9528,7 +9528,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
from hermes_cli._subprocess_compat import windows_hide_flags
result = subprocess.run(
exec_cmd, shell=True, capture_output=True,
text=True, timeout=30, env=sanitized_env,
text=True, encoding="utf-8", errors="replace", timeout=30, env=sanitized_env,
# No console flash on Windows (#56747).
creationflags=windows_hide_flags(),
)

View file

@ -252,7 +252,7 @@ class WebhookRouteProcessor:
argv,
input=json.dumps(payload),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=self.script_timeout_seconds,
cwd=str(path.parent),
env=_sanitize_subprocess_env(os.environ.copy()),

View file

@ -7271,7 +7271,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
out = subprocess.run(
[systemctl, *scope_flags, "show", service_name,
"--property=MainPID", "--value"],
capture_output=True, text=True, timeout=2,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=2,
)
return (out.stdout or "").strip()
except Exception:

View file

@ -131,7 +131,7 @@ def _run_repair_install(specs: list[str], project_root: Path) -> bool:
[sys.executable, "-m", "pip", "install", "--force-reinstall", *specs],
cwd=project_root,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
except Exception as exc:
print(f" ✗ Early venv repair could not run pip: {exc}", file=sys.stderr)

View file

@ -1330,7 +1330,7 @@ def _probe_container(cmd: list, backend: str, via_sudo: bool = False):
all other exceptions propagate naturally.
"""
try:
return subprocess.run(cmd, capture_output=True, text=True, timeout=15)
return subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=15)
except subprocess.TimeoutExpired:
label = f"sudo {backend}" if via_sudo else backend
print(
@ -1843,7 +1843,7 @@ def _restore_tui_workspace(tui_dir: Path) -> bool:
[git, "restore", "--", tui_dir.name],
cwd=str(tui_dir.parent),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
)
except OSError:
@ -4729,7 +4729,7 @@ def _capture_head_sha(git_cmd, cwd) -> str | None:
git_cmd + ["rev-parse", "HEAD"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
return result.stdout.strip() or None
@ -5088,7 +5088,7 @@ def _nixos_build_env() -> dict[str, str] | None:
try:
result = subprocess.run(
["nix-shell", "-p", "python3", "--run", "which python3"],
capture_output=True, text=True, check=False, timeout=15,
capture_output=True, text=True, encoding="utf-8", errors="replace", check=False, timeout=15,
)
if result.returncode == 0:
python3_path = result.stdout.strip()
@ -6290,7 +6290,7 @@ def _find_stale_dashboard_pids(
result = subprocess.run(
["ps", "-A", "-o", "pid=,command="],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
if result.returncode == 0:
@ -6579,7 +6579,7 @@ def _restart_managed_dashboard_service(
return subprocess.run(
["systemctl", *args],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=timeout,
)
@ -6643,7 +6643,7 @@ def _restart_managed_dashboard_service(
result = subprocess.run(
list(command),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=60,
)
except (FileNotFoundError, subprocess.TimeoutExpired, OSError) as e:
@ -6732,7 +6732,7 @@ def _kill_stale_dashboard_processes(
result = subprocess.run(
["taskkill", "/PID", str(pid), "/F"],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
if result.returncode == 0:
@ -7055,7 +7055,7 @@ def _stash_local_changes_if_needed(git_cmd: list[str], cwd: Path) -> Optional[st
git_cmd + ["status", "--porcelain"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
if not status.stdout.strip():
@ -7069,7 +7069,7 @@ def _stash_local_changes_if_needed(git_cmd: list[str], cwd: Path) -> Optional[st
git_cmd + ["ls-files", "--unmerged"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if unmerged.stdout.strip():
print("→ Clearing unmerged index entries from a previous conflict...")
@ -7085,13 +7085,13 @@ def _stash_local_changes_if_needed(git_cmd: list[str], cwd: Path) -> Optional[st
git_cmd + ["rev-parse", "--verify", "refs/stash"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
).stdout.strip()
push = subprocess.run(
git_cmd + ["stash", "push", "--include-untracked", "-m", stash_name],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if push.stdout.strip():
print(push.stdout.strip())
@ -7099,7 +7099,7 @@ def _stash_local_changes_if_needed(git_cmd: list[str], cwd: Path) -> Optional[st
git_cmd + ["rev-parse", "--verify", "refs/stash"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
stash_ref = stash_probe.stdout.strip()
stash_created = (
@ -7157,7 +7157,7 @@ def _resolve_stash_selector(
git_cmd + ["stash", "list", "--format=%gd %H"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
for line in stash_list.stdout.splitlines():
@ -7242,7 +7242,7 @@ def _restore_stashed_changes(
git_cmd + ["stash", "apply", stash_ref],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
# Check for unmerged (conflicted) files — can happen even when returncode is 0
@ -7250,7 +7250,7 @@ def _restore_stashed_changes(
git_cmd + ["diff", "--name-only", "--diff-filter=U"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
has_conflicts = bool(unmerged.stdout.strip())
@ -7312,7 +7312,7 @@ def _restore_stashed_changes(
git_cmd + ["stash", "drop", stash_selector],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if drop.returncode != 0:
print(
@ -7364,7 +7364,7 @@ def _discard_stashed_changes(
git_cmd + ["stash", "drop", stash_selector],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if drop.returncode != 0:
print(
@ -7401,7 +7401,7 @@ def _get_origin_url(git_cmd: list[str], cwd: Path) -> Optional[str]:
git_cmd + ["remote", "get-url", "origin"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.returncode == 0:
return result.stdout.strip()
@ -7434,7 +7434,7 @@ def _has_upstream_remote(git_cmd: list[str], cwd: Path) -> bool:
git_cmd + ["remote", "get-url", "upstream"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
return result.returncode == 0
except Exception:
@ -7448,7 +7448,7 @@ def _add_upstream_remote(git_cmd: list[str], cwd: Path) -> bool:
git_cmd + ["remote", "add", "upstream", OFFICIAL_REPO_URL],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
return result.returncode == 0
except Exception:
@ -7462,7 +7462,7 @@ def _count_commits_between(git_cmd: list[str], cwd: Path, base: str, head: str)
git_cmd + ["rev-list", "--count", f"{base}..{head}"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.returncode == 0:
return int(result.stdout.strip())
@ -7498,7 +7498,7 @@ def _sync_fork_with_upstream(git_cmd: list[str], cwd: Path) -> bool:
git_cmd + ["push", "origin", "main", "--force-with-lease"],
cwd=cwd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
return result.returncode == 0
except Exception:
@ -8541,7 +8541,7 @@ def _detect_broken_lazy_refresh_imports(
result = subprocess.run(
[str(venv_python), "-c", check_script],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
env=env,
)
@ -9000,7 +9000,7 @@ def _verify_core_dependencies_installed(
result = subprocess.run(
[str(venv_python), "-c", check_script, *applicable],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
env=env,
)
@ -9722,7 +9722,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["rev-parse", "--is-shallow-repository"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
).stdout.strip()
== "true"
)
@ -9734,7 +9734,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["fetch"] + depth_args + ["upstream", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if fetch_result.returncode != 0:
# Fallback to origin if upstream doesn't exist
@ -9743,7 +9743,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["fetch"] + depth_args + ["origin", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
upstream_exists = False
compare_branch = f"origin/{branch}"
@ -9757,7 +9757,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["fetch"] + depth_args + ["origin", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
upstream_exists = False
compare_branch = f"origin/{branch}"
@ -9782,7 +9782,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["rev-parse", "--verify", "--quiet", compare_branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if verify_result.returncode != 0:
print(f"✗ Branch '{branch}' not found on {compare_branch.split('/', 1)[0]}.")
@ -9793,11 +9793,11 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
# report presence-only (mirrors the banner's _check_via_local_git).
head_sha = subprocess.run(
git_cmd + ["rev-parse", "HEAD"],
cwd=PROJECT_ROOT, capture_output=True, text=True,
cwd=PROJECT_ROOT, capture_output=True, text=True, encoding="utf-8", errors="replace",
).stdout.strip()
target_sha = subprocess.run(
git_cmd + ["rev-parse", compare_branch],
cwd=PROJECT_ROOT, capture_output=True, text=True,
cwd=PROJECT_ROOT, capture_output=True, text=True, encoding="utf-8", errors="replace",
).stdout.strip()
if head_sha and target_sha and head_sha == target_sha:
print("✓ Already up to date.")
@ -9812,7 +9812,7 @@ def _cmd_update_check(branch: str = "main", *, branch_explicit: bool = False):
git_cmd + ["rev-list", f"HEAD..{compare_branch}", "--count"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
behind = int(rev_result.stdout.strip())
@ -9873,7 +9873,7 @@ def _ensure_fhs_path_guard() -> None:
"command -v hermes",
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
except (FileNotFoundError, subprocess.TimeoutExpired):
@ -10197,7 +10197,7 @@ def _venv_core_imports_healthy() -> tuple[bool, str]:
result = subprocess.run(
[str(venv_python), "-c", check],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=60,
cwd=PROJECT_ROOT,
)
@ -10640,7 +10640,7 @@ def _discard_lockfile_churn(git_cmd, repo_root):
git_cmd + ["diff", "--name-only"],
cwd=repo_root,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if diff.returncode != 0:
return
@ -10661,7 +10661,7 @@ def _discard_lockfile_churn(git_cmd, repo_root):
git_cmd + ["checkout", "--", *dirty],
cwd=repo_root,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
)
print(f"→ Discarded npm lockfile churn ({len(dirty)} file(s))")
@ -10886,7 +10886,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["fetch", "origin", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if fetch_result.returncode != 0:
stderr = fetch_result.stderr.strip()
@ -10910,7 +10910,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["rev-parse", "--abbrev-ref", "HEAD"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
current_branch = result.stdout.strip()
@ -10933,7 +10933,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["checkout", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if checkout_result.returncode != 0:
# Local checkout doesn't have this branch yet. Try to set
@ -10944,7 +10944,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["checkout", "-B", branch, f"origin/{branch}"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if track_result.returncode != 0:
# Restore the user's prior branch + stash before bailing
@ -10975,7 +10975,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["rev-list", f"HEAD..origin/{branch}", "--count"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=True,
)
commit_count = int(result.stdout.strip())
@ -11001,7 +11001,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["checkout", current_branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
)
@ -11073,7 +11073,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["pull", "--ff-only", "origin", branch],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if pull_result.returncode != 0:
# ff-only failed — local and remote have diverged (e.g. upstream
@ -11086,7 +11086,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["reset", "--hard", f"origin/{branch}"],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if reset_result.returncode != 0:
print(f"✗ Failed to reset to origin/{branch}.")
@ -11122,7 +11122,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
git_cmd + ["reset", "--hard", pre_pull_sha],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if rollback_result.returncode == 0:
print(" ✓ Rollback complete — your install is unchanged.")
@ -11717,7 +11717,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
_verify = subprocess.run(
scope_cmd_ + ["is-active", svc_name_],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=5,
)
if _verify.stdout.strip() == "active":
@ -11751,7 +11751,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
"--value",
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=5,
)
except (FileNotFoundError, subprocess.TimeoutExpired):
@ -11900,7 +11900,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
"--no-pager",
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
except FileNotFoundError:
@ -11919,7 +11919,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
check = subprocess.run(
scope_cmd + ["is-active", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=5,
)
if check.stdout.strip() != "active":
@ -11952,7 +11952,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
"--value",
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=5,
)
_main_pid = int((_show.stdout or "").strip() or 0)
@ -12005,13 +12005,13 @@ def _cmd_update_impl(args, gateway_mode: bool):
subprocess.run(
_manage_cmd + ["reset-failed", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
subprocess.run(
_manage_cmd + ["start", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=15,
)
# Short poll: the gateway should be up
@ -12095,13 +12095,13 @@ def _cmd_update_impl(args, gateway_mode: bool):
subprocess.run(
_manage_cmd + ["reset-failed", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
restart = subprocess.run(
_manage_cmd + ["restart", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=15,
)
if restart.returncode == 0:
@ -12127,13 +12127,13 @@ def _cmd_update_impl(args, gateway_mode: bool):
subprocess.run(
_manage_cmd + ["reset-failed", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
)
subprocess.run(
_manage_cmd + ["restart", svc_name],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=15,
)
if _wait_for_service_active(
@ -12191,7 +12191,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
check = subprocess.run(
["launchctl", "list", get_launchd_label()],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=5,
)
if check.returncode == 0:
@ -15016,7 +15016,7 @@ def main():
from hermes_cli.tools_config import _cua_driver_env
version = subprocess.run(
[path, "--version"],
capture_output=True, text=True, timeout=5,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5,
env=_cua_driver_env(),
).stdout.strip()
except Exception:

View file

@ -1450,7 +1450,7 @@ def setup_terminal_backend(config: dict):
ssh_cmd.extend(["-p", port])
ssh_cmd.append(f"{user}@{host}" if user else host)
ssh_cmd.append("echo ok")
result = subprocess.run(ssh_cmd, capture_output=True, text=True, timeout=10)
result = subprocess.run(ssh_cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=10)
if result.returncode == 0:
print_success(" SSH connection successful!")
else:

View file

@ -708,7 +708,7 @@ def _pip_install(
try:
result = subprocess.run(
[uv_bin, "pip", "install", *args],
capture_output=capture_output, text=True, timeout=timeout,
capture_output=capture_output, text=True, encoding="utf-8", errors="replace", timeout=timeout,
env=uv_env,
creationflags=_post_setup_no_window_flags(
streams_to_console=not capture_output
@ -726,7 +726,7 @@ def _pip_install(
# Probe for pip; bootstrap via ensurepip if missing (uv venv lacks it).
probe = subprocess.run(
pip_cmd + ["--version"],
capture_output=True, text=True, timeout=15,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=15,
creationflags=_post_setup_no_window_flags(),
)
if probe.returncode != 0:
@ -735,7 +735,7 @@ def _pip_install(
try:
subprocess.run(
[sys.executable, "-m", "ensurepip", "--upgrade", "--default-pip"],
capture_output=True, text=True, timeout=120, check=True,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=120, check=True,
creationflags=_post_setup_no_window_flags(),
)
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
@ -747,7 +747,7 @@ def _pip_install(
return subprocess.run(
pip_cmd + ["install", *args],
capture_output=capture_output, text=True, timeout=timeout,
capture_output=capture_output, text=True, encoding="utf-8", errors="replace", timeout=timeout,
creationflags=_post_setup_no_window_flags(
streams_to_console=not capture_output
),
@ -859,7 +859,7 @@ def install_cua_driver(upgrade: bool = False) -> bool:
try:
version = subprocess.run(
[binary, "--version"],
capture_output=True, text=True, timeout=5, env=_cua_driver_env(),
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5, env=_cua_driver_env(),
creationflags=_post_setup_no_window_flags(),
).stdout.strip()
_print_success(f" {driver_cmd} already installed: {version or 'unknown version'}")
@ -917,7 +917,7 @@ def install_cua_driver(upgrade: bool = False) -> bool:
try:
before = subprocess.run(
[binary, "--version"],
capture_output=True, text=True, timeout=5, env=_cua_driver_env(),
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5, env=_cua_driver_env(),
creationflags=_post_setup_no_window_flags(),
).stdout.strip()
except Exception:
@ -930,7 +930,7 @@ def install_cua_driver(upgrade: bool = False) -> bool:
try:
after = subprocess.run(
[binary, "--version"],
capture_output=True, text=True, timeout=5, env=_cua_driver_env(),
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5, env=_cua_driver_env(),
creationflags=_post_setup_no_window_flags(),
).stdout.strip()
if after and after != before:
@ -1075,7 +1075,7 @@ def _run_cua_driver_installer(label: str = "Installing", verbose: bool = True) -
try:
dl = subprocess.run(
["curl", "-fsSL", "-o", script_path, install_url],
capture_output=True, text=True, timeout=120,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=120,
)
except (subprocess.TimeoutExpired, OSError) as e:
_print_warning(f" cua-driver installer download failed: {e}")
@ -1243,7 +1243,7 @@ def _run_post_setup(post_setup_key: str):
# only, avoiding the apps/* glob which would pull in
# apps/desktop (Electron + node-pty) unnecessarily. See #38772.
[npm_bin, "install", "--silent", "--workspaces=false"],
capture_output=True, text=True, cwd=str(PROJECT_ROOT),
capture_output=True, text=True, encoding="utf-8", errors="replace", cwd=str(PROJECT_ROOT),
creationflags=_post_setup_no_window_flags(),
)
if result.returncode == 0:
@ -1323,7 +1323,7 @@ def _run_post_setup(post_setup_key: str):
try:
result = subprocess.run(
install_cmd,
capture_output=True, text=True, cwd=str(PROJECT_ROOT), timeout=600,
capture_output=True, text=True, encoding="utf-8", errors="replace", cwd=str(PROJECT_ROOT), timeout=600,
creationflags=_post_setup_no_window_flags(),
)
if result.returncode == 0:
@ -1357,7 +1357,7 @@ def _run_post_setup(post_setup_key: str):
result = subprocess.run(
# --workspaces=false avoids resolving apps/desktop. See #38772.
[_npm_bin, "install", "--silent", "--workspaces=false"],
capture_output=True, text=True, cwd=str(PROJECT_ROOT),
capture_output=True, text=True, encoding="utf-8", errors="replace", cwd=str(PROJECT_ROOT),
creationflags=_post_setup_no_window_flags(),
)
if result.returncode == 0:

View file

@ -362,7 +362,7 @@ def _resolve_direct_interpreter(python_entry: str) -> tuple[str, list[str]]:
"print(json.dumps({'base':getattr(sys,'_base_executable','') or sys.executable,"
"'path':[p for p in sys.path if p],'root':root}))"
)
out = subprocess.run([python_entry, "-c", query], capture_output=True, text=True, timeout=30)
out = subprocess.run([python_entry, "-c", query], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=30)
if out.returncode != 0:
raise ValueError("could not resolve the base Python interpreter")
info = json.loads(out.stdout.strip().splitlines()[-1])
@ -437,8 +437,8 @@ def inspect_hermes(hermes_path: str) -> dict[str, Any]:
path = os.path.abspath(hermes_path)
if not os.path.isabs(hermes_path) or not os.path.isfile(path):
raise ValueError("Hermes path is not an executable file")
version = subprocess.run([path, "--version"], capture_output=True, text=True, timeout=20)
help_result = subprocess.run([path, "serve", "--help"], capture_output=True, text=True, timeout=20)
version = subprocess.run([path, "--version"], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=20)
help_result = subprocess.run([path, "serve", "--help"], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=20)
help_text = help_result.stdout + help_result.stderr
return {
"path": path,

View file

@ -183,7 +183,7 @@ def _reinstall_sidecar_deps() -> None:
[npm, "ci"],
cwd=str(_SIDECAR_DIR),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
timeout=_NPM_REINSTALL_TIMEOUT,
creationflags=windows_hide_flags(),
@ -196,7 +196,7 @@ def _reinstall_sidecar_deps() -> None:
[npm, "install"],
cwd=str(_SIDECAR_DIR),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
check=False,
timeout=_NPM_REINSTALL_TIMEOUT,
creationflags=windows_hide_flags(),

View file

@ -355,7 +355,7 @@ def _probe_voice_duration_seconds(path: str) -> Optional[int]:
proc = subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1", path],
capture_output=True, text=True, timeout=5,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=5,
)
if proc.returncode == 0:
return _coerce_duration_seconds(proc.stdout.strip())

View file

@ -115,7 +115,7 @@ def _git_show(ref: str, path: str, repo_root: str) -> str | None:
proc = subprocess.run(
["git", "show", f"{ref}:{path}"],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
cwd=repo_root,
)
return proc.stdout if proc.returncode == 0 else None
@ -125,7 +125,7 @@ def _tracked_lockfiles(ref: str, repo_root: str) -> set[str]:
proc = subprocess.run(
["git", "ls-tree", "-r", "--name-only", ref],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
cwd=repo_root,
check=True,
)

View file

@ -246,7 +246,7 @@ def upload_evidence(
],
check=True,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
env=environment,
)
except subprocess.CalledProcessError as exc:

View file

@ -178,7 +178,7 @@ class ScratchDashboard:
]
self.proc = subprocess.Popen(
cmd, cwd=str(REPO_ROOT), env=env,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding="utf-8", errors="replace", bufsize=1,
)
threading.Thread(target=self._drain, args=(self.proc.stdout,), name="dash-log", daemon=True).start()
if not self._ready.wait(timeout=90.0):

View file

@ -2097,7 +2097,7 @@ def git(*args, cwd=None):
"""Run a git command and return stdout."""
result = subprocess.run(
["git"] + list(args),
capture_output=True, text=True,
capture_output=True, text=True, encoding="utf-8", errors="replace",
cwd=cwd or str(REPO_ROOT),
)
if result.returncode != 0:
@ -2111,7 +2111,7 @@ def git_result(*args, cwd=None):
return subprocess.run(
["git"] + list(args),
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
cwd=cwd or str(REPO_ROOT),
)
@ -2591,7 +2591,7 @@ def main():
if gh_bin:
result = subprocess.run(
gh_cmd,
capture_output=True, text=True,
capture_output=True, text=True, encoding="utf-8", errors="replace",
cwd=str(REPO_ROOT),
)
else:

View file

@ -314,7 +314,7 @@ def _run_one_file_once(
cwd=repo_root,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
text=True, encoding="utf-8", errors="replace",
env=os.environ,
# POSIX: place the child at the head of its own process group so
# _kill_tree can SIGKILL the group atomically.

View file

@ -68,7 +68,7 @@ def accept_changes(
result = subprocess.run(
cmd,
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=30,
check=False,
env=get_soffice_env(),

View file

@ -201,7 +201,7 @@ class RedliningValidator:
str(modified_file),
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.stdout.strip():
@ -229,7 +229,7 @@ class RedliningValidator:
str(modified_file),
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.stdout.strip():

View file

@ -201,7 +201,7 @@ class RedliningValidator:
str(modified_file),
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.stdout.strip():
@ -229,7 +229,7 @@ class RedliningValidator:
str(modified_file),
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.stdout.strip():

View file

@ -192,6 +192,8 @@ def convert_to_images(pptx_path: Path, temp_dir: Path) -> list[Path]:
["--headless", "--convert-to", "pdf", "--outdir", str(temp_dir), str(pptx_path)],
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
if result.returncode != 0 or not pdf_path.exists():
detail = (result.stderr or result.stdout or "").strip()
@ -207,7 +209,7 @@ def convert_to_images(pptx_path: Path, temp_dir: Path) -> list[Path]:
str(temp_dir / "slide"),
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
)
if result.returncode != 0:
raise RuntimeError("Image conversion failed")

View file

@ -189,7 +189,7 @@ def _recalc_with_profile(filename, abs_path, timeout, profile_dir: Path):
try:
result = subprocess.run(
cmd, capture_output=True, text=True, env=get_soffice_env(), timeout=timeout + 15
cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", env=get_soffice_env(), timeout=timeout + 15
)
except subprocess.TimeoutExpired:
return {"error": timed_out}

View file

@ -295,7 +295,7 @@ def _linux_x11_active_window_id() -> Optional[int]:
proc = subprocess.run(
["xprop", "-root", "_NET_ACTIVE_WINDOW"],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=2,
check=False,
)
@ -379,7 +379,7 @@ def _resolve_mcp_invocation(
from tools.environments.local import _sanitize_subprocess_env
proc = subprocess.run(
[driver_cmd, "manifest"],
capture_output=True, text=True, timeout=timeout,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout,
stdin=subprocess.DEVNULL,
# cua-driver is a third-party binary — never hand it provider
# API keys via inherited env (same policy as the MCP and CLI
@ -445,7 +445,7 @@ def _cua_driver_supports_no_overlay(driver_cmd: str) -> bool:
from tools.environments.local import _sanitize_subprocess_env
proc = subprocess.run(
[driver_cmd, "--help"],
capture_output=True, text=True, timeout=3.0,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=3.0,
stdin=subprocess.DEVNULL,
env=_sanitize_subprocess_env(cua_driver_child_env()),
)
@ -576,7 +576,7 @@ def cua_driver_update_check(*, timeout: float = 8.0) -> Optional[Dict[str, Any]]
from tools.environments.local import _sanitize_subprocess_env
proc = subprocess.run(
[driver_cmd, "check-update", "--json"],
capture_output=True, text=True, timeout=timeout,
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout,
# Some older drivers don't have the verb and fall through to a
# stdin-reading mode rather than erroring — DEVNULL gives them EOF
# so they exit fast instead of blocking until the timeout.
@ -1256,7 +1256,7 @@ class _CuaDriverSession:
for attempt in range(attempts):
try:
proc = _subprocess.run(
cmd, capture_output=True, text=True, timeout=max(15.0, timeout),
cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=max(15.0, timeout),
env=_sanitize_subprocess_env(cua_driver_child_env()),
)
except Exception as e: # pragma: no cover - subprocess spawn failure

View file

@ -248,7 +248,7 @@ def _popen_bash(
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE if stdin_data is not None else subprocess.DEVNULL,
text=True,
text=True, encoding="utf-8", errors="replace",
**kwargs,
)
if stdin_data is not None:

View file

@ -1377,7 +1377,7 @@ class DockerEnvironment(BaseEnvironment):
subprocess.run(
[self._docker_exe, "rm", "-f", container_id],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=30,
check=False,
stdin=subprocess.DEVNULL,
@ -1701,7 +1701,7 @@ class DockerEnvironment(BaseEnvironment):
container_id,
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
check=False,
stdin=subprocess.DEVNULL,

View file

@ -764,7 +764,7 @@ def _mandatory_aslr_enabled() -> "bool | None":
"(Get-ProcessMitigation -System).Aslr.ForceRelocateImages.ToString()",
],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=10,
creationflags=windows_hide_flags(),
)
@ -830,7 +830,7 @@ def _bash_starts(bash: str) -> bool:
result = subprocess.run(
[bash, "--noprofile", "--norc", "-c", _BASH_EXTERNAL_PROGRAM_PROBE],
capture_output=True,
text=True,
text=True, encoding="utf-8", errors="replace",
timeout=15,
creationflags=windows_hide_flags() if _IS_WINDOWS else 0,
)