July 2026
This section covers everything you need to know to upgrade from 1.25.0 to 1.26.0.
This release adds a preflight validator to build_and_run.sh that refuses to start the stack when secrets are left at known-weak defaults. This affects LOCAL Docker Compose deployments only (e.g. a local box, EC2, or macOS running build_and_run.sh). Managed deployments are NOT affected - AWS ECS/DocumentDB and EKS/Helm supply their own secrets and do not run this preflight.
If you are a local Docker Compose user upgrading an existing deployment, build_and_run.sh will now fail with:
ERROR: DOCUMENTDB_PASSWORD is set to the known-weak default 'admin'.
ERROR: OPENBAO_TOKEN is set to the known-weak default 'dev-root-token'.
You must set strong values in .env. The two secrets are handled differently:
- OpenBao token (
OPENBAO_TOKEN) - the dev OpenBao container runs in-memory and is recreated on every restart, so there is no stored data to preserve. Just set a strong value (openssl rand -hex 32) in.env. Any previously vaulted egress credentials are re-established by reconnecting accounts after startup. - MongoDB password (
DOCUMENTDB_PASSWORD) - your existingmongodb-datavolume already holds a user created with the OLD password. MongoDB only creates that user on first boot, so changing.envalone does NOT update the stored user and will lock the app out of your existing data (registered servers/agents). You must rotate the stored user's password in place first, then set the same value in.env.
Full step-by-step instructions (including macOS sed variants, verification, and troubleshooting) are in the new FAQ:
If you do not need to preserve local data, you can instead recreate the MongoDB volume - see How do I migrate an existing local MongoDB to authenticated mode?.
Related hardening in this release that local Docker Compose users should be aware of:
- MongoDB now runs with authentication by default in
docker-compose.yml(--auth+ a keyfile-init helper). Fresh installs create the root user fromDOCUMENTDB_USERNAME/DOCUMENTDB_PASSWORDon first boot;build_and_run.shauto-generates a strongDOCUMENTDB_PASSWORDwhen it is unset (#1386). - Non-front-door Compose ports are now loopback-bound (
127.0.0.1) by default; only the nginx front door (80/443) is published on all interfaces. Override withHOST_BIND_IP=0.0.0.0if you deliberately need LAN access (#1376). - Keycloak realm setup uses
sslRequired=external(notnone). The orphaneddisable-ssl.shwas removed and the setup guides were corrected (#1380, #1384).
The weak-secret preflight does not run on EKS, but there are two required upgrade actions:
- New
openbaosubchart dependency. The stack chart (charts/mcp-gateway-registry-stack/Chart.yaml) now declares anopenbaodependency (condition: openbao.enabled) for the per-user egress credential vault. You must runhelm dependency build/helm dependency updatebeforehelm upgrade(see Upgrade Instructions), or the packaged subcharts will be stale. Many other subchart templates/values also changed this release, so this is required regardless. - New required value
egressAuth.markerSecretfor standalone deployments. The chart now rendersAUTH_SERVER_NGINX_MARKER_SECRETvia{{ required ... }}, so a standalone install/upgrade fails to render unlessegressAuth.markerSecretis set to a strong random value (identical across auth-server and registry). It guards all mcp-proxy token minting and is not egress-specific. Set it in your values before upgrading.
No mandatory new variables: the egress credential vault is off by default (egress_auth_enabled = false) and every new variable (cors_allowed_origins, mcp_proxy_timeout, the egress_* family) has a default. Two things to know:
- If you enable the egress vault (
egress_auth_enabled = true), ECS uses AWS Secrets Manager as the backend and the registry task role is granted scopedsecretsmanager+ KMS access underegress_secrets_manager_path_prefix. Set theegress_*variables accordingly (seeterraform/aws-ecs/terraform.tfvars.example). egress_nginx_marker_secretis auto-generated into Secrets Manager when left empty; set it only to pin a specific value. (ECS supplies this automatically, unlike the Helm standalone path which requires it explicitly.)
| Variable | Default | Description |
|---|---|---|
EGRESS_AUTH_ENABLED |
false |
Enable the per-user egress credential vault (third-party OBO). |
SECRET_STORE_BACKEND |
openbao |
Secret store for per-user egress tokens: secrets-manager or openbao. |
OPENBAO_ADDR |
http://openbao:8200 |
OpenBao backend address. |
OPENBAO_TOKEN |
(required, no default) | OpenBao token. The preflight rejects the old dev-root-token. |
OPENBAO_NAMESPACE |
(empty) | OpenBao namespace (enterprise/HCP). |
OPENBAO_KV_MOUNT |
secret |
KV v2 mount path. |
OPENBAO_AUTH_METHOD |
token |
OpenBao auth method (token for Compose; kubernetes for EKS). |
OPENBAO_ROLE |
(empty) | OpenBao role for kubernetes auth. |
EGRESS_OAUTH_CALLBACK_BASE_URL |
(empty) | Base URL for the egress OAuth callback. |
EGRESS_TOKEN_REFRESH_SKEW_SECONDS |
300 |
Refresh egress tokens this many seconds before expiry. |
EGRESS_STATE_TTL_SECONDS |
600 |
TTL for the egress OAuth state parameter. |
SECRETS_MANAGER_PATH_PREFIX |
mcp/egress |
Path prefix for the AWS Secrets Manager backend. |
SECRETS_MANAGER_KMS_KEY_ID |
(empty) | Optional KMS key for the Secrets Manager backend. |
AWS_SECRETS_REGION |
(empty) | Region for the Secrets Manager backend (falls back to AWS_REGION). |
CORS_ALLOWED_ORIGINS |
(empty) | Exact allowlist of browser origins for credentialed CORS (fail-closed). |
MCP_PROXY_TIMEOUT |
30 |
Upstream read timeout (seconds) for the MCP proxy hop; supports long-running tool calls. |
AUTH_SERVER_NGINX_MARKER_SECRET |
(auto-generated) | Shared marker secret guarding mcp-proxy token minting; build_and_run.sh generates it if empty. |
DOCUMENTDB_PASSWORD |
(required, no default) | MongoDB/DocumentDB password. The preflight rejects admin; build_and_run.sh generates a strong value when unset. |
SECRET_KEY |
(auto-generated) | Session-signing key; enforced minimum length. build_and_run.sh generates it if empty. |
PF_ADMIN_PASS |
(placeholder) | PingFederate admin password; the shipped placeholder is rejected. |
cd mcp-gateway-registry
git pull origin main
git checkout 1.26.0
# REQUIRED (local Docker Compose upgrades): set strong secrets before starting.
# OpenBao is in-memory (no data to preserve): set a strong OPENBAO_TOKEN in .env.
# MongoDB: rotate the stored password IN PLACE, then set it in .env -- otherwise
# you lose access to your existing data. Full steps:
# docs/faq/rotate-mongodb-and-openbao-secrets.md
# Review new env vars in .env.example and update your .env, then:
./build_and_run.shcd mcp-gateway-registry
git pull origin main
git checkout 1.26.0
# REQUIRED: chart files changed in this release, so rebuild packaged subcharts.
cd charts/mcp-gateway-registry-stack
helm dependency build
helm dependency update
# Update values.yaml (new egress-vault / OpenBao settings) then upgrade:
helm upgrade mcp-gateway . -f your-values.yamlThe weak-secret preflight is a build_and_run.sh check and does not run on EKS. Helm/EKS deployments supply DOCUMENTDB_PASSWORD and the OpenBao/vault configuration through their own values/secrets.
cd mcp-gateway-registry
git pull origin main
git checkout 1.26.0
# Update your .tfvars with any new variables (egress vault / Secrets Manager)
cd terraform/aws-ecs
terraform plan
terraform applyECS uses AWS DocumentDB (authenticated + TLS by the managed service) and AWS Secrets Manager, so the local weak-secret preflight and MongoDB password rotation do not apply.
The three gateway service images are published to Amazon ECR Public and pulled by the prebuilt Compose path (./build_and_run.sh --prebuilt). Override the namespace with ECR_REGISTRY if you mirror them elsewhere.
docker pull public.ecr.aws/p3v1o3c6/registry:1.26.0
docker pull public.ecr.aws/p3v1o3c6/auth-server:1.26.0
docker pull public.ecr.aws/p3v1o3c6/mcpgw:1.26.0The example MCP servers (currenttime, realserverfaketools) and the metrics service are built locally by build_and_run.sh and are not published as release images.
The gateway can now broker per-user, third-party credentials for egress to external MCP servers, so an authenticated user's connection to a downstream SaaS (e.g. Slack, Atlassian, GitHub) uses that user's own OAuth token rather than a shared credential. Tokens are held in a secret store - OpenBao (a dev-mode container ships with Docker Compose; a sealed, file-backed standalone OpenBao ships with Helm) or AWS Secrets Manager - and refreshed ahead of expiry. Off by default (EGRESS_AUTH_ENABLED=false).
The MCP proxy hop's upstream timeout was hardcoded to 30s, causing long-running tool calls to fail with 504. It is now a first-class parameter, MCP_PROXY_TIMEOUT, wired across all deployment surfaces (Compose, Helm, Terraform) and derived into nginx's proxy_read_timeout.
Agent tool execution is now gated behind an explicit confirmation step, and agent-to-agent (A2A) calls authenticate the calling agent, closing an unauthenticated-execution path.
This release is a broad security-hardening pass across the auth, proxy, and data layers:
- Enable MongoDB authentication by default in Docker Compose; drop the committed weak
adminpassword (#1386) - Loopback-bind all non-front-door Compose ports by default (#1376)
- Remove the orphaned
disable-ssl.shthat weakened Keycloak TLS; keepsslRequired=external(#1380) - Remove weak default Keycloak credentials and stop forcing non-temporary passwords (#1381)
- Remove the anonymous
/.well-known/mcp-serversdiscovery endpoint (#1374) - Drop unused
python-joseto remove CVE-bearing transitive dependencies (#1387) - Add access control to
GET /servers/{path}/versionsso it no longer leaks backend URLs (#1388) - Make peer federation tokens write-only in responses (#1389)
- Separate internal service tokens from user tokens (#1359); MCP session-id hardening (#1357)
- SSRF URL validation on registration and OAuth token calls (#1363, #1396)
- CORS allowlist made fail-closed and credential-aware (#1364)
- ID-token signature verification and secret-key length hardening (#1366, #1367)
- Authorization/ownership checks tightened across management routes (#1365)
- Enforce CSRF validation on IAM management and federation endpoints (#1390)
- Stop relaying caller credentials to untrusted MCP/A2A upstreams (#1391); treat client auth headers as ingress-only and strip on egress (#1369)
- Block script-scheme (
javascript:/data:) URLs in dynamic frontend links (#1394) - MCP proxy body-integrity: re-authorize the exact forwarded body, fail closed on an uninspectable body (#1393)
- Require a per-deployment secret for metrics API-key hashing and close a rate-limit oracle (#1399)
- Restrict read-only info disclosure on management/search responses (#1397)
- Harden Docker Compose stacks against insecure defaults, incl. a weak-secret denylist and preflight (#1400, #1368)
- Raise dependency floors above known CVE fixes (incl. aiohttp), refresh all
uv.lockfiles, and extend the python-jose guard to the root and all sub-project manifests/locks (#1401) - Federation credential hardening: validate peer
endpointURLs through the SSRF guard on create/update/sync and harden peer credential handling (#1398) - Log redaction and secret hygiene: redact secrets/tokens from logs across auth-server, providers, and CLI/discovery clients; keep freshly minted M2M secrets off stdout; write secret files with
0600perms (#1405)
- Add an OpenBao dev-mode container to the Docker Compose stacks (#1349)
- Pull prebuilt images from Amazon ECR Public instead of Docker Hub (#1352)
- New FAQ: rotate MongoDB password + OpenBao token for local Docker Compose (#1402)
- Remove DockerHub publish steps from the release-notes skill (the project no longer publishes to DockerHub) (#1404)
- Stop instructing
sslRequired=nonein the setup guides;externalis correct (#1384) - Fix mermaid rendering in the auth and egress-vault docs (#1382, #1383, #1373, #1375)
- Add a self-service lifecycle workflow demo video link
- Repair the fresh-deploy path in
docker-compose.podman.yml: mongo-init credentials, OAuth discovery env wiring, and realm-setup documentation (#1395) - Make the MCP proxy upstream timeout configurable to fix 504s on long-running tool calls (#1356)
- Update
TemplateResponsecalls to the current Starlette signature (#1360) - Reduce authorization lookups and extend nginx header stripping (#1342)
- Remove the invalid "file" storage backend from the terraform-setup skill docs (#1353)
- Recurse into the FastAPI 0.138 included-router wrapper in the internal-route meta-test (#1347)
| Issue | Title | Closed By |
|---|---|---|
| #1379 | docker-compose.podman.yml: mongodb-init default credentials don't match the no-auth mongodb-ce service | #1395 |
| #1378 | docker-compose.podman.yml: KEYCLOAK_EXTERNAL_URL/MCP_HTTPS_REQUIRED not passed to containers; Keycloak has no host port mapping | #1395 |
| #1377 | docker-compose.podman.yml: Keycloak realm import is silently broken | #1395 |
| #1320 | MCP proxy hop upstream timeout is hardcoded to 30s (long-running tool calls fail with 504) | #1356 |
| #1266 | Egress: ingress-token relay fix (relay-ingress + none) | #1369 |
| PR | Title |
|---|---|
| #1405 | log redaction |
| #1404 | docs(skill): remove DockerHub publish steps from release-notes skill |
| #1402 | docs(faq): rotate MongoDB password + OpenBao token for local Docker Compose (EC2/macOS) |
| #1401 | update dependencies (raise floors above CVE fixes; extend python-jose guard) |
| #1398 | federation credential hardening |
| #1400 | harden compose: case-insensitive weak-secret denylist; blank PF_ADMIN_PASS placeholder |
| #1399 | fix(metrics-service): require per-deployment secret for API-key hashing; close rate-limit oracle |
| #1397 | readonly info restriction |
| #1396 | fix(egress): route OAuth token calls through the SSRF guard and escape callback HTML |
| #1395 | fix(podman): repair fresh-deploy path in docker-compose.podman.yml |
| #1394 | frontend xss hrefs |
| #1393 | mcp proxy integrity |
| #1392 | feat: gate LLM tool execution behind confirmation and authenticate A2A agents |
| #1391 | fix: stop relaying caller credentials to untrusted MCP/A2A upstreams |
| #1390 | fix: enforce CSRF validation on IAM management and federation endpoints |
| #1389 | fix(security): make peer federation_token write-only in responses |
| #1388 | fix(security): add access control to GET /servers/{path}/versions |
| #1387 | fix(security): drop unused python-jose (removes CVE-bearing deps) |
| #1386 | fix(security): enable MongoDB auth by default; drop weak admin password |
| #1384 | docs: stop instructing sslRequired=none; external is correct |
| #1383 | docs(egress-vault): fix mermaid render of placeholders |
| #1382 | docs(auth): fix mermaid render of token placeholder |
| #1381 | fix(security): remove weak Keycloak default credentials |
| #1380 | fix(security): remove orphaned disable-ssl.sh that weakened Keycloak TLS |
| #1376 | fix(security): loopback-bind non-front-door compose ports |
| #1375 | docs(egress): make mermaid notes/messages parseable |
| #1374 | security: remove /.well-known/mcp-servers anonymous discovery endpoint |
| #1373 | docs(egress): fix mermaid render error from angle-bracket token placeholders |
| #1369 | fix(egress): treat client auth headers as ingress-only, strip on egress |
| #1368 | remove hardcoded placeholder secrets |
| #1367 | secret key hardening |
| #1366 | idtoken signature |
| #1365 | authz and ownership |
| #1364 | cors and cookies |
| #1363 | ssrf url validation |
| #1361 | feat(nginx): derive mcp-proxy proxy_read_timeout from MCP_PROXY_TIMEOUT |
| #1360 | fix: update TemplateResponse calls to current Starlette signature |
| #1359 | fix(security): separate internal service tokens from user tokens |
| #1358 | feat(config): wire MCP_PROXY_TIMEOUT as a first-class param across all surfaces |
| #1357 | (fix) mcp session id hardening |
| #1356 | fix: make MCP proxy upstream timeout configurable |
| #1353 | fix(terraform-setup): remove invalid "file" storage backend from skill docs |
| #1352 | fix(compose): pull prebuilt images from ECR Public instead of Docker Hub |
| #1351 | update python-jose dependency |
| #1350 | docs(slides): update presentation PDF |
| #1349 | feat(compose): add OpenBao dev-mode container to Docker Compose stacks |
| #1347 | test(auth): recurse into FastAPI 0.138 included-router wrapper |
| #1344 | build(deps): bump actions/checkout |
| #1342 | fix: reduce authz lookups, extend nginx header stripping, reuse constants |
| #1312 | Feat/egress auth |
| #1305 | feat(helm): standalone OpenBao for per-user egress credential vault |
Thank you to all contributors for this release:
Full Changelog: 1.25.0...1.26.0