CLI version check timeout can hang indefinitely while waiting for termination
Summary
SubprocessCLITransport._check_claude_version() has a two-second timeout, but its cleanup performs an unbounded process wait outside that timeout.
Affected code
src/claude_agent_sdk/_internal/transport/subprocess_cli.py:1024-1065
Current behavior
The anyio.fail_after(2) scope covers process creation and reading the version output. In finally, the code calls:
version_process.terminate()
await version_process.wait()The wait is outside the timeout and there is no kill fallback. If the executable ignores or fails to respond to SIGTERM, wait() never returns.
Exceptions are also suppressed, so this path does not expose useful diagnostic information.
Why this matters
The version check runs during transport connection. A stale, wrapped, broken, or malicious executable at the configured CLI path can therefore hang every SDK connection indefinitely despite the documented two-second timeout.
Expected behavior
The entire probe, including process cleanup and reaping, should have a finite upper bound.
Possible fix
Use bounded subprocess shutdown:
- Terminate the process.
- Wait for a short bounded interval.
- Kill it if still running.
- Await/reap it under another bounded interval.
- Preserve cancellation semantics while suppressing only expected cleanup errors.
A regression test can use a mocked process whose first wait() does not complete and assert that kill() is called and connection continues within the deadline.
This follow-up was mentioned as out of scope in PR #1082, but I found no dedicated issue or active implementation.
Environment
- Repository revision: current
mainaudit at SDK version 0.2.128 - Bundled CLI version: 2.1.220
- Python test suite: 1,291 passed, 5 skipped
- Ruff and mypy: clean
I searched the existing issues and pull requests using the affected symbols and behavior before filing this.
Source: anthropics/claude-agent-sdk-python