CoDA can run inside locked-down enterprise networks where outbound traffic is restricted to internal proxies, mirrors, and registries. This page documents the env-var contract that redirects every external reach.
The default behaviour is unchanged when no enterprise vars are set —
non-enterprise deployments continue to use public PyPI, npmjs.org, GitHub,
and claude.ai/install.sh.
This feature targets the proxy/registry lockdown profile:
- Outbound is allowed but only to internal JFrog Artifactory / Nexus / GitHub Enterprise.
- Public PyPI, npmjs.org, github.com, claude.ai are unreachable.
- TLS termination uses a corporate root CA.
Fully air-gapped deployments (zero egress except to DATABRICKS_HOST) need
binary vendoring, which is a separate follow-up feature.
-
Mirror the upstream binaries into your JFrog generic-local repo:
{generic-repo}/cli/cli/releases/download/v2.50.0/gh_2.50.0_linux_amd64.tar.gz {generic-repo}/databricks/cli/releases/download/v0.235.0/databricks_cli_0.235.0_linux_amd64.zip {generic-repo}/micro-editor/micro/releases/download/v2.0.13/micro-2.0.13-linux64-static.tar.gzConvention: keep the same path tail as
github.com/.../releases/download/.... No path rewriting needed. -
Configure your Databricks App's
app.yamlwith the env vars you need (see the table below). All are optional — set only what your environment requires. -
Run
make enterprise-doctoron the deployment host to confirm every configured target is reachable before deploying. -
Deploy as normal:
make deploy.
| Variable | Purpose | Default |
|---|---|---|
ENTERPRISE_MODE |
Master switch. When true, log a startup banner and warn on missing recommended mirrors. Behavioural overrides are still driven by the individual vars below — this flag is for diagnostics. |
unset |
HTTPS_PROXY / HTTP_PROXY / NO_PROXY |
Corporate egress proxy. Honoured natively by curl, uv, npm, git, requests. |
unset |
REQUESTS_CA_BUNDLE / NODE_EXTRA_CA_CERTS / SSL_CERT_FILE |
Corporate root CA bundle path (PEM). | unset |
UV_DEFAULT_INDEX |
Internal PyPI proxy URL, e.g. https://jfrog/api/pypi/pypi-virtual/simple/. |
public PyPI |
UV_HTTP_TIMEOUT |
Larger timeout for slow proxies. | uv default |
UV_INDEX_<name>_USERNAME / UV_INDEX_<name>_PASSWORD |
uv-native auth for named indexes. | unset |
NPM_REGISTRY |
Internal npm registry URL. Written to ~/.npmrc. |
npmjs.org |
NPM_TOKEN |
Bearer token for NPM_REGISTRY. Written to ~/.npmrc as //host/:_authToken. |
unset |
GITHUB_API_BASE |
Replacement for https://api.github.com (GitHub Enterprise or JFrog API mirror). |
api.github.com |
GITHUB_RELEASE_MIRROR |
Replacement for https://github.com for release downloads. Path tail preserved — point at a JFrog generic-repo. |
github.com |
CLAUDE_INSTALLER_URL |
Override https://claude.ai/install.sh. |
upstream |
HERMES_PIP_URL |
Override git+https://github.com/NousResearch/hermes-agent.git. Can be a mirrored git URL or an internal-index package spec. |
upstream git URL |
DEEPWIKI_MCP_URL / EXA_MCP_URL |
Override or set empty to omit these MCP servers entirely. | upstream URLs |
Browser terminals receive only reviewed non-secret network settings. URL-valued variables with embedded userinfo or malformed ports are omitted, and credential-shaped environment names are excluded as a defense-in-depth check. App-level setup processes may still use their configured credentials; those values are not inherited by browser PTYs.
GITHUB_RELEASE_MIRROR must serve assets at the same path tail as github.com:
{mirror}/{owner}/{repo}/releases/download/{tag}/{asset}
So https://github.com/cli/cli/releases/download/v2.50.0/gh.tar.gz becomes
{mirror}/cli/cli/releases/download/v2.50.0/gh.tar.gz.
In JFrog Artifactory, a Generic repository or a Generic Remote repo proxying github.com works without configuration.
GITHUB_API_BASE replaces the hostname and prefix:
https://api.github.com/repos/cli/cli/releases/latest
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
path preserved
For GitHub Enterprise, the base path is typically /api/v3:
https://ghe.example.com/api/v3 — install scripts will hit
https://ghe.example.com/api/v3/repos/cli/cli/releases/latest.
~/.npmrc is written automatically at app startup when NPM_REGISTRY is set.
Format:
registry=https://jfrog.example.com/api/npm/npm-virtual/
//jfrog.example.com/:_authToken=<NPM_TOKEN>
always-auth=true
uv reads UV_DEFAULT_INDEX from the environment. No file written; configuration
is process-environment only.
For named-index auth (when your proxy needs HTTP basic auth):
- name: UV_DEFAULT_INDEX
value: https://jfrog.example.com/api/pypi/pypi-virtual/simple/
- name: UV_INDEX_INTERNAL_USERNAME
value: svc-coda
- name: UV_INDEX_INTERNAL_PASSWORD
value: <secret>env:
# Master switch — enables startup banner and missing-mirror warnings.
- name: ENTERPRISE_MODE
value: "true"
# Corporate egress proxy.
- name: HTTPS_PROXY
value: http://proxy.corp.example.com:3128
- name: NO_PROXY
value: localhost,127.0.0.1,.corp.example.com
# Corporate root CA.
- name: REQUESTS_CA_BUNDLE
value: /etc/ssl/certs/corp-root.pem
- name: NODE_EXTRA_CA_CERTS
value: /etc/ssl/certs/corp-root.pem
# Internal PyPI proxy.
- name: UV_DEFAULT_INDEX
value: https://jfrog.example.com/api/pypi/pypi-virtual/simple/
# Internal npm registry.
- name: NPM_REGISTRY
value: https://jfrog.example.com/api/npm/npm-virtual/
- name: NPM_TOKEN
value: <use a Databricks secret reference here>
# GitHub mirror (releases + API).
- name: GITHUB_RELEASE_MIRROR
value: https://jfrog.example.com/artifactory/github-mirror
- name: GITHUB_API_BASE
value: https://ghe.example.com/api/v3
# Drop the public MCP servers from agent configs.
- name: DEEPWIKI_MCP_URL
value: ""
- name: EXA_MCP_URL
value: ""Your app-level proxy needs credentials. Include them in the URL:
HTTPS_PROXY=http://user:pass@proxy.corp.example.com:3128. The startup banner
masks the password in logs. Credential-bearing proxy URLs are intentionally
excluded from browser-terminal environments.
The corporate root CA isn't in the trust store. Set
REQUESTS_CA_BUNDLE (Python), NODE_EXTRA_CA_CERTS (npm/node), and
SSL_CERT_FILE (catch-all) to a PEM bundle that includes your corp root.
NPM_TOKEN is missing, wrong, or expired. Confirm with:
curl -H "Authorization: Bearer $NPM_TOKEN" "$NPM_REGISTRY"Check that UV_DEFAULT_INDEX ends in /simple/ (the PEP 503 path). JFrog
typically exposes PyPI as /api/pypi/<repo>/simple/.
GITHUB_API_BASE is unreachable or doesn't proxy the GitHub API. For
JFrog-style mirrors, you may need to set the base to point at a service
that proxies api.github.com, or pin the version manually in the install
script.
pyproject.toml currently pins requests to a direct GitHub source:
[tool.uv.sources]
requests = { git = "https://github.com/psf/requests", rev = "v2.33.0" }This bypasses the PyPI proxy and breaks in enterprise environments. Two workarounds for customers:
- Mirror
psf/requestsin your internal git and override the URL with apyproject.tomlpatch in your deployment overlay. - Remove the override entirely if your internal PyPI proxy has
requests>=2.33.0available.
This is tracked as a follow-up — the override exists for transient Databricks internal-proxy gaps, and will be removed once those gaps close.
Run make enterprise-doctor from the deployment host:
$ make enterprise-doctor
enterprise_config: effective settings
ENTERPRISE_MODE=true
HTTPS_PROXY=http://proxy.corp.example.com:3128
...
[PASS] NPM_REGISTRY https://jfrog.example.com/api/npm/npm-virtual/ HTTP 200
[PASS] UV_DEFAULT_INDEX https://jfrog.example.com/api/pypi/pypi-virtual/simple/ HTTP 200
[PASS] GITHUB_RELEASE_MIRROR https://jfrog.example.com/artifactory/github-mirror HTTP 200
Any FAIL line is something your network team needs to fix before deployment.
CoDA's enterprise mode shifts one trust boundary materially: the operator gains a new control point — the ability to redirect every external package install to a mirror they control. The following limits are deliberate and worth understanding before deploying into a regulated environment.
| Assumption | What relies on it |
|---|---|
| The operator's mirror serves correct artifacts | All CLI installs; no checksum/signature verification is performed |
REQUESTS_CA_BUNDLE (when set) is a legitimate corporate root CA, not an attacker-controlled CA |
TLS validation on every outbound call from the app, including PAT-bearing calls to the Databricks workspace API |
The operator who controls app.yaml is trusted |
Mirror URLs, installer URLs, MCP override URLs are not allow-listed — any URL the operator sets is accepted (after a shell-safety regex check) |
The Hermes upstream commit pin in enterprise_config.py:DEFAULT_HERMES_PIN_SHA was reviewed when it was set |
uv tool install pulls Hermes from this specific SHA, mitigating the "force-push to default branch" attack — but the pin must be rotated deliberately on each CoDA release |
- No checksum verification on mirror-served binaries. Claude installer script, GitHub release tarballs (gh, micro, databricks CLI), and npm packages are pulled with no SHA256 manifest check. The mirror operator could swap a binary at any time.
- No CA bundle pinning. If
REQUESTS_CA_BUNDLEis set, the app trusts whatever CA the operator points at. This is by design (needed for corporate TLS interception) but means an attacker who can writeapp.yamlcan MITM every outbound TLS call including PAT-bearing API calls to the workspace. - No mirror allow-listing.
GITHUB_RELEASE_MIRROR,NPM_REGISTRY,CLAUDE_INSTALLER_URLetc. accept any URL. The shell-safety regex inenterprise_config._validate_url()rejects values containing shell metacharacters, but it does not restrict by domain. - No fail-closed on mirror unreachability at runtime.
bootstrap()validates URL shape and logs a banner, but does not probe mirror reachability. Runmake enterprise-doctorbefore deploy to surface reachability failures early.
If you are filing a Security Design Review (SDR) for a CoDA deployment, these are the questions worth raising with ProdSec:
- Should mirror-served binaries require SHA256 verification? Today the enterprise mode trusts the mirror entirely. Adding verification would require customers to publish a manifest alongside their mirror.
- Should we add mirror allow-listing (e.g., reject URLs whose host
isn't under
*.jfrog.io/ the operator-declared internal domains)? - Should the CA bundle be pinned to a known fingerprint rather than accepting whatever the operator provides?
- Should the Hermes git pin be enforced in CI (e.g., reject PRs that bump the SHA without a security review note)?
- Should the content-filter proxy at localhost:4000 use an auth token or Unix socket rather than being unauthenticated?
These are deliberate trade-offs, not bugs — but they are limits of the current threat model and worth surfacing to anyone who has to sign off on an enterprise deployment.