Yaamlabs

Vulnerabilities

GitLab AI Gateway flaw: a custom flow can run commands

CVE-2026-90970 (CVSS 9.9) lets a Duo Agent Platform user escape the prompt template sandbox on self-hosted AI Gateways. Fixed versions, interim step, checks.

GitLab has fixed CVE-2026-90970, a CVSS 9.9 flaw in the self-hosted GitLab AI Gateway, the service that sits between a GitLab instance and the large language models behind GitLab Duo. An authenticated user with access to the Duo Agent Platform can submit a crafted flow configuration that escapes the prompt template sandbox and runs commands on the gateway host. GitLab published the fix on October 2 in AI Gateway 19.2.4, 19.3.2 and 19.4.1. Every gateway version from 18.1.6 up to those releases is affected.

Only self-hosted gateways need action. GitLab says it has already patched the gateways it hosts, so GitLab.com, GitLab Dedicated, and Self-Managed instances that use a GitLab-hosted gateway are protected. If your GitLab Self-Managed instance points at an AI Gateway you run yourself, in Docker or through the Helm chart, it is on you to upgrade, and the attacker only needs an ordinary account that can use Duo agents.

How it works

The Duo Agent Platform lets users build custom flows: YAML definitions that chain agents, tools and prompts into a multi-step job. Each prompt in a flow has a prompt_template with a system and user section, and those sections pull in runtime values through double-brace placeholders such as {{goal}} or {{project_id}}. When a flow runs, the AI Gateway fills in the placeholders and sends the finished text to the model.

According to Forkast and Cybersecurity News, the gateway renders these templates with Jinja2, the Python template engine, inside a sandbox meant to allow variable substitution and nothing else. GitLab describes the bug as improper neutralization in the custom flow prompt template: user-supplied flow content is not cleaned before rendering, so a template expression in a crafted flow can climb out of the sandbox and reach the host's operating system. The weakness is classed as CWE-1336, improper neutralization of special elements used in a template engine, which is server-side template injection. The CVSS vector (AV:N/AC:L/PR:L/UI:N/S:C) reflects a network attack needing only a low-privilege account, no victim interaction, and an impact that reaches beyond the gateway process itself.

The changed scope matters because of what the gateway host holds. GitLab's install documentation has self-hosted gateways run with four RSA private keys passed as environment variables: AIGW_SELF_SIGNED_JWT__SIGNING_KEY and its validation key for the gateway, and DUO_WORKFLOW_SELF_SIGNED_JWT__SIGNING_KEY and its validation key for the Duo Agent Platform service. A process running commands on the host can read those, along with whatever credentials the gateway uses to call your model providers, and it sits on a network path to the GitLab instance and to any self-hosted models.

This is the second template injection in the same component this year. CVE-2026-1868, published in February, was also rated 9.9 and classed as CWE-1336: insecure template expansion of user data in crafted Duo Agent Platform flow definitions, fixed in 18.6.2, 18.7.1 and 18.8.1. Both ranges start at 18.1.6, and a gateway patched to 18.8.1 for the February bug is still inside the affected range for the new one. Some coverage this week labelled the new flaw CVE-2026-1868; GitLab's advisory uses CVE-2026-90970, and the two are separate bugs.

What attackers are doing

There is no confirmed exploitation. GitLab's advisory does not report attacks and publishes no technical exploit detail. The CISA assessment added to the CVE record on October 2 lists exploitation as "none". One vulnerability tracker links a GitHub repository as a proof of concept, while other outlets report that no public exploit exists; we could not confirm that the repository works. The flaw was reported to GitLab through HackerOne by the researcher invisiblemeerkat.

Jinja2 sandbox escapes are a well documented class of bug, and the fixed release shows anyone who compares it with 19.4.0 where the hole was. Treat any account with Duo Agent Platform access as able to reach the gateway host until you have upgraded.

What to do

1. Upgrade the gateway

Move to 19.2.4, 19.3.2 or 19.4.1, matching the release line of your GitLab instance, since the gateway's image tag (self-hosted-vX.Y.Z-ee) should line up with your GitLab version. Anything from 18.1.6 to 19.2.3, 19.3.0 to 19.3.1, or 19.4.0 is vulnerable. For Docker, stop and remove the gitlab-aigw container, pull the fixed tag and start it again with the same environment variables. For Kubernetes, run helm search repo ai-gateway --versions to find the chart that ships the fixed image, then helm upgrade --install ai-gateway ai-gateway/ai-gateway --version <chart-version>. Confirm the running image tag or digest afterwards.

2. If you cannot upgrade today

GitLab lists no workaround. One interim step under your control is to stop custom flows from running: in GitLab Self-Managed, go to Admin > GitLab Duo > Change configuration and clear "Allow custom flows" under "Custom and external agents and flows". GitLab's documentation says that with this off, users cannot create or run custom flows, and the instance setting overrides group settings. GitLab has not said whether this fully blocks CVE-2026-90970, so treat it as risk reduction and upgrade as soon as you can. Also make sure the gateway's ports (5052 for HTTP, 50052 for gRPC) accept traffic only from your GitLab instance and the clients that need them.

3. Check whether you were hit

GitLab has published no indicators. Start with the flows themselves: under each project's AI > Flows and in the AI Catalog, list custom flows created or edited since you deployed a vulnerable gateway, and read their prompt_template sections. Placeholders should be plain names. Expressions that call methods or reach into object internals, such as __class__, __globals__, __subclasses__ or references to os or popen, are typical of Jinja2 sandbox escapes and do not belong in a prompt. Creating a flow in the GitLab UI needs the Maintainer or Owner role on the project, so the accounts holding those roles are the first to review.

On the gateway host, look for processes the gateway should not start (shells, curl, wget, Python one-liners) with docker top gitlab-aigw or your container runtime's equivalent, and check firewall or egress logs for connections from the gateway to addresses other than your GitLab instance and your model providers.

4. If anything looks wrong

Rebuild the gateway on a fixed version rather than patching in place. Generate four new RSA keys with openssl genrsa -out <name>.key 2048, replace both gateway key pairs, and update the matching configuration on the GitLab side. Rotate the API keys or service credentials the gateway uses for each model provider, and remove or rewrite any suspicious flows and the accounts that created them.

The wider lesson

AI gateways get deployed as plumbing, often with long-lived keys in environment variables and broad network reach, while the flow and agent definitions they process are written by ordinary users. Any field a user can write that a template engine later renders deserves the same review as code. When a component has had two template injections in one year, add its prompt and flow handling to your test scope, and keep the gateway on its own patch schedule rather than waiting for the next GitLab upgrade window.

Our AI-native systems work covers how agent platforms and model gateways are wired into your environment, and our red team code review looks for template injection and similar bugs in the code that sits around them. Open the chat and Yaali, our AI agent, will pass your question to the engineer who would do the work.


Sources: GitLab AI Gateway 19.4.1 patch release, GitLab custom flows documentation, GitLab AI Gateway install documentation, Security Affairs, Cybersecurity News, Forkast, Cyber Press, TheHackerWire, OpenCVE: CVE-2026-1868.

Back to the blog, or read this post on the full site.