
{"id":16,"date":"2026-08-30T09:36:05","date_gmt":"2026-08-30T09:36:05","guid":{"rendered":"https:\/\/www.0xprathamesh.com\/blog\/ai-gateway-control-plane-security\/"},"modified":"2026-09-21T06:05:47","modified_gmt":"2026-09-21T06:05:47","slug":"ai-gateway-control-plane-security","status":"publish","type":"post","link":"https:\/\/www.0xprathamesh.com\/blog\/ai-gateway-control-plane-security\/","title":{"rendered":"Your AI Gateway Is a Privileged Control Plane"},"content":{"rendered":"<p class=\"answer-first\"><strong>Short answer:<\/strong> an AI gateway is a privileged control plane because it sits between applications, model providers, databases and execution runtimes. Microsoft\u2019s new incident research shows the consequence: compromise of LiteLLM, RAGFlow or Kestra did not stop at one web process. Attackers reached provider keys, database records, workflow execution, container metadata and host compute. Defenders should secure these services like identity, CI\/CD and orchestration infrastructure, not like ordinary application proxies.<\/p>\n<p class=\"authorised-use\"><strong>Authorised-use notice:<\/strong> this article analyses public incident research and vendor advisories for defensive architecture, patching and detection. It omits exploit payloads and reproduction steps. Apply every check only to systems you own or are authorised to assess.<\/p>\n<p>On 26 August 2026, Microsoft Security Research published three compromise cases involving LiteLLM, RAGFlow and Kestra. The products do different jobs. LiteLLM routes model calls, RAGFlow connects retrieval and model workflows, and Kestra orchestrates tasks. Their security failure had the same shape.<\/p>\n<p>Each service concentrated authority. The gateway could see provider credentials and database connection details. The retrieval platform handled newly configured model keys. The workflow engine could create processes and, in the observed environment, reach container infrastructure. Once an attacker entered the application context, the next move was already nearby.<\/p>\n<p>This is the part worth remembering. The model was not the prize in these cases. The infrastructure around the model was.<\/p>\n<figure>\n  <img fetchpriority=\"high\" src=\"https:\/\/www.0xprathamesh.com\/assets\/blog\/ai-gateway-control-plane-security\/control-plane-map.svg\" width=\"1600\" height=\"900\" loading=\"eager\" decoding=\"async\" alt=\"AI gateway control-plane map showing users and applications connected through LiteLLM, RAGFlow and Kestra to provider keys, databases, workflow execution and container infrastructure.\"><figcaption>An original trust map based on Microsoft\u2019s three observed compromises. The dangerous property is concentrated authority, not the presence of an LLM.<\/figcaption><\/figure>\n<h2>What happened to LiteLLM, RAGFlow and Kestra?<\/h2>\n<p>Microsoft\u2019s report separates observed activity from technical assessment. That distinction matters. Incident telemetry can show which process launched a shell, read a secret or opened a network connection. It does not always prove the exact vulnerability used for initial access.<\/p>\n<table>\n<thead>\n<tr>\n<th>Workload<\/th>\n<th>Observed post-compromise activity<\/th>\n<th>Why the service role mattered<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>LiteLLM<\/td>\n<td>Runtime secret collection, PostgreSQL access, payload execution, persistence and cryptomining.<\/td>\n<td>The gateway process sat beside provider keys, proxy-issued virtual keys, the master key, database configuration and model-routing policy.<\/td>\n<\/tr>\n<tr>\n<td>RAGFlow<\/td>\n<td>Application-path modification and a hidden Python hook that intercepted newly configured provider credentials.<\/td>\n<td>The platform\u2019s legitimate tenant configuration flow receives model names, API keys and provider endpoints.<\/td>\n<\/tr>\n<tr>\n<td>Kestra<\/td>\n<td>Workflow-origin shell execution, container discovery, secret collection, XMRig deployment and data storage through the application\u2019s key-value interface.<\/td>\n<td>A workflow engine is designed to execute tasks. Compromising its control surface can turn intended automation into attacker-directed execution.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Microsoft assesses with high confidence that LiteLLM initial access was consistent with a chain involving CVE-2026-42271 and CVE-2026-48710. The LiteLLM advisory describes command execution through MCP stdio test endpoints in versions from 1.74.2 to before 1.83.7. Those endpoints accepted a server configuration containing command, argument and environment fields, then spawned the command with the proxy process\u2019s privileges. Version 1.83.7 restricts them to the <code>PROXY_ADMIN<\/code> role.<\/p>\n<p>CVE-2026-48710 affected Starlette\u2019s handling of malformed Host headers. In affected applications, the reconstructed <code>request.url.path<\/code> could differ from the path used by the router. Security checks built on the reconstructed value could therefore make a decision about the wrong path. Starlette 1.0.1 added validation. Microsoft\u2019s assessment is that the two weaknesses could combine in exposed, vulnerable LiteLLM deployments and make command execution reachable without valid credentials.<\/p>\n<p>The RAGFlow evidence needs more restraint. Microsoft observed possible SSRF-style reconnaissance followed several days later by code execution and credential-hook persistence. It lists public RAGFlow execution flaws as technical context, including CVE-2026-45312 and CVE-2026-28797, but does not assign one confirmed root cause to this intrusion. The maintainer advisories show why the application surface deserves attention: user-controlled Jinja2 templates in agent and prompt components could reach server-side command execution in affected versions.<\/p>\n<p>For Kestra, Microsoft assesses with high confidence that CVE-2026-49869 was the likely initial route. The maintainer advisory describes a suffix-based authentication exception. A path ending in <code>\/configs<\/code> could be treated as public even when it addressed a different API resource. In affected Kestra OSS releases before 1.0.45 and 1.3.21, an unauthenticated user could create and run a workflow. Script plugins then turned that authentication error into command execution inside the worker container.<\/p>\n<h2>Why an AI gateway is a control plane<\/h2>\n<p>A data plane handles the work. A control plane decides where that work goes, under which identity, with what policy and with access to which downstream systems. Modern AI gateways and orchestration platforms increasingly make those decisions.<\/p>\n<p>LiteLLM can route calls across providers and tenants. It may issue virtual keys, apply budgets, store model configuration and connect to a database. RAGFlow joins retrieval, model configuration, user content and workflow logic. Kestra stores and executes workflows that call other services. These are management functions, even when the product is introduced as a proxy, RAG application or automation tool.<\/p>\n<p>The security boundary should follow authority, not the product label. A small service becomes critical when four properties meet:<\/p>\n<ol>\n<li><strong>It is reachable.<\/strong> Users, applications or the internet can access a management or execution surface.<\/li>\n<li><strong>It can execute.<\/strong> The process launches tools, interpreters, plugins, workflows or child processes.<\/li>\n<li><strong>It can read authority.<\/strong> Provider keys, database strings, master tokens and tenant policy are in memory, environment variables or nearby storage.<\/li>\n<li><strong>It can communicate.<\/strong> Outbound access reaches providers, databases, package sources or arbitrary internet destinations.<\/li>\n<\/ol>\n<p>The three incidents do not share one vulnerability class. They share those four properties. That is why patching a CVE is necessary but does not finish the architecture review.<\/p>\n<h2>The LiteLLM case shows the full blast radius<\/h2>\n<p>The LiteLLM intrusion is the clearest example because Microsoft\u2019s telemetry follows the chain beyond first access. The gateway process read its own PID 1 environment and searched for secret-like values. That environment could contain model-provider API keys, the LiteLLM master key, database URLs, UI credentials and other tokens.<\/p>\n<p>The attacker then used the database connection string to reach LiteLLM\u2019s PostgreSQL tier. Microsoft observed access to tables that may hold upstream model configuration and proxy-issued virtual keys. A web-process compromise therefore became a database and identity incident without first breaking a second perimeter. The connection details were already part of the runtime.<\/p>\n<p>The same process lineage downloaded payloads, performed host discovery, prepared cryptomining, modified SSH access and added persistence. Multiple outbound tools were tried in sequence. Blocking one binary would not have solved the egress problem because Python, curl and wget provided alternate routes.<\/p>\n<p>There is a useful detection idea here. A model gateway should route requests. It should not normally spawn <code>bash<\/code>, inspect <code>\/proc\/1\/environ<\/code>, install a PostgreSQL client at runtime or execute a file from <code>\/tmp<\/code>. Process ancestry gives defenders a low-noise starting point because the parent is specific and the child behaviour is operationally strange.<\/p>\n<pre><code>\/\/ Defensive hunting shape adapted from Microsoft's published logic\nDeviceProcessEvents\n| extend Parent = tolower(InitiatingProcessCommandLine), Cmd = tolower(ProcessCommandLine)\n| where Parent has_any (\"litellm\", \"ragflow\", \"kestra\")\n| where FileName in~ (\"bash\", \"sh\", \"curl\", \"wget\", \"python\", \"python3\")\n| where Cmd has_any (\"\/proc\/1\/environ\", \"database_url\", \"\/tmp\/\", \"base64\")\n| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessCommandLine<\/code><\/pre>\n<p>This query is a starting shape, not a universal detector. Teams should tune it against their own expected plugins, health checks and workflow tasks. The value lies in joining workload identity with process behaviour. A generic \u201cpython launched shell\u201d alert can be noisy. \u201cThe production model gateway launched a shell that read PID 1 secrets\u201d deserves immediate investigation.<\/p>\n<h2>RAGFlow shows how application logic becomes persistence<\/h2>\n<p>The RAGFlow case had a different objective. Microsoft did not observe a miner or an interactive reverse shell. The attacker modified the application startup path and installed a hook around the tenant LLM configuration flow. When an administrator later supplied a provider key, the hook captured the provider type, model name, endpoint and credential material, then sent it out while allowing the normal configuration request to continue.<\/p>\n<p>That is quieter than stealing every existing secret at once. It waits for future authority to pass through a trusted function. A clean-looking dashboard is not proof that the configuration path is clean.<\/p>\n<p>Container replacement may remove this persistence if the application filesystem is truly immutable and ephemeral. It may also survive service restarts when the modified path sits on persistent storage. Responders need to know which image digest should be running, which files were changed after deployment and whether the application path is writable by its own service account.<\/p>\n<p>For AI platforms, file-integrity monitoring should cover more than binaries. Startup modules, plugin directories, prompt templates, workflow definitions and model-configuration handlers can all change what the service does with a credential before any model receives a request.<\/p>\n<h2>Kestra shows the danger of combining orchestration and runtime access<\/h2>\n<p>Kestra is built to turn definitions into actions. That makes an authentication bypass more serious than the same bug in a read-only catalogue. Microsoft observed workflow-origin shell sessions followed by Docker and container-environment discovery, XMRig deployment and later data collection.<\/p>\n<p>The affected environment exposed a Docker socket to the workload. From there, the attacker could inspect container metadata and environment arrays from other containers. The lesson extends beyond Kestra: mounting a container-runtime socket into an orchestration service can turn container-level execution into visibility across the host\u2019s workload inventory.<\/p>\n<p>Security teams often review the permissions inside a container and stop there. Runtime sockets, host namespaces, metadata endpoints and writable mounts decide whether that boundary means anything. A process running without a host shell may still hold an API to the host\u2019s container manager.<\/p>\n<h2>Five checks for every AI management surface<\/h2>\n<figure>\n  <img src=\"https:\/\/www.0xprathamesh.com\/assets\/blog\/ai-gateway-control-plane-security\/five-evidence-checks.svg\" width=\"1600\" height=\"900\" loading=\"lazy\" decoding=\"async\" alt=\"Five AI control-plane security checks covering exposure, process authority, secret reach, egress and runtime access.\"><figcaption>Architecture claims are useful only when the team can point to current enforcement and telemetry. These five checks connect each claim to evidence.<\/figcaption><\/figure>\n<h3>1. Exposure: find every management surface<\/h3>\n<p>Inventory public listeners, load balancer routes, ingress objects, VPN paths and internal service discovery. Include test endpoints, admin UIs, MCP configuration routes, workflow APIs and secondary management ports. A service can be \u201cinternal\u201d and still be reachable by every compromised workstation, CI runner or neighbouring namespace.<\/p>\n<p>Record the authentication decision point for each route. Reverse proxies sometimes protect the obvious UI while an API path or alternate port reaches the application directly. Verify the effective route with configuration and logs, not with a network diagram that predates the deployment.<\/p>\n<h3>2. Process authority: baseline what the service may execute<\/h3>\n<p>Document the runtime user, Linux capabilities, writable paths and expected child processes. A gateway that should never spawn a shell can use a strict policy. A workflow engine needs execution, so controls must move closer to the task: approved plugins, isolated workers, per-workflow identities, resource limits and a clear child-process baseline.<\/p>\n<p>Do not give the control-plane process package-management rights in production. Runtime installation of Python modules or system packages gives a compromised process another way to change its own capability and makes incident reconstruction harder.<\/p>\n<h3>3. Secret reach: measure the distance to authority<\/h3>\n<p>List every secret the process can obtain from environment variables, files, workload identity, database rows and metadata services. Mark its audience, lifetime and downstream permission. A provider key restricted to one model and a small spend limit is different from an organisation-wide key that can call every provider feature.<\/p>\n<p>Where possible, fetch credentials just in time from a broker and keep them short-lived. Separate the database identity used for request routing from identities used for administration, migrations and backup. The gateway should not be able to read or update every table simply because it uses the database.<\/p>\n<h3>4. Egress: decide where compromised authority can travel<\/h3>\n<p>Use deny-by-default outbound policy. Permit named provider and service endpoints through an inspecting proxy or FQDN-aware firewall. Log DNS and proxy decisions. Block raw-IP destinations and unusual ports unless the workload has a documented need.<\/p>\n<p>This can be awkward with providers that change addresses or use shared delivery networks. The trade-off is real. An outbound path broad enough for every future integration is also broad enough for credential exfiltration and payload retrieval. Treat exceptions as reviewed architecture, not temporary firewall tickets that never expire.<\/p>\n<h3>5. Runtime access: inspect sockets, mounts and metadata<\/h3>\n<p>Search deployment definitions for Docker or containerd sockets, host paths, privileged mode, host networking and broad service-account tokens. Block cloud metadata access unless the workload needs it. Where orchestration requires container creation, move that capability into a separate worker pool with narrow admission rules and no unrelated workloads on the same runtime.<\/p>\n<p>A useful control-plane review ends with a diagram that shows both API calls and privilege transitions. If the diagram stops at \u201ccontainer\u201d, it has probably stopped one boundary too early.<\/p>\n<h2>A 60-minute defensive review<\/h2>\n<p>A team can find the largest gaps without rebuilding the platform. Pick one production AI gateway, retrieval service or workflow engine and collect five pieces of evidence:<\/p>\n<ol>\n<li><strong>Reachability:<\/strong> the current ingress, listener and authentication configuration for every management route.<\/li>\n<li><strong>Runtime identity:<\/strong> the service account, UID, capabilities, writable mounts and expected child processes.<\/li>\n<li><strong>Secret map:<\/strong> provider keys, master tokens, database permissions, virtual keys and metadata-derived credentials available to that identity.<\/li>\n<li><strong>Outbound policy:<\/strong> the effective destination allowlist plus DNS, proxy and denied-connection logs.<\/li>\n<li><strong>Runtime boundary:<\/strong> sockets, host mounts, metadata access and worker isolation.<\/li>\n<\/ol>\n<p>Then ask one incident question: if the main process executes an attacker-controlled command, what is the maximum reachable consequence before another control stops it?<\/p>\n<p>Do not answer with a CVSS score. Follow the identity into the database. Follow the environment into provider accounts. Follow the socket into other containers. Follow the egress policy to its actual enforcement point. The first honest map is often uncomfortable, which is exactly why it is useful.<\/p>\n<h2>Patch now, then reduce the next blast radius<\/h2>\n<p>Teams running the affected products should compare deployed versions with current vendor advisories. LiteLLM fixed CVE-2026-42271 in 1.83.7. Starlette fixed CVE-2026-48710 in 1.0.1. Kestra fixed CVE-2026-49869 in 1.0.45 and 1.3.21. RAGFlow operators should review the project\u2019s security advisories against the exact release and deployment, especially when self-registration, agent workflows or user-controlled templates are available.<\/p>\n<p>Version checks need an image digest or package inventory, not a deployment manifest alone. A manifest can say <code>latest<\/code> while the node still runs an older cached image. Record the digest, package version and restart time. If exploitation is suspected, patching should follow evidence preservation and credential rotation. Replacing the vulnerable container does not revoke provider keys or remove an attacker\u2019s database access.<\/p>\n<p>After patching, keep the child-process, secret-access and egress detections. The next entry point may be a different endpoint, stolen API key or compromised dependency. Architecture controls continue to work when the CVE number changes.<\/p>\n<h2>Frequently asked questions<\/h2>\n<h3>What is an AI gateway?<\/h3>\n<p>An AI gateway is a service between applications and model providers. It can route requests, enforce policy, issue virtual keys, track budgets, select models and store provider configuration. Those functions often give it access to high-value credentials and databases.<\/p>\n<h3>Why call it a privileged control plane?<\/h3>\n<p>The service decides how requests reach models and workflows, and it commonly holds the identities needed to make those decisions real. Compromise can therefore affect downstream providers, databases, tenants and execution environments rather than one isolated web process.<\/p>\n<h3>Were the LiteLLM, RAGFlow and Kestra attacks caused by AI models?<\/h3>\n<p>Microsoft\u2019s report describes attacks on the software infrastructure around AI workloads. The observed chains used familiar weaknesses in web authentication, template handling, process execution, secrets and container configuration. The models themselves were not the central exploitation target.<\/p>\n<h3>What should defenders monitor first?<\/h3>\n<p>Start with unexpected child processes from the gateway or orchestration service, direct reads of container environment data, access to provider-key or virtual-key stores, execution from temporary paths, runtime-socket access and outbound connections outside approved provider destinations.<\/p>\n<h3>Is patching enough?<\/h3>\n<p>Patching closes known software flaws. It does not reduce an over-privileged service account, long-lived provider keys, unrestricted egress or a mounted Docker socket. Those controls determine the damage available after the next successful entry.<\/p>\n<h2>The decision to make now<\/h2>\n<p>AI infrastructure is joining identity providers, CI\/CD systems and cluster orchestrators in the small group of services that can turn one application failure into many downstream failures. The sensible response is not a new category of AI fear. It is an accurate privileged-systems inventory.<\/p>\n<p>Find every gateway, retrieval platform and workflow engine that can reach model keys or execute work. Put its real authority on the diagram. Then design for the day its main process is no longer trustworthy. That review will remain useful long after CVE-2026-42271 and CVE-2026-49869 disappear from the news.<\/p>\n<h2>Primary sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.microsoft.com\/en-us\/security\/blog\/2026\/08\/26\/when-ai-infrastructure-becomes-target-securing-gateways-control-points\/\" rel=\"nofollow noopener\" target=\"_blank\">Microsoft Security Research, \u201cWhen AI infrastructure becomes the target: Securing gateways and control points\u201d<\/a>, 26 August 2026.<\/li>\n<li><a href=\"https:\/\/github.com\/BerriAI\/litellm\/security\/advisories\/GHSA-v4p8-mg3p-g94g\" rel=\"nofollow noopener\" target=\"_blank\">LiteLLM maintainer advisory for CVE-2026-42271<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/advisories\/GHSA-86qp-5c8j-p5mr\" rel=\"nofollow noopener\" target=\"_blank\">Starlette maintainer advisory for CVE-2026-48710<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/infiniflow\/ragflow\/security\/advisories\/GHSA-wpg4-h5g2-jxm6\" rel=\"nofollow noopener\" target=\"_blank\">RAGFlow maintainer advisory for CVE-2026-45312<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/infiniflow\/ragflow\/security\/advisories\/GHSA-vvwj-fvwh-4whx\" rel=\"nofollow noopener\" target=\"_blank\">RAGFlow maintainer advisory for CVE-2026-28797<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/kestra-io\/kestra\/security\/advisories\/GHSA-5vc5-wxxq-3fjx\" rel=\"nofollow noopener\" target=\"_blank\">Kestra maintainer advisory for CVE-2026-49869<\/a>.<\/li>\n<li>Continue with my <a href=\"https:\/\/www.0xprathamesh.com\/writeups\/\">authorised security write-ups<\/a> for practical attack-path methodology.<\/li>\n<\/ul>\n<p><!--0XPRATHAMESH-CTA--><\/p>\n<h2>One next action<\/h2>\n<p>If you run an agent that executes tools, <a href=\"https:\/\/github.com\/prathamesh-ops-sudo\/AgentCrash\" target=\"_blank\" rel=\"noopener noreferrer\">AgentCrash<\/a> is an open-source harness that crash-tests it in a synthetic workplace: synthetic tools, visual evidence and regression tests. It is built for exactly this problem, turning a containment claim into something you can run against the system instead of arguing about it in review.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Real LiteLLM, RAGFlow and Kestra compromises show why AI gateways need control-plane security, not ordinary application hardening.<\/p>\n","protected":false},"author":0,"featured_media":15,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[14,18,17,15,16,19],"class_list":["post-16","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-notes","tag-ai-gateway-security","tag-cloud-security","tag-kestra","tag-litellm","tag-ragflow","tag-security-operations"],"jetpack_featured_media_url":"https:\/\/www.0xprathamesh.com\/blog\/wp-content\/uploads\/2026\/08\/0xprathamesh-85f9b0252b23-featured.jpg","_links":{"self":[{"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":1,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":100,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/posts\/16\/revisions\/100"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/media\/15"}],"wp:attachment":[{"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.0xprathamesh.com\/blog\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}