GerriScary: Hacking the Supply Chain of Popular Google Products (ChromiumOS, Chromium, Bazel, Dart & More)

Tenable Cloud Research discovered a supply chain compromise vulnerability in Google's Gerrit code-collaboration platform which we dubbed GerriScary. GerriScary allowed unauthorized code submission to at least 18 Google projects including ChromiumOS (CVE-2025-1568), Chromium, Dart and Bazel, which are now remediated. Third-party organizations that use Gerrit may also be at risk from GerriScary.
TL;DR
- Tenable Cloud Research discovered GerriScary, a way to infiltrate Google’s software supply chain by exploiting misconfigured permissions in Gerrit, Google’s open-source code-review system used across many major Google projects.
- At least 18 Google projects were found to be exposed, proving that open collaboration without strong safeguards is a serious security concern - even for tech giants. The affected Google projects include, among others, ChromiumOS (CVE-2025-1568), third-party Chromium packages, Dart and Bazel.
- Gerrit, developed by Google, is used both internally at the company and by the wider open-source community. While affected Google projects have been fixed, other projects may still remain vulnerable to the attack.
- Organizations that use Gerrit should check their projects’ permissions to confirm they are not exposed.

The vulnerability

ChromiumOS code injection proof-of-concept (POC)
Gerrit is an open-source, web-based code collaboration and review system developed by Google. It allows developers to propose, discuss and approve code changes before they are merged into large-scale software projects.
GerriScary, discovered by Tenable Cloud Research, is a supply chain compromise vulnerability in Gerrit’s projects that allowed any registered user to push code changes to many of Google’s projects. Registration to Gerrit is open to anyone.
By exploiting misconfigurations in permissions and the voting system’s label handling, attackers could have executed malicious code without user interaction, enabling supply chain attacks.
Moreover, attackers could have exploited a race condition with bot code-submission timings to push a change, leading to a 0-click malicious code push to the vulnerable projects.
Affected projects that haven’t mitigated this vulnerability are susceptible to a supply-chain attack due to excessive default permissions and logic flaws in the code-review process. For projects with vulnerable configurations in place, attackers can inject malicious code into trusted build pipelines.
A number of Google projects were affected, including ChromiumOS, third-party Chromium packages, Bazel and Dart. For a full list of affected packages please see Appendix A.
By default, Gerrit contains a default permission (“addPatchSet”) that allows any registered user to modify existing code change suggestions. In addition to this permission, some of the vulnerable projects contained a logic flaw in the patch set approval process that caused new patch sets not to require new code reviews and approvals as intended. This flaw allowed a risky scenario where a legitimate code change approved by trusted developers would remain trusted and approved even when malicious code is pushed by an attacker - without requiring any re-confirmation or approval.
Google and the ChromiumOS team changed the label persistence configuration across patch sets in the vulnerable projects to mitigate the issue.
The ChromiumOS team also pushed a change to limit the “addPatchSet” permission to trusted contributors.
Technical details
Background and basic Gerrit terms
Our GerriScary discovery began when, during another research project, we stumbled upon the following link: https://chromium.googlesource.com/
The source code of the open-source product in that specific case, Chromium, was present in the googlesource.com domain. Users can easily access the corresponding Gerrit project through the “Code Review” button in this domain while logged in to a Google account.
Just like Chromium, there are many projects with corresponding subdomains that Google hosts, such as dart.googlesource.com and its corresponding Gerrit system dart-review.googlesource.com.

