All posts
Unproven Execution

GitLab AI Gateway: Flow Author Reaches Host Shell

CVE-2026-90970 lets a Duo Agent Platform user escape GitLab AI Gateway's template sandbox and run commands on the self-hosted gateway host

Securityv0 Intelligence Team OWASP: ASI05 sv0 finding: unproven_execution
gitlab ai-gateway duo-agent-platform template-injection unproven-execution asi05

The Incident

On October 2, 2026 GitLab disclosed CVE-2026-90970, a CVSS 9.9 template-engine injection (CWE-1336) in the self-hosted GitLab AI Gateway. An authenticated user with Duo Agent Platform access can submit a crafted flow configuration that escapes the gateway’s prompt-template sandbox and runs arbitrary commands on the AI Gateway host. The flaw sits on the server-side rendering of the flow definition, before any model call: it is template injection against the gateway, not model-level prompt injection. Affected builds are AI Gateway 18.1.6 through 19.2.3, 19.3.0 through 19.3.1, and 19.4.0; fixes shipped in 19.2.4, 19.3.2, and 19.4.1. Discovery is credited to HackerOne researcher invisiblemeerkat. Only self-hosted AI Gateway deployments are affected — GitLab.com, GitLab Dedicated, and self-managed instances pointed at a GitLab-hosted gateway are not — and GitLab reported no in-wild exploitation at disclosure. The CVE is not in CISA KEV.

This is the second CWE-1336 template-engine failure in the same Duo Workflow Service in 2026. CVE-2026-1868, also rated CVSS 9.9, was fixed earlier in AI Gateway 18.6.2, 18.7.1, and 18.8.1; its root cause was template expansion of Duo Agent Platform flow definitions on the gateway, the same subsystem that returned here as CVE-2026-90970.

MITRE ATT&CK coverage:

  • T1059 — Command and Scripting Interpreter
  • T1552.001 — Unsecured Credentials: Credentials In Files

The Authority Path That Failed

The identity carrying execution authority at the moment of failure is the Duo Agent Platform flow-author role on a self-hosted deployment. The Duo Agent Platform runs under GitLab’s composite-identity design: a service account is the primary author on each flow and the human user is the secondary author. The scope that role was granted is “author a flow configuration” — a surface the operator expected to be confined to flow definitions the AI Gateway would consume and render. The scope that same role actually exercised, through the sandbox escape, was arbitrary command execution on the AI Gateway host. The role never carried that authority on paper; the template engine held it on the role’s behalf, under confinement nobody tested as a security boundary.

The trust anchor that failed first was the prompt-template sandbox itself. The gateway accepted user-controlled flow configuration and rendered it through its template engine on the premise that the sandbox confined evaluation to data substitution; a crafted configuration (CWE-1336) escaped the sandbox and reached the shell on the host that runs the gateway process. On a self-hosted deployment that host also stores admin-configured model-provider API keys, instance-minted JWTs, and Cloud Connector service tokens, so an attacker who reaches shell on the gateway inherits a concentrator of machine identities, not just one process. CVE-2026-1868 told the same story in February: template expansion of flow definitions, same service, same CVSS, same class, same fix shape. The second occurrence makes this a design pattern in the Duo Workflow Service, not an isolated bug.

SecurityV0 Perspective

For any self-hosted GitLab AI Gateway running an affected build, SecurityV0 would raise unproven_execution against the gateway runtime. The finding attaches because the Duo Agent Platform’s flow-author role has a code-execution surface in its reachable graph — the template engine on the AI Gateway host — that the operator never authorized the role to exercise, and that is not visible in any role manifest, policy document, or admin UI. The pattern is the Langflow CSV-Agent + Python-REPL reference: an AI framework component ships with un-fenced execution authority on a path the operator does not realize they are exposing. The 18.x and 19.x fixes close this template path, but the architectural question remains: the gateway’s template engine is still rendering user-controllable flow data on a host that also holds model-provider API keys and instance tokens. The secondary nhi_compromise angle is that blast radius — RCE on the gateway converts a flow-authoring privilege into attacker control of every NHI the gateway concentrates.

The evidence pack would carry the AI Gateway version string, the deployment mode (self-hosted vs. GitLab-hosted), the list of principals with Duo Agent Platform access on each namespace or group, the service-account composite-identity binding, the inventory of model-provider API keys and OIDC/JWKS material stored on the gateway host, the template subsystem’s current patch state, and any flow-definition rendering logs with sandbox-escape markers. Pre-exfiltration, that pack answers: which identities can author inputs that reach the AI Gateway’s templating subsystem, and what is the worst that subsystem can do on the gateway host if its sandbox fails? Post-exfiltration, it answers: which flow author submitted which configuration between the vulnerable deployment and the patched one, which gateway processes executed under the sandbox-escape path, and which NHI material the gateway held at that moment and must now be rotated.

What To Do

  • Upgrade self-hosted AI Gateway to 19.2.4, 19.3.2, or 19.4.1 (or later) today. The fix is in those exact release lines; GitLab.com, GitLab Dedicated, and self-managed instances pointed at a GitLab-hosted gateway are not affected, so the action here is scoped to operators running their own gateway. Confirm the active build with the gateway’s version endpoint, not with the GitLab application version.
  • Inventory every principal with Duo Agent Platform access on affected deployments, and treat each as a reachable path to the gateway host. Record which users and which group service accounts can submit flows, under the composite-identity binding, for every self-hosted gateway in the organization. The role-level permission “author a flow” is what the exploit chains from; the inventory is the pre-exfiltration population you must assume could have reached host shell during the exposure window.
  • Rotate every machine identity the AI Gateway stored during the exposure window. Admin-configured model-provider API keys (OpenAI, Anthropic, Azure OpenAI, Bedrock, and self-hosted model endpoints), instance-minted JWTs, and Cloud Connector service tokens all co-reside on the gateway host and would have been readable from the sandbox-escape path. Rotation is a function of the exposure window and the host’s secret inventory, not of whether exploitation was observed.
  • Log and retain flow-configuration submissions with the submitting principal and the rendered template output, not just the request body. The forensic question for CVE-2026-90970 is not “did a flow get submitted” but “which flow’s template rendering reached the shell.” Capture the submitter’s composite-identity pair, the raw flow configuration, the template engine’s resolved output, and any gateway-host process spawned around the render — then keep it long enough to cover the deployment’s time at an affected build.
  • Treat the AI Gateway host as a shared NHI concentrator and gate it accordingly, independent of this patch. CVE-2026-1868 was the first CWE-1336 flow-template failure in the Duo Workflow Service in 2026; CVE-2026-90970 is the second. The design pattern — rendering user-controllable flow data on a host that also holds every model-provider key the deployment uses — survives both fixes. Isolate the gateway process from the key store, require fresh human approval for new flow-authoring roles, and plan for a third occurrence.

Sources