Release 1.27.0 - OBO, Application-Level Rate Limiting and a Broad Security-Hardening Pass
July 2026
Overview
This release takes the per-user egress auth story most of the way there: both 3LO (per-user OAuth, tokens vaulted by the gateway) and OBO (on-behalf-of token exchange for same-trust-domain backends) are now fully implemented and work across providers. Direct PAT (personal access token) egress is still to come, so this is one big step closer rather than the finish line. On top of that, it adds more gateway-centric capabilities. With A2A reverse-proxy routing, you can now optionally route inter-agent (agent-to-agent) traffic through the gateway too, so agent calls get the same fine-grained access control (FGAC) governance we already apply to MCP servers, each agent gated per call with its own invoke_agent grant while its real backend stays private. And with application-level rate limiting, the gateway now does AI traffic management: identity-, group-, and target-aware request limits enforced at the auth-server hop, so you can cap a caller or protect a busy MCP server / A2A agent, complementary to the coarse per-IP edge limiting. The release also lands a broad security-hardening pass across the auth, proxy, data, and frontend layers.
Upgrading from 1.26.0
This section covers everything you need to know to upgrade from 1.26.0 to 1.27.0.
Breaking Changes
There are no breaking changes in this release. All new behavior is opt-in and defaults preserve the prior behavior:
- Rate limiting is off by default (
RATE_LIMITING_ENABLED=false). With it unset,/validatebehaves exactly as before. - The registry configuration endpoints now require authentication.
GET /api/config/*previously served without auth; it now requires a valid session/token. If you had tooling reading/api/configanonymously, give it an authenticated token. The anonymous/healthprobe no longer leaks deployment topology. - Internal service tokens are now single-use and M2M token audience is validated against an explicit allowlist. If you mint internal tokens outside the shipped flow, they must be single-use; M2M callers must present a token whose audience is allowlisted.
New Environment Variables
| Variable | Default | Description |
|---|---|---|
RATE_LIMITING_ENABLED |
false |
Master switch for application-level rate limiting. false = no checks (prior behavior). |
RATE_LIMIT_BACKEND |
documentdb |
Counter backend. Only documentdb is implemented in v1. |
RATE_LIMIT_FAIL_OPEN |
true |
Global fail-open on backend error (a per-limit fail_closed overrides to closed). Prevents a counter-store blip from becoming a full gateway outage. |
RATE_LIMIT_DEFINITIONS_CACHE_TTL_SECONDS |
30 |
In-process cache TTL for definition reads (zero DB reads in steady state). |
RATE_LIMIT_BACKEND_TIMEOUT_MS |
250 |
Hard per-op timeout for each counter operation, so a slow store fails fast into the fail-open/closed policy rather than hanging /validate. |
RATE_LIMIT_USER_FLOOR_PER_MIN |
20 |
Lockout-safeguard floor: a group whose short-window user limit falls below this is rejected at config time. |
RATE_LIMIT_AGENT_FLOOR_PER_MIN |
10 |
Lockout-safeguard floor for the agent (M2M) caller limit. |
AUDIT_LOG_REQUIRE_DURABLE |
true |
Require the audit trail to be durable-by-default; a non-durable audit sink fails closed. |
EGRESS_OBO_ALLOWED_AUDIENCES |
(empty) | Explicit, audited allowlist of internal server audiences the OBO token-exchange may target. Empty denies OBO. |
RUM_ALLOWED_HOSTS |
(empty) | Comma-separated allowlist of hosts the RUM snippet may reference (script src + beacon). A snippet referencing any other host is rejected (fail closed). Empty disables RUM. |
TRUSTED_PROXY_HOPS |
1 |
Number of trusted reverse-proxy hops when resolving the client IP (rightmost-trusted XFF). |
TRUSTED_EXTERNAL_HOSTS |
(empty) | Allowlisted external Host values (e.g. a CloudFront domain) used when building redirect URIs. |
TRUSTED_REAL_IP_CIDRS |
(empty) | CIDRs of trusted upstreams (e.g. an ALB subnet) whose forwarded client IP is honored. |
SSRF_ALLOWED_HOSTS |
(empty) | Opt-in allowlist of internal hosts the SSRF guard may reach (for private A2A/MCP backends). |
SSRF_ALLOWED_CIDRS |
(empty) | Opt-in allowlist of internal CIDRs the SSRF guard may reach. Prefer SSRF_ALLOWED_HOSTS when you can name the hosts. |
Rate-limit definitions and group memberships are managed at runtime (admin API /api/rate-limits, the rate-limit-* CLI commands, or Settings -> IAM -> Rate Limits in the UI), not via environment variables.
Upgrade Instructions
Docker Compose
cd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# Review new env vars in .env.example and update your .env if needed
# (rate limiting, SSRF allowlists, trusted-proxy, OBO audiences all default to
# prior behavior when unset). Then rebuild and restart:
./build_and_run.shKubernetes / Helm (EKS)
cd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# REQUIRED: subchart templates/values changed in this release. Rebuild deps so
# the packaged .tgz subcharts pick up the changes (a plain helm upgrade would
# otherwise use the stale packaged subcharts).
cd charts/mcp-gateway-registry-stack
helm dependency build
helm dependency update
# Update values.yaml if needed (new rate-limiting, egress OBO, and
# trusted-request-source values), then upgrade:
helm upgrade mcp-gateway . -f your-values.yamlTerraform / ECS
cd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# Update your .tfvars with any new variables (rate-limiting floors, SSRF
# allowlists, OBO audiences), then:
cd terraform/aws-ecs
terraform plan
terraform applyMajor Features
Application-Level Rate Limiting
Identity-, group-, and target-aware request limiting enforced at the auth-server /validate hop, complementary to the coarse per-IP nginx edge limiting. Two axes compose: a caller limit caps a user or agent (resolved by rate-limit group membership, kept in a dedicated collection and deliberately decoupled from the token's authz groups so adding a limit never changes a caller's scopes), and a target limit caps aggregate load on an MCP server or A2A agent regardless of caller. Each limit is per time window; multiple windows stack, and a request denied by a tighter window never consumes a wider window's quota. Lockout safeguards: admins bypass caller limits, caller limits apply to data-plane MCP/A2A calls only (never the dashboard or /api/*), and config-time floors reject a group whose short-window limit falls below the configured minimum. Counters live in DocumentDB (shared across replicas) via an atomic conditional increment; a per-op timeout fails fast into a fail-open availability guardrail by default, or fail-closed per-limit for security-critical caps. Throttled calls return HTTP 429 with X-RateLimit-* and Retry-After headers, plus an OTel metric and an attributable app-log line. Off by default; managed at runtime via the admin API, CLI, or the Settings -> IAM -> Rate Limits UI.
Amazon Cognito M2M (client_credentials) Support for Agent Callers
Agent (machine-to-machine) callers can now authenticate with Amazon Cognito client_credentials tokens, with provider-aware caller classification so a genuine M2M token is treated as an agent for rate limiting and authorization.
On-Behalf-Of (OBO) Egress Token Exchange
For same-trust-domain backends, the gateway now supports an obo_exchange egress mode (Microsoft Entra jwt-bearer today): it exchanges the caller's ingress token for a backend-audience token at call time, preserving the user's identity with nothing to vault. The target audiences are gated to an explicit, audited allowlist (EGRESS_OBO_ALLOWED_AUDIENCES). This complements the existing 3LO per-user vault, and 3LO itself now works across providers (including Entra).
A2A Reverse-Proxy Gateway Support
Opt in to route agent-to-agent traffic through the gateway the same way MCP servers are proxied: each enabled agent gets authenticated /agent/{path} routes, its real backend stays private (proxy_pass_url) and is redacted from non-admin reads, discovery advertises the gateway URL, and every call is gated per-agent with an invoke_agent grant. The egress trust model keeps the gateway a policy gate, not a credential broker: the caller's gateway token rides in X-Authorization (stripped at egress) while the target agent's own credential rides in Authorization (forwarded end to end).
RFC 8707 Resource Indicator for Custom OAuth Providers
Custom OIDC egress providers can now emit an RFC 8707 resource indicator on the authorize request and both token grants, binding the minted token to one protected resource. This is required by resource servers that issue per-resource tokens (for example Atlassian's Rovo MCP).
What's New
Security Hardening
This release lands a broad, systematic security-hardening pass across the auth, proxy, data, and frontend layers:
- OAuth CSRF hardening: validate the
stateat the token-exchange point (#1429) - Internal service tokens are now single-use to prevent replay (#1430)
- Enforce M2M token audience against an explicit allowlist (#1418)
- Require authentication for the registry configuration endpoints; stop leaking deployment topology from the anonymous
/healthprobe (#1445) - Enforce scope-based server and tool access on the tool catalog and single-server reads (#1444)
- Fix a skill-visibility bypass via cross-resource permission confusion (#1439)
- Honor the disabled flag when enriching token groups from the database (#1443)
- Authorization hardening: delete-ownership enforcement, path canonicalization before authz, credential-destination re-validation, group-enrichment gating, and token-mint session reconciliation (#1468)
- Intra-admin safety guards and follow-up: refuse self-delete and last-admin removal/demotion (#1428, #1437)
- Harden the audit trail: durable-by-default with per-instance attribution, and record raw human-readable identity across all audit streams (#1438, #1432)
- Validate override endpoint fields through the canonical SSRF guard (#1470)
- Close a potential regex-injection vector (#1417)
- Tighten CLI credential handling (#1419)
- Harden legacy static admin/privilege-granting tokens: validate strength, least-privilege federation scope (#1466, plus static-token bypass hardening)
- AgentCore IAM scoping to least privilege (#1442)
- Constrain auto-generated secret characters to a URI-safe, AWS-safe set (#1362)
- Add a repository security-guidelines catalog and wire it into the review skills (#1416)
Infrastructure and Deployment
- CDK / Terraform parity: embed CloudFront, drop the 8888/7860 listeners,
sslRequired=external(#1435) - Fix DocumentDB rotation IAM to use the
rds:*action namespace the boto3docdbclient actually evaluates, in both Terraform and CDK (#1406, #1474) - Generic bring-your-own RUM (Real User Monitoring) injection hook for the frontend, host-allowlisted and fail-closed (#1472)
- Configurable Claude Code connect-snippet scope via
IDE_CONNECT_SCOPE(#1464) - nginx edge rate limiting (#1431)
Frontend
- Page through the list APIs so the dashboard is not hard-capped at the first page (#1436)
Documentation
- New 3LO (per-user OAuth) AgentCore gateway FAQ, with a Cognito + Claude Code worked example (#1473)
- Correct the egress runtime-sequence diagram to match the implementation (#1483)
- README refactor: audience-routed rewrite, theory-of-the-system and executive brief, feature/release highlights, and MkDocs strict-mode nav cleanup (#1422, #1423, #1424, #1425)
- Move release notes out of the main README into the docs site (#1411, #1421)
- Update the 3LO demo video link across docs and README (#1482)
CI and Maintenance
- Align the repository to pre-commit and enforce it (#1440)
- Use a slim detect-secrets baseline to stop line-number churn (#1480)
- Use the lockfile for docs builds (#1465)
- Weekly dependency and GitHub Actions updates (#1408, #1409, #1462, #1463)
Bug Fixes
- fix(scopes): grant
publish_skillto the admin seed scopes (#1479) - fix(a2a): pass a dict to
update_agentin the security-pending-tag path (#1441) - fix(rate-limiting): provider-aware caller classification, correct human-vs-agent classification, surface throttle as 429 through nginx
auth_request, and capture the actualRetry-Afterheader (#1467) - fix(readme): replace the PAT-gated star-history chart with shields.io badges (#1481)
Closed Issues
| Issue | Title | Closed By |
|---|---|---|
| #1471 | Add a generic RUM injection hook for the frontend | PR #1472 |
| #1433 | Failed to get admin token (admin publish_skill permission) | PR #1479 |
| #1410 | Remove "What's New" from README.md | PR #1411 |
| #1354 | Auto-generated secrets with special characters break deployment | PR #1362 |
| #1348 | DocumentDB secret rotation fails: docdb:* vs rds:* namespace |
PR #1406 |
| #1282 | SSRF hardening: validate outbound URL on agent card fetch | PR #1470 |
| #1269 | Egress: token-exchange (OBO) for same-trust-domain backends | PR #1420 |
| #880 | Implement proper frontend pagination for servers, agents, skills | PR #1436 |
| #847 | Add reverse-proxy gateway support for A2A agents | PR #1355 |
| #295 | Application-level rate limiting | PR #1467 |
Pull Requests Included
| PR | Title |
|---|---|
| #1483 | docs: correct egress runtime-sequence diagram to match implementation |
| #1482 | docs: update 3LO demo video link across docs and README |
| #1481 | fix(readme): replace PAT-gated star-history chart with shields.io badges |
| #1480 | chore(ci): use slim detect-secrets baseline to stop line-number churn |
| #1479 | fix(scopes): grant publish_skill to admin seed scopes |
| #1474 | fix(cdk): use rds:* actions for DocumentDB rotation IAM (Terraform parity) |
| #1473 | docs: add FAQ for 3LO (per-user OAuth) AgentCore gateways |
| #1472 | Add generic bring-your-own RUM hook for the frontend |
| #1470 | Validate override endpoint fields through the canonical SSRF guard |
| #1469 | chore(usage-report): bump install-forecast target to 2,000 |
| #1468 | Authorization hardening: delete ownership, path canonicalization, credential re-validation, enrichment gating, mint reconciliation |
| #1467 | feat: application-level rate limiting + Cognito M2M support |
| #1466 | Harden legacy static admin token |
| #1465 | use lockfile for docs builds |
| #1464 | feat(connect): configurable Claude Code snippet scope (IDE_CONNECT_SCOPE) |
| #1463 | chore(deps): weekly lockfile update (2026-07-13) |
| #1462 | build(deps): bump the actions group with 7 updates |
| #1445 | Require authentication for the registry configuration |
| #1444 | Enforce scope-based server and tool access on the tool catalog and single-server reads |
| #1443 | Honor the disabled flag when enriching token groups from the database |
| #1442 | Agentcore scoping |
| #1441 | fix(a2a): pass dict to update_agent in security-pending-tag path |
| #1440 | fix: align repository to pre-commit and enforce pre-commit |
| #1439 | Fix skill visibility bypass via cross-resource permission confusion |
| #1438 | Harden the audit trail: durable-by-default and per-instance attribution |
| #1437 | admin safety guards followup |
| #1436 | fix(frontend): page through list APIs so dashboard is not hard-capped |
| #1435 | feat(infra): CDK / Terraform parity, embed CloudFront, drop 8888/7860 listeners |
| #1434 | feat(a2a): egress trust model, {agent,actions} scopes, gateway-aware discovery |
| #1432 | fix(audit): record raw human-readable identity across all audit streams |
| #1431 | nginx rate limiting |
| #1430 | Make internal service tokens single-use |
| #1429 | OAuth CSRF Hardening |
| #1428 | Intra-admin safety guards |
| #1427 | feat(egress): add RFC 8707 resource indicator for custom OAuth providers |
| #1425 | docs: replace MkDocs site with a README-generated landing page |
| #1424 | docs: fix all mkdocs --strict warnings and auto-generate nav |
| #1423 | docs: rewrite README (audience-routed) + regrowth prevention |
| #1422 | docs: add theory-of-the-system, executive brief, and feature/release highlights |
| #1421 | Add redirect stubs for moved release notes; fix stale path references |
| #1420 | Egress OBO: add obo_exchange mode + make 3LO work on Entra / across providers |
| #1419 | tighten cli credentials |
| #1418 | Enforce M2M token audience against an explicit allowlist |
| #1417 | close potential regex injection |
| #1416 | add security guidelines |
| #1413 | docs(skills): add security-patterns catalog and wire into review skills |
| #1412 | skill credential handling |
| #1411 | remove releases notes from main repo README and add to mkdocs |
| #1409 | chore(deps): weekly lockfile update (2026-07-06) |
| #1408 | build(deps): bump the actions group with 7 updates |
| #1406 | Fix DocumentDB rotation IAM actions |
| #1362 | fix: constrain secret characters to URI-safe, AWS-safe set |
| #1355 | feat(a2a): add reverse-proxy gateway support for A2A agents |
Contributors
Thank you to all contributors for this release:
- Amit Arora (@aarora79)
- omrishiv (@omrishiv)
- Harshit Gupta (@harshitkgupta)
- Gonçalo Faustino (@go-faustino)
- Lucas Anjos (@anjosluc)
- TechSphrex TA (@KhaiTrang1995)
- ahfoysal (@ahfoysal)
- zsxh1990 (@zsxh1990)
- ceng (@ceng-p)
Support
Full Changelog: 1.26.0...1.27.0
What's Changed
- build(deps): bump the actions group in /.github/workflows with 7 updates by @dependabot[bot] in #1408
- chore(deps): weekly lockfile update (2026-07-06) by @github-actions[bot] in #1409
- docs(skills): add security-patterns catalog and wire into review skills by @aarora79 in #1413
- fix: constrain secret characters to URI-safe, AWS-safe set (#1354) by @zsxh1990 in #1362
- skill credential handling by @omrishiv in #1412
- add security guidelines by @omrishiv in #1416
- close potential regex injection by @omrishiv in #1417
- Enforce M2M token audience against an explicit allowlist by @omrishiv in #1418
- remove releases notes from main repo README and add to mkdocs by @ceng-p in #1411
- Add redirect stubs for moved release notes; fix stale path references (follow-up to #1411) by @aarora79 in #1421
- docs: add theory-of-the-system, executive brief, and feature/release highlights (README refactor, PR A) by @aarora79 in #1422
- docs: rewrite README (audience-routed, ~130 lines) + regrowth prevention (README refactor, PR B) by @aarora79 in #1423
- docs: fix all mkdocs --strict warnings and auto-generate nav via awesome-pages by @aarora79 in #1424
- docs: replace MkDocs site with a README-generated landing page + restore fork-safe relative links by @aarora79 in #1425
- tighten cli credentials by @omrishiv in #1419
- OAuth CSRF Hardening by @omrishiv in #1429
- Egress OBO: add
obo_exchangemode + make 3LO work on Entra / across providers by @omrishiv in #1420 - fix(audit): record raw human-readable identity across all audit streams by @omrishiv in #1432
- Intra-admin safety guards by @omrishiv in #1428
- admin safety guards followup by @omrishiv in #1437
- Make internal service tokens single-use by @omrishiv in #1430
- nginx rate limiting by @omrishiv in #1431
- Fix skill visibility bypass via cross-resource permission confusion by @omrishiv in #1439
- Harden the audit trail: durable-by-default and per-instance attribution by @omrishiv in #1438
- feat(a2a): add reverse-proxy gateway support for A2A agents by @anjosluc in #1355
- feat(a2a): egress trust model, {agent,actions} scopes, gateway-aware discovery by @aarora79 in #1434
- fix(a2a): pass dict to update_agent in security-pending-tag path by @aarora79 in #1441
- fix: align repository to pre-commit and enforce pre-commit by @omrishiv in #1440
- feat(infra): CDK ↔ Terraform parity — embed CloudFront, drop 8888/7860 listeners, sslRequired=external by @harshitkgupta in #1435
- Honor the disabled flag when enriching token groups from the database by @omrishiv in #1443
- Enforce scope-based server and tool access on the tool catalog and single-server reads by @omrishiv in #1444
- Require authentication for the registry configuration by @omrishiv in #1445
- feat(egress): add RFC 8707 resource indicator for custom OAuth providers by @go-faustino in #1427
- chore(deps): weekly lockfile update (2026-07-13) by @github-actions[bot] in #1463
- use lockfile for docs builds by @omrishiv in #1465
- chore(deps): bump the actions group in /.github/workflows with 7 updates by @dependabot[bot] in #1462
- Harden legacy static admin token by @omrishiv in #1466
- feat(connect): configurable Claude Code snippet scope (IDE_CONNECT_SCOPE) by @go-faustino in #1464
- feat: application-level rate limiting + Cognito M2M support (#295) by @aarora79 in #1467
- chore(usage-report): bump install-forecast target to 2,000 by @aarora79 in #1469
- Agentcore Scoping by @omrishiv in #1442
- fix(frontend): page through list APIs so dashboard is not hard-capped (#880) by @KhaiTrang1995 in #1436
- Validate override endpoint fields through the canonical SSRF guard by @omrishiv in #1470
- Add generic bring-your-own RUM hook for the frontend (#1471) by @aarora79 in #1472
- docs: add FAQ for 3LO (per-user OAuth) AgentCore gateways by @aarora79 in #1473
- Fix DocumentDB rotation IAM actions by @ahfoysal in #1406
- fix(cdk): use rds:* actions for DocumentDB rotation IAM (Terraform parity) by @aarora79 in #1474
- Authorization hardening: delete ownership, path canonicalization, credential re-validation, enrichment gating, mint reconciliation by @omrishiv in #1468
- fix(scopes): grant publish_skill to admin seed scopes (#1433) by @aarora79 in #1479
- chore(ci): use slim detect-secrets baseline to stop line-number churn by @aarora79 in #1480
- fix(readme): replace PAT-gated star-history chart with shields.io badges by @aarora79 in #1481
- docs: update 3LO demo video link across docs and README by @aarora79 in #1482
- docs: correct egress runtime-sequence diagram to match implementation by @aarora79 in #1483
New Contributors
- @ceng-p made their first contribution in #1411
- @anjosluc made their first contribution in #1355
- @KhaiTrang1995 made their first contribution in #1436
- @ahfoysal made their first contribution in #1406
Full Changelog: 1.26.0...1.27.0