Skip to content
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `APM_EXTRA_CA_BUNDLE` now adds an enterprise CA bundle without replacing
existing trust. APM applies it to parent Requests and truststore-backed Python
HTTPS, snapshots `certifi` plus the extra CA for Python/Requests children,
refreshes the managed `llm` bootstrap, and propagates the validated extra
snapshot to Node without overwriting an explicit `NODE_EXTRA_CA_CERTS`.
(closes #2034)
Comment thread
TameTheGame marked this conversation as resolved.
Outdated
- gh-aw's shared APM import now supports `token-source: github-token`; after consumers re-vendor the workflow, its read-only current-repository identity can fetch same-repository private packages, while `cascade` remains the default and cross-repository packages still require a dedicated token or GitHub App. (#2706)
- OpenAPM v0.1 adds `req-pl-018` for dependency-policy identity casing and amends `req-rs-016` clause (3), the Section 6.4 merge rules, and the Section 6.5 pattern grammar so repository identity and policy matching cannot diverge; Section 11.2 item 6 now requires the per-host case rule in `CONFORMANCE.md`. (#2706)

Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/enterprise/registry-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ and `apm cache clean`.
| `ERROR: ... locked to direct VCS hosts` | Lockfile predates the proxy | `apm install --update` |
| HTTP 401/403 from the proxy | Missing or invalid `PROXY_REGISTRY_TOKEN` | Verify the token has read on the upstream repo path |
| `git clone` hangs through the proxy | `HTTPS_PROXY` not set in the env that runs `git` | Export it in the shell that invokes `apm install`; CI secrets often miss this |
| `TLS verification failed` | Corporate proxy CA is not trusted by the OS store | Install the CA into the OS trust store, or set `REQUESTS_CA_BUNDLE`; see [SSL / TLS issues](../../troubleshooting/ssl-issues/) |
| `TLS verification failed` | Corporate proxy CA is not trusted by the OS store | Install the CA into the OS trust store, or set additive `APM_EXTRA_CA_BUNDLE` to retain public trust. Use `REQUESTS_CA_BUNDLE` only for intentional full replacement; see [SSL / TLS issues](../../troubleshooting/ssl-issues/) |
| `DeprecationWarning: ARTIFACTORY_BASE_URL is deprecated` | Legacy env names | Rename to `PROXY_REGISTRY_*` |
| Plaintext-token warning on proxy startup | Token sent over `http://` | Use `https://`, or set `PROXY_REGISTRY_ALLOW_HTTP=1` if the link is internal-only |
| `Invalid zip archive` with a body that starts `<!DOCTYPE html>` and is ~17KB | Upstream returned a sign-in page; proxy cached the HTML | Configure upstream credentials on the registry remote, purge the cache, then refetch |
Expand Down
17 changes: 11 additions & 6 deletions docs/src/content/docs/enterprise/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,17 @@ APM has no runtime footprint. Once `apm install` or `apm compile` completes, the

APM keeps certificate verification enabled for every HTTPS request. Python-based paths verify against the operating-system trust store by default through `truststore`, so corporate roots trusted by `git` and `curl` are also trusted by `apm install`.

- `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE` replace the OS store with an explicitly selected PEM bundle for APM's HTTP layer.
- `APM_DISABLE_TRUSTSTORE=1` restores the previous bundled-`certifi` behavior.
- If `truststore` is unavailable or injection fails, APM falls back to `certifi`; it does not disable verification.
- The Python-based `llm` runtime receives a shipped, self-contained `.pth` bootstrap in its managed virtual environment. The bootstrap imports only `truststore`; it does not execute dependency-provided package content.

Node-based (Copilot) and Rust-based (Codex) child runtimes retain their own trust configuration for now. See [SSL / TLS issues](../../troubleshooting/ssl-issues/) for scope, overrides, and recovery steps.
- Trust selection is deterministic: `REQUESTS_CA_BUNDLE`, then `CURL_CA_BUNDLE`, `APM_DISABLE_TRUSTSTORE`, `APM_EXTRA_CA_BUNDLE`, the OS trust store, and finally bundled `certifi` as the Requests verification fallback.
- `APM_DISABLE_TRUSTSTORE=1` disables APM's OS/additive propagation. It does not unset a separately configured Requests/curl replacement bundle.
- `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE` replace the OS store with an explicitly selected PEM bundle for APM's Python HTTP layer.
- `APM_EXTRA_CA_BUNDLE` is additive. Truststore-backed parent contexts retain native OS roots and add certificates from the selected PEM bundle; the parent Requests fallback retains bundled `certifi` roots plus those certificates.
- Before `apm run` launches a child, APM copies the validated CA bytes into an APM-owned, per-process directory beneath the user's `~/.apm/tls/` data directory. Python/Requests children receive a merged `certifi`-plus-extra snapshot, and the source file cannot change their trust after validation. The per-process directory is removed when the APM process exits normally.
- The Python-based `llm` runtime receives a shipped, self-contained `.pth` bootstrap in its managed virtual environment. APM refreshes the bootstrap before a managed `llm` launch, so an existing runtime receives trust updates after APM is upgraded. The bootstrap imports only `truststore`; it does not execute dependency-provided package content.
- For Node-based children, APM derives `NODE_EXTRA_CA_CERTS` from the validated extra-only snapshot. An explicitly set `NODE_EXTRA_CA_CERTS` remains authoritative and is never overwritten.
- A missing, unreadable, empty, non-regular, oversized, non-ASCII, malformed, or private-key-bearing additive bundle is a configuration error. APM rejects private material before snapshotting and fails closed rather than ignoring the bundle or disabling verification.
- If `truststore` is unavailable or injection fails, the APM parent's Requests-based HTTPS falls back to `certifi`; when an additive bundle is selected, it remains additive to that fallback. Parent stdlib `urllib` callers do not consult the Requests fallback bundle. A managed Python child without `truststore` likewise retains `certifi` plus the extra CA for Requests-based HTTPS. APM never disables verification.

Git remains separately configured through its own trust settings. Rust-based Codex retains its runtime-owned trust configuration. See [SSL / TLS issues](../../troubleshooting/ssl-issues/) for scope, overrides, and recovery steps.

## Dependency provenance

Expand Down
14 changes: 10 additions & 4 deletions docs/src/content/docs/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ Controls how APM clones packages and enumerates refs on Git hosts. These setting

## TLS trust

APM verifies HTTPS against the operating-system trust store by default. For the full troubleshooting flow, see [SSL / TLS issues](../../troubleshooting/ssl-issues/).
APM verifies HTTPS against the operating-system trust store by default, with bundled `certifi` as the Requests fallback. Use `APM_EXTRA_CA_BUNDLE` to add an enterprise CA to whichever default is active instead of replacing it. For the full troubleshooting flow, see [SSL / TLS issues](../../troubleshooting/ssl-issues/).

| Variable | Purpose | Default | Notes |
|---|---|---|---|
| `REQUESTS_CA_BUNDLE` | PEM bundle for APM's Python HTTP requests. | unset | Explicit override; wins over OS trust-store injection. Use for a per-shell corporate CA bundle. |
| `CURL_CA_BUNDLE` | PEM bundle fallback honoured by `requests`. | unset | Explicit override; wins over OS trust-store injection when `REQUESTS_CA_BUNDLE` is unset. |
| `APM_DISABLE_TRUSTSTORE` | Set to `1` (or `true`/`yes`/`on`) to disable OS trust-store injection. | unset | Escape hatch that restores the legacy bundled-`certifi` verification path. |
| `APM_DISABLE_TRUSTSTORE` | Set to `1` (or `true`/`yes`/`on`) to disable OS trust-store injection. | unset | Disables APM's OS and additive trust propagation. It does not unset an independently configured `REQUESTS_CA_BUNDLE` or `CURL_CA_BUNDLE`; those explicit replacements remain authoritative. |
| `REQUESTS_CA_BUNDLE` | PEM bundle for APM's Python HTTP requests. | unset | Explicit replacement override; wins over `CURL_CA_BUNDLE`, additive trust, and the OS trust store. |
| `CURL_CA_BUNDLE` | PEM bundle fallback honoured by `requests`. | unset | Explicit replacement override when `REQUESTS_CA_BUNDLE` is unset; wins over additive trust and the OS trust store. |
| `APM_EXTRA_CA_BUNDLE` | Certificate-only PEM bundle to add to APM's normal TLS trust. | unset | Additive: truststore-backed parent contexts retain OS roots, the parent Requests fallback and Python/Requests children receive `certifi` plus the extra CA, and APM derives `NODE_EXTRA_CA_CERTS` for Node children unless that native variable is already set. A selected bundle that is missing, unreadable, empty, non-regular, over 8 MiB, non-ASCII, malformed, or contains a private-key block fails closed. |
| `NODE_EXTRA_CA_CERTS` | PEM bundle added by Node.js to its normal roots. | unset | Native Node override. APM preserves an explicitly set value instead of replacing it with `APM_EXTRA_CA_BUNDLE`. |

Trust resolution is ordered: `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, `APM_DISABLE_TRUSTSTORE`, `APM_EXTRA_CA_BUNDLE`, the OS trust store, then bundled `certifi` as the final Requests fallback. The `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE` settings replace normal Requests trust; `APM_DISABLE_TRUSTSTORE` suppresses OS/additive propagation without deleting those replacements; `APM_EXTRA_CA_BUNDLE` augments the selected defaults. APM derives child settings only when the additive bundle wins this precedence.

See [runtime coverage and limitations](../../troubleshooting/ssl-issues/#runtime-coverage) for Python, Node, Git, and Rust behavior, fallback trust, and snapshot lifetime.

## Registry (MCP and proxy)

Expand Down
6 changes: 4 additions & 2 deletions docs/src/content/docs/troubleshooting/common-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,14 @@ See also: [Install failures](../install-failures/)
TLS verification failed -- APM uses the system trust store by default.
If you're behind a corporate proxy or firewall, make sure your
organisation's CA is installed in the OS trust store, or set
REQUESTS_CA_BUNDLE to a readable PEM bundle and retry.
APM_EXTRA_CA_BUNDLE to a readable PEM bundle to add it while retaining
public trust. Use REQUESTS_CA_BUNDLE only to replace the complete
Python trust set.
```

Cause: Python's TLS stack rejected the server certificate. Almost always a corporate proxy doing TLS interception with a CA that is not in the system trust store.

Fix: install the corporate CA into the OS trust store and retry. For a per-shell override, export `REQUESTS_CA_BUNDLE=/path/to/corporate-ca.pem`; `SSL_CERT_FILE` alone is not a reliable requests override. Do not disable TLS verification.
Fix: install the corporate CA into the OS trust store and retry. For a per-shell additive setting that retains public trust, export `APM_EXTRA_CA_BUNDLE=/path/to/corporate-ca.pem`. Use `REQUESTS_CA_BUNDLE` only when you intend to replace the complete Python trust set; `SSL_CERT_FILE` alone is not a reliable requests override. Do not disable TLS verification.

See also: [SSL issues](../ssl-issues/)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ For end-to-end auth setup see [Authentication](../../getting-started/authenticat
[!] TLS verification failed
```

APM verifies HTTPS against the OS trust store by default. Behind a corporate proxy, install your org's CA into the OS trust store; for a per-shell override, set `REQUESTS_CA_BUNDLE` to a readable PEM bundle. Full walkthrough: [SSL / TLS issues](../ssl-issues/).
APM verifies HTTPS against the OS trust store by default. Behind a corporate proxy, install your org's CA into the OS trust store; for a per-shell additive setting that retains public trust, set `APM_EXTRA_CA_BUNDLE` to a readable PEM bundle. Use `REQUESTS_CA_BUNDLE` only when you intend to replace the complete Python trust set. Full walkthrough: [SSL / TLS issues](../ssl-issues/).

### Timeouts and proxies

Expand Down
Loading
Loading