A Bot's browser identifies itself as headless and automated, so Google refuses sign-in with "Couldn't sign you in — This browser or app may not be secure." Take-the-wheel exists so a person can finish exactly this kind of sign-in, and the person cannot: the refusal is on Google's side and no amount of clicking gets past it.
This is not a heuristic that happened to fire. The browser is announcing it.
What is wrong
LAUNCH_ARGS (agent-computer/src/profiles.ts:95-99) is three flags, and nothing anywhere in agent-computer/src touches automation signalling — no --disable-blink-features=AutomationControlled, no enable-automation exclusion, no user-agent override, and no channel on chromium.launchPersistentContext (profiles.ts:296), so the launch is Playwright's bundled Chromium at its default, which is headless.
Measured from inside a running Bot's browser on this deployment, by navigating it to a page that prints what a site sees:
{
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.7922.34 Safari/537.36",
"webdriver": true,
"headlessHint": true,
"uaDataBrands": null,
"plugins": 0,
"languages": ["en-US@posix"]
}
HeadlessChrome in the user-agent string and navigator.webdriver === true are each independently sufficient for Google's sign-in to refuse. navigator.userAgentData.brands being null and zero plugins are consistent with the same. The en-US@posix locale is a separate oddity worth knowing about — it is a POSIX locale modifier rather than a language tag, and sites that parse navigator.languages may mishandle it.
Why it matters
It removes the feature rather than degrading it. A Bot that meets a Google sign-in cannot proceed, and neither can the person who takes the wheel to help it, so the escape hatch and the thing it is an escape hatch from fail together. Google sign-in is a common gate in front of ordinary work, and Google is not the only provider that checks.
It is also invisible until late. Nothing at start-up says the browser will be refused by some sites; the operator finds out when a person is already sitting in front of a takeover that cannot be completed.
Related: #270 blocks the same workflow at a different point (a popup sign-in window is unreachable). Fixing either one alone still leaves popup-based Google sign-in broken.
On what a fix should and should not be
Worth stating plainly, because the obvious fix is the wrong one: the goal here is not to defeat bot detection. Google's check is correct — it is an automated browser. Suppressing the signals while the Bot drives would make the detector wrong rather than the situation better, and may run against the provider's terms.
What is defensible is narrower: when a person has taken the wheel and is signing into their own account, the browser they are typing into should be an ordinary browser, because at that moment the automation claim is no longer true. Options, with their costs:
- Run headed under Xvfb. Removes
HeadlessChrome from the user-agent honestly, because the browser genuinely is not headless. Costs an X server in the image and some memory.
- Use a real Chrome build (
channel: "chrome") rather than bundled Chromium. Changes what ships in the image and its licensing.
- Leave
navigator.webdriver alone. It is true, and a deployment that lies about it is claiming something false about itself.
- Document the limitation and point at the credential vault for providers that cannot be signed into interactively — the honest answer if the above are judged not worth it.
Whatever is chosen, saying it at start-up alongside the existing computer-sandbox line would stop an operator discovering it mid-takeover.
How to check it is fixed
Take the wheel on a page that offers Google sign-in and complete it. As a cheaper proxy, navigate a Bot to a page printing navigator.userAgent and navigator.webdriver and confirm the user-agent no longer contains Headless.
Scope of verification
The fingerprint above was measured on a real deployment at 7fda66a plus the branch for #270, through agent-computer's own /navigate and /read. The Google refusal was observed by a person holding the wheel. I have not tested any of the suggested remedies.
A Bot's browser identifies itself as headless and automated, so Google refuses sign-in with "Couldn't sign you in — This browser or app may not be secure." Take-the-wheel exists so a person can finish exactly this kind of sign-in, and the person cannot: the refusal is on Google's side and no amount of clicking gets past it.
This is not a heuristic that happened to fire. The browser is announcing it.
What is wrong
LAUNCH_ARGS(agent-computer/src/profiles.ts:95-99) is three flags, and nothing anywhere inagent-computer/srctouches automation signalling — no--disable-blink-features=AutomationControlled, noenable-automationexclusion, no user-agent override, and nochannelonchromium.launchPersistentContext(profiles.ts:296), so the launch is Playwright's bundled Chromium at its default, which is headless.Measured from inside a running Bot's browser on this deployment, by navigating it to a page that prints what a site sees:
{ "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.7922.34 Safari/537.36", "webdriver": true, "headlessHint": true, "uaDataBrands": null, "plugins": 0, "languages": ["en-US@posix"] }HeadlessChromein the user-agent string andnavigator.webdriver === trueare each independently sufficient for Google's sign-in to refuse.navigator.userAgentData.brandsbeing null and zero plugins are consistent with the same. Theen-US@posixlocale is a separate oddity worth knowing about — it is a POSIX locale modifier rather than a language tag, and sites that parsenavigator.languagesmay mishandle it.Why it matters
It removes the feature rather than degrading it. A Bot that meets a Google sign-in cannot proceed, and neither can the person who takes the wheel to help it, so the escape hatch and the thing it is an escape hatch from fail together. Google sign-in is a common gate in front of ordinary work, and Google is not the only provider that checks.
It is also invisible until late. Nothing at start-up says the browser will be refused by some sites; the operator finds out when a person is already sitting in front of a takeover that cannot be completed.
Related: #270 blocks the same workflow at a different point (a popup sign-in window is unreachable). Fixing either one alone still leaves popup-based Google sign-in broken.
On what a fix should and should not be
Worth stating plainly, because the obvious fix is the wrong one: the goal here is not to defeat bot detection. Google's check is correct — it is an automated browser. Suppressing the signals while the Bot drives would make the detector wrong rather than the situation better, and may run against the provider's terms.
What is defensible is narrower: when a person has taken the wheel and is signing into their own account, the browser they are typing into should be an ordinary browser, because at that moment the automation claim is no longer true. Options, with their costs:
HeadlessChromefrom the user-agent honestly, because the browser genuinely is not headless. Costs an X server in the image and some memory.channel: "chrome") rather than bundled Chromium. Changes what ships in the image and its licensing.navigator.webdriveralone. It is true, and a deployment that lies about it is claiming something false about itself.Whatever is chosen, saying it at start-up alongside the existing
computer-sandboxline would stop an operator discovering it mid-takeover.How to check it is fixed
Take the wheel on a page that offers Google sign-in and complete it. As a cheaper proxy, navigate a Bot to a page printing
navigator.userAgentandnavigator.webdriverand confirm the user-agent no longer containsHeadless.Scope of verification
The fingerprint above was measured on a real deployment at
7fda66aplus the branch for #270, throughagent-computer's own/navigateand/read. The Google refusal was observed by a person holding the wheel. I have not tested any of the suggested remedies.