Gerrit: Dart project
Since anyone can register, we registered, and logged in with our Google account. The natural attacker’s question arises: What can a registered user do in Gerrit? We tried to create a code change, to see if we could push it. As expected, it failed.
After reading Gerrit’s documentation, we got more clarity on the terms. From Gerrit’s documentation on patch sets:
“As described in Changes, a change represents a single commit under review. Each change is assigned a Change-Id. It is very common to amend a commit during the code review process. Gerrit uses the Change-Id to associate each iteration of the commit with the same change. These iterations of a commit are referred to as patch sets. When a change is approved, only the latest version of a commit is submitted to the repository.”
Basically, each patch set is a new commit version.
Gerrit’s access control
Permissions and labels
Gerrit’s security model revolves around two key technical structures: permissions, which define who can perform actions; and labels, which define what approvals are required before code changes can be merged into a project.
Permissions are enforced based on Git references, such as refs/heads/*, refs/for/*, and refs/meta/* — and they dictate actions like reading, pushing, submitting and editing changes. Permissions are granted to groups, and those groups can be globally defined, such as Registered Users, or locally scoped to the project or even to the change itself.
For example, a commonly configured permission is “addPatchSet”, which, when granted, allows a user to upload a new patchset to an existing code change, even if that change was created by someone else.
The voting system (labels)

An example of active code change
The second mechanism, labels, also known as “Submit Requirements,” are metadata scores applied during the code review process. Labels are declared in the project’s configuration and typically include fields like “Code-Review” and “Verified.” Each label has a defined scoring range. For example, “Code-Review” may allow scores from -2 (strong disapproval) to +2 (final approval), while Verified might allow -1 and +1 to represent test failures or passes. Labels serve as gates: for a change to be eligible for submission, it must satisfy the label rules set in the project configuration.
Permissions and labels are managed in a configuration file called project.config. This file specifies the permissions granted to users for each project.
Each permission rule in project.config follows a structure like this:
[access "refs/heads/*"]
label-Code-Review = -2..+2 group Registered Users
submit = group Project Owners
push = group Registered Users
The example above demonstrates a highly permissive configuration: any registered user—a user who merely created a Gerrit account - could push changes directly to the refs/heads/* namespace and decide on a “Code-Review +2.”
Component 1: Free addPatchSets
The interesting fact about permission handling in Gerrit is the following quote from Gerrit’s documentation, referencing the “addPatchSet” permission:
“By default, this permission is granted to Registered Users on refs/for/*, allowing all registered users to upload a new patch set to any change. Revoking this permission (by granting it to no groups and setting the "Exclusive" flag) will prevent users from uploading a patch set to a change they do not own.”
That default sounds reasonable since Gerrit is a community-based system > However, it probably can open the door to more attacks, like GerriScary.
We checked these defaults and it seems like they are present in many Google projects.
Component 2: The “woah” moment
When pressing the “Reply” button on code changes to try and add votes and affect the voting system, we did not have enough permissions to upvote any submission requirements:

No permissions to vote on any submit requirement
So we wondered: What if we find a code change that has already been approved and has its submission requirements satisfied and then add our malicious code with “addPatchSet”? What will happen to the submission requirements? Surprisingly, in some cases, nothing.
We discovered that we can abuse a Gerrit mechanism called “Copy Conditions”. Turns out that the vulnerable Google projects are configured to copy their labels to additional patch sets. “Copy Conditions” in Gerrit define whether label scores from prior patch sets are retained on new revisions, based on the nature of the change, such as unchanged code or purely metadata edits. Label scores also play a crucial role in determining if a change must be re-reviewed.
The “Copy Conditions” rules are pretty complicated to write and understand, which might be the reason they made the affected projects vulnerable.
The affected projects had misconfigured “Copy Conditions” in place that allowed us to add our malicious patch sets and retain the submit requirements. Alarmingly, this resulted in a code change that contained malicious code and was fully approved.
In submittable code changes, all of the submit requirements and label scores are completed or fulfilled. We were able to find submittable code changes by using Gerrit queries and scraping. For example:

Using Gerrit queries to find submittable code changes
Component 3: Completing the attack chain
The final step to merge a code change is to submit it successfully. Most projects we observed handle verified code-change submissions with automated bots, and some of them are handled by developers who have to press “Submit” to submit the verified code change. When a developer presses “Submit,” a bot will merge the code change.

The Commit Queue bot merges the code change
In most cases, we did not have the “Submit” permission. Sometimes the bot pushed the code change seconds after the code change was verified, and sometimes it took minutes, or hours, which allowed eagle-eyed developers to stop or block the malicious code-push attempt.
We wanted to minimize this window to zero, resulting in a full supply-chain compromise without any user interaction by the victim.
The solution: Research the submission process and race it
We discovered we can successfully race the automated bot submission. A race condition attack happens when two or more things try to happen at the same time, and the outcome depends on who finishes first.
Here’s how we did it.
Gerrit project maintainers can create custom labels. Google has its own custom label named “Commit-Queue”. In Google's setup, a vote of “Commit-Queue+2” instructs an automated bot to finalize and submit the code change.
When the "Commit-Queue" label in particular is equal to 2, it signals to the automation bot to submit a merge and the bot eventually merges the change. Some of these bots' operations can be observed by looking at merged change logs.
Let’s use this as an example: https://dart-review.googlesource.com/c/sdk/+/392640
In this specific case, a bot named Commit-Queue - [email protected] has pushed the change. We have not yet observed a repository that operates differently.
This is the exact timing delay attackers can abuse: The race window from a “Commit-Queue” to a successful bot submission. As an example, it’s five minutes in ChromiumOS and in Dart repositories, and seconds to a minute on other Google repositories:

Example of the five-minute time difference between the Commit Queue vote and an actual merge
The “Copy Conditions” logic flaw can be abused to get the race, as mentioned. This setting includes labels like "Code Review", but also controls custom labels like the "Commit Queue" label that Google uses in its Gerrit instances.
Given this configuration, any modified code that retains “Submit Requirements” can lead to a full chain of malicious code pushed to the vulnerable repositories, without any user interaction at all.
Attackers could look for submittable code changes that were also labeled “Commit-Queue +2”, and race the bot submission by adding a malicious patch set just before it merges the code change.
Full chain explanation
Here’s what happens on ChromiumOS when you abuse these three components:
- Default “addPatchSet” permission granted to registered users
- Unsafe labels’ “Copy Conditions” logic on vulnerable projects
- Race window from commit queue vote to bot submission and an unsafe custom “Commit-Queue” label copy condition logic
Attackers can write a scraper or query the Gerrit API with automation to hook changes that have a submittable status, and have been labeled “Commit-Queue +2”. When the exploit code detects such a change, it will modify the change's code with the “addPatchSet” permission, and inject malicious code into the change, all of whose submit requirements have been verified and fulfilled. Since the change was already voted “Commit-Queue +2”, it's a matter of 5 minutes in ChromiumOS and in Dart repositories as an example, and seconds to a minute on other Google repositories, until the change is merged by the bot, including the malicious code. This is the exact race window the attacker has - between the commit-queue +2 vote, to the bot actually submitting the change.
This “Copy Conditions” misconfigurations allows for abusing the “addPatchSet” permission which is granted by default to registered users, to inject malicious code into a change without a vote reset. Because of that, although we did not confirm it specifically as a precaution, it is highly likely that the copyCondition logic for the "Commit-Queue" label is similarly misconfigured to copy votes across patch sets.
Mass scanning of Google projects by developing a custom fuzzer
Since we do not have permission to view the config of each Gerrit project (project.config file), we opted to dynamically scan Google’s Gerrit projects, without disrupting the projects.
We discovered a fingerprinting technique in Gerrit that allowed us to determine whether we have the “addPatchSet” permission on a project. By analyzing the HTTP response status code of a request to modify a commit message, we observed that a successful request—when properly authorized—returns a “200 OK” status, which is expected.

Commit message example is marked in red
However, sending commit message modification requests to many projects is both noisy and inefficient. We found that submitting the same commit message that is already present in a modification request returns a “209” status code (can be used as a fingerprint) if we have the required permission. Using this method, we were able to scan Google’s Gerrit projects and identify many affected ones.
More attacks
We discovered some Google projects that allow denial of service and disruption of code changes; modifications by registered users such as removing and adding code change CCs (carbon copy) and reviewers; and messing with submit-requirement votes to deny code changes from being pushed:

Proof of concept
To support the vulnerability disclosure, we created POCs on ChromiumOS, Dart, and two third-party packages of Chromium: Dawn and BoringSSL. To avoid disruption, we did not live test the race condition component, but we did test uploading an innocent comment to some Google projects. These allowed us to prove the impact of GerriScary, while following ethical research rules.
One comment we added to a random file in a ChromiumOS project was actually pushed, and can be seen on the ChromiumOS code search tool as a valid POC for our findings:

ChromiumOS code injection POC
Vendor response
Google fixed the label-persistence configuration (“Copy Conditions”) in the affected projects. This change ensured that new patch sets now require fresh code reviews and verifications by developers, preventing previously approved labels from carrying over without re-evaluation.
The ChromiumOS team also decided to remove the “addPatchSet” permission from the Registered Users group, and to only give the permission to trusted contributors.
These proactive steps were part of Google's commitment to maintaining the security and integrity of its systems.
While these Google-managed projects have been secured, other projects utilizing Gerrit may still be vulnerable and should apply secure configurations to mitigate potential risks.
Appendix A - List of Google Projects Vulnerable to GerriScary
https://chromium-review.googlesource.com/c/chromiumos - (ChromiumOS)
https://dart-review.googlesource.com/ - (Frontend language, the backbone of Flutter apps)
https://dawn-review.googlesource.com/ - (3rd party Chromium dependency)
https://boringssl-review.googlesource.com/ - (3rd party Chromium dependency)
https://gn-review.googlesource.com/ - (Build system of Chromium, Fuchsia, and related projects)
https://bazel-review.googlesource.com - (Google's build engine)
https://gerrit-review.googlesource.com/#(/zull/jobs) - (Gerrit itself, /zull/jobs and /gcompute-tools specifically)
https://ceres-solver-review.googlesource.com/ - (C++ library)
https://code-review.googlesource.com/ - (Includes a Git mirror)
https://quiche-review.googlesource.com - (Google's production-ready implementation of QUIC, HTTP/2, HTTP/3, and related protocols and tools)
https://android-kvm-review.googlesource.com/ - (Virtualized Android runtime)
https://opensecura-review.googlesource.com/ - (AI hardware backbone)
https://cue-review.googlesource.com/ - (Data validation language)
https://linux-review.googlesource.com/ - (Open-source operating system)
https://plan9port-review.googlesource.com/ - (Unix with Plan 9 utilities)
https://hafnium-review.googlesource.com/ - (Supplies memory isolation)
https://nginx-review.googlesource.com/ - (High-performance web server)
https://weave-review.googlesource.com/ - (Network application layer protocol)
- Cloud
- Cloud