From ca22f46ca3341a3b115c4326f69246e17b364899 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Sat, 17 Oct 2026 04:55:38 +0200 Subject: [PATCH] fix(runtime): keep APM truststore bootstrap out of ensurepip on llm re-setup Re-running `apm runtime setup llm` over an existing venv recreates it while APM's `_apm_tls.pth` bootstrap is installed. ensurepip launches its bundled pip via `python -c runpy...`, which the bootstrap's pip detection misses, so truststore is injected into ssl; pip's vendored truststore then probes `create_default_context().wrap_bio(...)` and truststore 0.10.5 rejects it ("check_hostname requires server_hostname"). Run the pip bootstrap with APM_DISABLE_TRUSTSTORE=1 (honored by every shipped bootstrap); pip still verifies against the OS store through its own vendored truststore. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 761bf207-57da-41d0-bd3f-ffecbb97b83a --- scripts/runtime/setup-llm.ps1 | 11 +++++++++-- scripts/runtime/setup-llm.sh | 6 ++++-- tests/integration/test_tls_r3_verify.py | 10 ++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/scripts/runtime/setup-llm.ps1 b/scripts/runtime/setup-llm.ps1 index 0cd2a78dd3..1c18a93379 100644 --- a/scripts/runtime/setup-llm.ps1 +++ b/scripts/runtime/setup-llm.ps1 @@ -26,9 +26,16 @@ function Install-Llm { exit 1 } - # Create virtual environment + # Create virtual environment. A re-run over an existing venv must not let + # APM's truststore .pth bootstrap inject into ensurepip's bundled pip. Write-Info "Creating Python virtual environment for LLM..." - python -m venv $llmVenv + $previousDisable = $env:APM_DISABLE_TRUSTSTORE + $env:APM_DISABLE_TRUSTSTORE = "1" + try { + python -m venv $llmVenv + } finally { + $env:APM_DISABLE_TRUSTSTORE = $previousDisable + } $pipExe = Join-Path (Join-Path $llmVenv "Scripts") "pip.exe" $llmExe = Join-Path (Join-Path $llmVenv "Scripts") "llm.exe" diff --git a/scripts/runtime/setup-llm.sh b/scripts/runtime/setup-llm.sh index 60d8649ff0..4d20fec32c 100755 --- a/scripts/runtime/setup-llm.sh +++ b/scripts/runtime/setup-llm.sh @@ -43,7 +43,9 @@ setup_llm() { # Create virtual environment for LLM. Bootstrap pip as a separate step: # `python3 -m venv` hides ensurepip's output, so a failure would only - # report "exit status 1" without the reason. + # report "exit status 1" without the reason. A re-run over an existing venv + # must not let APM's truststore .pth bootstrap inject into ensurepip's + # bundled pip, whose vendored truststore rejects an already-injected ssl. local python3_bin python3_bin="$(command -v python3)" log_info "Creating Python virtual environment for LLM (using $python3_bin)..." @@ -51,7 +53,7 @@ setup_llm() { log_error "Could not create the LLM virtual environment at $llm_venv." exit 1 fi - if ! "$llm_venv/bin/python" -m ensurepip --upgrade --default-pip; then + if ! APM_DISABLE_TRUSTSTORE=1 "$llm_venv/bin/python" -m ensurepip --upgrade --default-pip; then log_error "Could not bootstrap pip into $llm_venv (python3: $python3_bin)." exit 1 fi diff --git a/tests/integration/test_tls_r3_verify.py b/tests/integration/test_tls_r3_verify.py index 57eed8e7d9..3a76bd3300 100644 --- a/tests/integration/test_tls_r3_verify.py +++ b/tests/integration/test_tls_r3_verify.py @@ -309,6 +309,16 @@ def spy(target, data): ) +def test_setup_llm_pip_bootstrap_skips_apm_truststore_injection(): + """Re-running setup over a bootstrapped venv must not inject into ensurepip's pip.""" + root = _repo_root() + sh = (root / "scripts" / "runtime" / "setup-llm.sh").read_text(encoding="utf-8") + ps1 = (root / "scripts" / "runtime" / "setup-llm.ps1").read_text(encoding="utf-8") + + assert 'APM_DISABLE_TRUSTSTORE=1 "$llm_venv/bin/python" -m ensurepip' in sh + assert '$env:APM_DISABLE_TRUSTSTORE = "1"' in ps1 + + # --------------------------------------------------------------------------- # # V4 (M1): runtime setup scripts install truststore best-effort + pinned # --------------------------------------------------------------------------- #