fix(mcp): run OSV malware preflight off the event loop with a bounded timeout (#29184)

During stdio MCP server startup, _run_stdio (an async method) called the
synchronous check_package_for_malware() inline. That makes a blocking
urllib HTTPS POST to api.osv.dev whose own timeout doesn't reliably cover a
stalled SSL handshake, so an intermittent network issue froze the entire
asyncio event loop for up to ~120s — blowing past the TUI/gateway's 15s
startup budget and showing "gateway startup timeout".

Run the check via asyncio.to_thread (off the loop) AND bound it with
asyncio.wait_for(timeout=_OSV_MALWARE_CHECK_TIMEOUT_S=12s). The malware check
is fail-open, so on timeout we log and proceed rather than blocking startup.

Salvaged from #29190 by @qdaszx (re-applied on current main — the call site
moved since the PR was opened), combining the to_thread approach also proposed
in #29192 by @ygd58. Two load-bearing tests: event-loop-not-blocked-during-
check and timeout-fails-open — both mutation-verified to fail against the old
inline blocking call.

Closes #29184.

Co-authored-by: ygd58 <buraysandro9@gmail.com>
This commit is contained in:
qdaszx 2026-06-25 02:37:21 +05:30 committed by kshitijk4poor
parent 7d2c1f3f84
commit 6305ac0e4b
3 changed files with 110 additions and 2 deletions

View file

@ -65,6 +65,7 @@ AUTHOR_MAP = {
"96944678+sweetcornna@users.noreply.github.com": "sweetcornna", # cron ticker-liveness salvage co-author (#33849)
"izumi0uu@gmail.com": "izumi0uu", # PR #49544 salvage (native rich reply echo; #49534)
"dev@pixlmedia.no": "texhy", # PR #27435 salvage (few-but-huge preflight compression gate; #27405)
"qdaszx@naver.com": "qdaszx", # PR #29190 salvage (non-blocking OSV malware preflight; #29184)
"w31rdm4ch1n3z@protonmail.com": "w31rdm4ch1nZ",
"xtpeeps@gmail.com": "x7peeps",
"ahmad@madsgency.com": "ahmadashfq",