P2 is_container() False-Positives on Docker Hosts Break Browser Auto-Launch — "Chrome Not Found" on Any Host with Containerd (#58135)

Executive Summary

Hermes Agent's is_container() check uses a mountinfo fallback that scans for containerd substrings. On any plain Linux host running Docker containers with the containerd image store, every running container contributes overlay mount lines containing /var/lib/containerd/... to the host's mount table. The check matches those lines and incorrectly concludes the host itself is a container. The result is cached for the process lifetime, meaning whether your browser works depends on whether a container happened to be running when the gateway started.

The Failure Cascade

StepWhat HappensWhy It's Wrong
1is_container() returns TrueFalse positive — the host is not a container, but containerd mount lines from running containers triggered the match.
2get_subprocess_home() with home_mode: auto returns an empty per-profile directoryHermes assumes it is inside a container and provisions a fresh home directory instead of using the real user home.
3Every subprocess (browser worker, ACP/CLI executors, dep-ensure) gets HOME={profile}/homeThe browser worker cannot find Chrome because the real home path is gone from the environment.
4Browser tool fails with "Chrome not found" on every browser_navigatenpx runs with the wrong HOME and cannot locate the installed browser binary.

The Timing Dependency

The reporter documented a striking case: two identically configured profiles created one minute apart ended up with permanently opposite browser behavior based entirely on gateway start order.

Profile B's home/.npm was created at the exact timestamp of its first failing browser_navigate. Profile A's home/ directory stayed completely untouched. This is deterministic misbehavior with a timing trigger.

Root Cause: Mountinfo Fallback Is Too Broad

On cgroup v2 hosts, /proc/1/cgroup is just 0::/, so is_container() falls back to scanning /proc/self/mountinfo for substrings: containerd, kubepods, crio. But every running Docker container adds overlay mount lines to the host's mount table with lowerdir=/var/lib/containerd/... — and the substring match does not distinguish between the host's own root mount and container-generated overlay entries.

The suggested fix: only inspect the root mount (the mountinfo line whose mount point is /), not every overlay mount contributed by running containers. Or do not cache a True obtained solely from the mountinfo fallback.

Impact Assessment

DimensionSeverityDetail
Browser AvailabilityHIGHThe browser is a core tool. Any host running Docker Desktop or any containerd-backed container can silently lose browser access.
Failure ModeHIGHSilent and timing-dependent — two identical profiles behave differently based on gateway start order. Extremely hard to debug without the forensic timeline the reporter provided.
ScopeHIGHAffects any Linux host where Docker containers are running. Docker Desktop's default containerd image store makes this the common case.
Fix AvailabilityMEDIUMTwo PRs already open (#58141 and #58145). Workaround exists: set terminal.home_mode: real or TERMINAL_HOME_MODE=real.

Docker/Container-Detection Bug History

IssueSeverityDescription
#50205P2Docker image missing lark-oapi — Feishu channel silently fails
#54354P2Docker backend first tool call runs on host before image pulled
#58135P2is_container() false-positives, breaks browser on any host with containerd

⚠️ Pattern: Three distinct Docker bugs now documented. #58135 is the subtlest — it is not a Docker-in-Docker bug, but a host-detection bug triggered by Docker's presence on the host. The containerd substring match in mountinfo is a single-line root cause with cascading consequences across browser, subprocess, and tool availability.

Source Evidence

📌 https://hermes-agent.reviews/hermes-is-container-false-positive-browser-58135.html
Tracked by hermes-agent.reviews — July 4, 2026