ITADN

Extension install fails with `Server returned 403` when an HTTP proxy denies the gallery host, even though the host is listed in `NO_PROXY` / `http.noProxy` (Positron Pro on Workbench)

#15177Openemcrisan 创建于 23 天前
bugsupportarea: extensions
E
emcrisancommented
## System details: #### Positron and OS details: ``` Positron Pro 2025.12.2 (build 5) Code - OSS Version: 1.106.0 Posit Workbench 2026.01.0+392.pro5 OS: RHEL 9.6 (x86_64), standalone VM, Local Job Launcher Session type: browser-based Positron Pro session (positron-server) ``` The behavior above was reported by the administrator of the affected deployment. We have not reproduced it on a Posit-side test system; the files involved appear unchanged between the tag matching this build and current `main`, but we have not verified a newer build empirically. #### Session details: Not interpreter-specific; occurs before any interpreter interaction, on a fresh session with no extensions installed. ## Describe the issue: In a Positron Pro session on Workbench, with `HTTP_PROXY`/`HTTPS_PROXY` present in the environment and a corporate proxy that returns **403** for the extension gallery host: - Browsing and searching the extension gallery **works**. - Installing any extension **fails immediately** with: ``` Server returned 403 at ExtensionGalleryServiceWithNoStorageService2.getManifest (installGalleryExtensions → checkAndGetCompatibleVersion → getManifest) ``` The gallery host is listed in `NO_PROXY`/`no_proxy` at the OS level, and `curl` from inside the same session honors that and reaches the gallery host successfully. Adding `http.noProxy` for the same host — both as an administrator-seeded default for all sessions and in individual user settings — does not change the behavior. The failure is deterministic: it recurs after a Workbench restart and in a brand-new session. ## Steps to reproduce the issue: Two parts: what the administrator actually did in the affected deployment, and a self-contained recipe we believe should reproduce it on a clean host. It is written from the reported symptoms plus source reading, and the outcomes in it are predictions, not observations. ### As reported in the affected deployment 1. Configure a self-hosted VS Code extensions gallery and point sessions at it with `EXTENSIONS_GALLERY` in `/etc/rstudio/launcher-env`. 2. Have all outbound traffic forced through a corporate proxy that returns 403 for that gallery host, with the proxy variables set system-wide and in the `rstudio-server` service environment, and the gallery host present in `NO_PROXY`/`no_proxy` at every layer. 3. Restart Workbench, open a fresh Positron Pro session, search the Extensions pane (returns results), then install an extension. Reported result: install fails immediately with the `Server returned 403` / `getManifest` error. Reported controls from the same host: `curl --noproxy '*'` to the gallery and asset URLs returns 200; the same `curl` forced through the proxy returns 403; a plain Node `https.get()` returns 200. Adding `http.noProxy` for the gallery host changed nothing. ### Self-contained recipe (untested by us) Needs one Linux host with Workbench + Positron Pro and outbound internet. Uses `open-vsx.org` as the gallery so no private infrastructure is involved. 1. Install a forward proxy that denies the gallery host and allows everything else: ```bash sudo dnf install -y squid sudo tee /etc/squid/squid.conf >/dev/null <<'EOF' http_port 3128 acl gallery dstdomain open-vsx.org http_access deny gallery http_access allow all EOF sudo systemctl enable --now squid ``` 2. Confirm the two control paths, which should show 200 direct and 403 through the proxy: ```bash curl -s -o /dev/null -w 'direct: %{http_code}\n' --noproxy '*' https://open-vsx.org/ curl -s -o /dev/null -w 'proxied: %{http_code}\n' -x http://localhost:3128 https://open-vsx.org/ ``` 3. Attempt an install with the gallery host present in `no_proxy`: ```bash env HTTP_PROXY=http://localhost:3128 HTTPS_PROXY=http://localhost:3128 \ NO_PROXY=open-vsx.org no_proxy=open-vsx.org \ /usr/lib/rstudio-server/bin/positron-server/bundled/bin/positron-server \ --install-extension redhat.vscode-yaml \ --extensions-dir /tmp/repro-exts --user-data-dir /tmp/repro-udd --log trace ``` Expected if this matches the reported behavior: the install fails carrying the proxy's 403, despite `no_proxy` covering the host. 4. Re-run the identical command with only `HTTP_PROXY`/`HTTPS_PROXY` removed, keeping `no_proxy`. Expected: the install succeeds. We chose the CLI form because `--install-extension` appears to construct the same `RequestService('remote')` and `ExtensionGalleryServiceWithNoStorageService` as the in-session install (`src/vs/server/node/remoteExtensionHostAgentCli.ts`), which would make it a smaller reproducer than driving the UI — but that equivalence is also inferred from source rather than tested, so the UI path in the reported-deployment section above is the authoritative symptom. ## Expected or desired behavior: Hosts listed in `NO_PROXY`/`no_proxy` (and/or in `http.noProxy`) are not routed through the proxy by the extension gallery request path — or, if that is not the intent, some supported way to exempt the gallery host, and documentation stating that the bypass variables do not apply here. Today an administrator whose proxy denies the gallery host appears to have no in-product configuration that makes gallery installs work. ## Were there any error messages in the UI, Output panel, or Developer Tools console? The UI error is the `Server returned 403` / `getManifest` message quoted above. A `Server` output-channel trace (`Developer: Set Log Level…` → `Server` → `Trace`) has been requested from the reporting administrator and is not yet captured. ## Observations that may be relevant Offered as triage context, not as a conclusion. Items 1-4 are reported by the administrator of the affected deployment; item 5 is our own reading of the source; items 6-7 are inferences from that reading and are not confirmed by observation. 1. **Search works while install fails** — search results render normally in the same session in which the install fails, suggesting the query and the install may not take the same network path. 2. **The same URLs are reachable from the same host** — `curl --noproxy '*'` and a plain Node `https.get()` both returned 200 for the gallery and asset URLs; only the in-product install fails. Forcing the same `curl` through the proxy returned 403, so the 403 text is consistent with what the proxy returns for that host. 3. **The bypass variables are present and effective for other clients** — `env | grep -i proxy` inside the session shows the gallery host in `no_proxy`, and `curl` in that same session honors it. 4. **`http.noProxy` made no difference** at either settings layer tried (administrator-seeded defaults for all sessions, and individual user settings). 5. **Source reading we did while triaging, which may or may not be pertinent:** - `src/vs/platform/request/node/proxy.ts` — `getSystemProxyURI()` reads `HTTP_PROXY`/`HTTPS_PROXY` (and lowercase) and `getProxyAgent()` returns an agent whenever a proxy URL is found; we did not find a bypass-list check on this path. - `src/vs/platform/request/node/requestService.ts` — `configure()` reads `http.proxy`, `http.proxyStrictSSL`, and `http.proxyAuthorization`; we did not find a read of `http.noProxy` here. - `git grep -i no_proxy -- src/` returns a single hit, in `src/vs/platform/windows/electron-main/windowImpl.ts` (Electron main process). `http.noProxy` additionally appears in `src/vs/workbench/api/node/proxyResolver.ts`, which covers extension-host requests. - `src/vs/server/node/serverServices.ts` registers `ExtensionGalleryServiceWithNoStorageService` and a `RequestService('remote', …)` in the server container. - These files look the same at `main` as at the tag matching the affected build, so we do not expect a newer Positron to behave differently — though we would be glad to be wrong about that. 6. **The failure appears to involve two requests, not one.** Consistent with `getAsset` retrying against the fallback asset URI when the primary request fails, and with the gallery in use publishing an identical fallback URI. Worth knowing when reading a trace log so the pair is not misread as two separate attempts. 7. **`RequestService.request()` resolves the login shell environment and merges it over `process.env`.** The administrator's attempt to clear the proxy variables only in Workbench's session-launch configuration did not change the behavior; we have not confirmed which layer re-supplied them, and this merge is one candidate. Mentioning it because it may affect how you reproduce. ## Questions for triage 1. Is the extension gallery request path intended to honor `NO_PROXY`/`no_proxy` or `http.noProxy`? If not, is that documented anywhere we should be pointing administrators at? 2. Is there a supported way today for an administrator to exempt the gallery host from the proxy for Positron Pro sessions, short of removing the proxy variables from the whole machine? 3. Are VS Code (code-server) sessions on Workbench expected to behave the same way? **Untested** — the reporting administrator has only exercised Positron Pro sessions. ## Possibly related - Upstream, appears to describe the same behavior in the same function, filed against VS Code Server: <https://github.com/microsoft/vscode/issues/147595> (open, Backlog). - Upstream feature request for a bypass setting: <https://github.com/microsoft/vscode/issues/200464> (open, Backlog). - Previous Positron issues in a similar class, all closed and all scoped to localhost rather than an arbitrary host, listed only for context: <https://github.com/posit-dev/positron/issues/5481>, <https://github.com/posit-dev/positron/issues/8426>, <https://github.com/posit-dev/positron/issues/11270>. ## Impact An enterprise deployment where all outbound traffic is forced through a corporate proxy that denies internal hosts. With a self-hosted extension gallery on such a host, no user can install any extension from the Extensions pane; the administrator's available options are all outside the product (proxy allowlist change, or pre-installing extensions from `.vsix`). The extension gallery in this case is housed in Posit Package Manager.
3 条评论