From 2c1aaa9cba600d44940f090c907330e80c8d0a8b Mon Sep 17 00:00:00 2001 From: teknium <127238744+teknium1@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:12:18 -0700 Subject: [PATCH] fix: keep interactive OAuth setup-token inheriting stdin The blanket DEVNULL pass muzzled run_oauth_setup_token()'s interactive 'claude setup-token' login, which needs inherited stdin to prompt the user. Revert that one call and replace the guard's brittle file:line whitelist with an inline 'noqa: subprocess-stdin' marker that travels with the code. --- agent/anthropic_adapter.py | 7 +++++-- scripts/check_subprocess_stdin.py | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/agent/anthropic_adapter.py b/agent/anthropic_adapter.py index cf22c2ab8a9..389b21831fb 100644 --- a/agent/anthropic_adapter.py +++ b/agent/anthropic_adapter.py @@ -1164,9 +1164,12 @@ def run_oauth_setup_token() -> Optional[str]: "Install it with: npm install -g @anthropic-ai/claude-code" ) - # Run interactively — stdin/stdout/stderr inherited so user can interact + # Run interactively — stdin/stdout/stderr inherited so the user can + # complete the OAuth login prompt. Must keep inherited stdin; the TUI-EOF + # concern does not apply to an interactive login the user explicitly + # invokes. noqa: subprocess-stdin try: - subprocess.run([claude_path, "setup-token"], stdin=subprocess.DEVNULL) + subprocess.run([claude_path, "setup-token"]) except (KeyboardInterrupt, EOFError): return None diff --git a/scripts/check_subprocess_stdin.py b/scripts/check_subprocess_stdin.py index ccec7a3bfcf..4d312a5949e 100644 --- a/scripts/check_subprocess_stdin.py +++ b/scripts/check_subprocess_stdin.py @@ -44,6 +44,13 @@ KNOWN_SAFE = { "plugins/security-guidance/patterns.py", # subprocess mentions are in reminder strings, not calls } +# Inline marker that exempts a single subprocess call from this check. +# Put it in a comment on (or within) the call when the process MUST inherit +# stdin — e.g. an interactive login the user explicitly invokes. Travels with +# the line, so it survives edits that shift line numbers (unlike a pinned +# file:line entry). +EXEMPT_MARKER = "noqa: subprocess-stdin" + # Directories to skip entirely. SKIP_DIRS = { "tests/", @@ -105,6 +112,14 @@ def find_subprocess_calls(content: str, filepath: str) -> list[dict]: if "input=" in call_text: break + # Inline exemption marker on the call itself or within + # the few comment lines immediately above it → the call + # intentionally inherits stdin. + window_start = max(0, i - 4) + preceding = "\n".join(lines[window_start:i]) + if EXEMPT_MARKER in call_text or EXEMPT_MARKER in preceding: + break + violations.append({ "file": filepath, "line": i + 1,