Hoplon InfoSec
24 Apr, 2025
In early 2025, security researchers uncovered a serious privilege-escalation vulnerability in the Google Cloud Platform (GCP) that they dubbed “ConfusedComposer.” This flaw resided in Cloud Composer, Google’s managed workflow orchestration service powered by Apache Airflow. It would have allowed an attacker with only minimal permissions to seize control of a highly privileged service account. With that foothold, they could have mounted project-wide attacks, accessed sensitive data, and disrupted mission-critical pipelines.
Over the past decade, enterprises have flocked to managed cloud services to streamline operations, automate DevOps, and scale data processing. However, as organizations stitch together dozens of services, each with its service account and permission model, the risk of misconfiguration and unexpected interactions grows. ConfusedComposer is a textbook example: a seemingly innocuous feature (installing a custom Python package) inadvertently granted attackers a path to total compromise. In this post, we’ll trace the root cause of the vulnerability, explore the technical exploitation steps, detail Google’s remediation, and consider broader lessons for cloud security teams.
Cloud Composer is Google’s fully managed implementation of Apache Airflow, a popular open-source platform for authoring, scheduling, and monitoring complex data pipelines. Data engineers define directed acyclic graphs (DAGs) of tasks—extracting data from sources, transforming it, and loading results into data warehouses. Composer manages the underlying Kubernetes cluster, Airflow servers, and integrations with services such as Cloud Storage, BigQuery, and Pub/Sub, freeing teams from operational overhead.
To support specialized data transformations, Composer allows users to specify custom Python packages (hosted on PyPI or private repositories). When you update an environment to include new dependencies, Composer automatically spins up a Cloud Build job behind the scenes. That job packages and installs the requested modules into the environment’s worker images. From a developer’s perspective, it’s a seamless way to extend Airflow with third-party or in-house libraries.
In GCP, every managed service runs under one or more service account identities with associated IAM roles. Cloud Composer uses two key accounts:
The security gap emerged because Composer delegated the custom-package installation step to Cloud Build, crucially doing so under the Cloud Build service account rather than the more restricted environment account. As a result, any code that ran in that build inherited powerful permissions.
Tenable researchers categorize ConfusedComposer as a “Jenga” attack: adversaries exploit the stacking of services and permissions that cloud providers assemble automatically. Last year’s “ConfusedFunction” vulnerability similarly abused interactions between Cloud Functions and Cloud Build. In both cases, attackers topple the misconfigured stack, gaining leverage far beyond their initial privileges.
To exploit ConfusedComposer, an attacker only needs to possess the Composer’s environment and update permission in a target project. That permission is often granted to DevOps or data-engineering roles responsible for updating DAG definitions and dependencies. In many organizations, those roles are widespread, significantly lowering the bar for exploitation.
The adversary publishes a trojanized Python package, called evil-pkg, to a public (or private) PyPI repository. This package includes a setup.py script that runs arbitrary code during installation (leveraging Python’s “pre-install” and “post-install” hooks). The attacker then issues a standard Composer environment update, adding evil-pkg to the list of custom dependencies.
When Composer processes the update, it triggers a Cloud Build job in the victim’s project. That build fetches evil-pkg and, in the course of installing it, executes the malicious setup script. Inside the build container, that script runs with the Cloud Build service account’s credentials.
The script contacts the Cloud Build metadata server, retrieves the service account token, and exfiltrates it to an attacker-controlled endpoint. With that token in hand, the attacker can call any GCP API that the Cloud Build account is authorized to use.
By default, the Cloud Build service account holds roles such as:
Armed with those roles, the attacker can read or overwrite data in storage buckets, deploy new container images, spin up VMs, or even grant themselves further IAM privileges. What began as a minor environment update morphs into a complete project compromise.
In April 2025, Google rolled out a patch that changes which identity performs PyPI installations. Rather than invoking Cloud Build under its powerful service account, Composer now configures the build to run as the much more restricted Composer environment service account. That account only has permissions explicitly granted to the user’s environment, effectively removing the attacker’s path to high-impact roles.
Google has already applied this fix to all new Composer environments. Existing environments will receive the update automatically by the end of April 2025. No customer action is required to use the patch, though organizations should verify their environment version to confirm the change has taken effect.
Alongside the technical fix, Google revised Composer’s documentation in three key areas:
Cloud security teams should revisit their IAM policies to ensure the update of Composer environments. It is tightly scoped, ideally for a small set of trusted operators. Wherever possible, custom-package installation should be limited or subjected to code-review gates in CI/CD pipelines.
Managed cloud services often orchestrate multiple back-end components without overtly exposing them. In this case, Composer’s UI never mentions Cloud Build; users click “Install packages” and expect dependencies to appear. But under the hood, Composer delegates to Cloud Build, and that hidden linkage almost led to a catastrophic privilege jump.
Cloud architects must map not only the services they directly consume but also the ancillary services those platforms invoke on their behalf. Drawing a complete service dependency graph can reveal surprising “trust chains” that warrant tighter controls or monitoring.
Least privilege is more than assigning narrow IAM roles to human users; it requires ensuring that every automated component, from build services to managed pipelines, carries no more permissions than is strictly necessary. In practice, this means:
For environments running dynamic code, such as custom Python packages, consider introducing an approval workflow or sandbox testing phase before dependencies reach production.
The Jenga metaphor aptly captures the risk: every new service or permission is another block in the tower. A tower that looks stable at a glance can wobble if one misplaced block undermines the entire structure. Security teams should simulate scenarios where low-privileged actions trigger high-privileged processes, identifying and shoring up weak points before attackers do.
The ConfusedComposer vulnerability underscores a paradox of managed cloud offerings. They abstract away complexity and reduce operational burden, but that very abstraction can mask dangerous interactions. As cloud adoption accelerates, organizations must pair the convenience of managed services with rigorous service-account hygiene, threat modeling, and documentation review.
Google’s swift patch and documentation updates have closed the immediate gap in Cloud Composer. Yet the broader challenge remains: ensuring that every invisible handoff between services respects the principle of least privilege. By treating managed-service orchestration as part of their attack surface, cloud security teams can build more resilient architectures—ones, where a simple package install no longer, holds the keys to the castle.
Share this :