A threat model, not a campaign · roster measured 18 September 2026 against all 50 listed extensions
What this is. No malicious Docker Desktop extension has been publicly reported — not in Docker's Extensions Marketplace, not sideloaded — as of 18 September 2026. Docker's own statement, from September 2024, is that "No existing extensions exploiting the vulnerabilities were found in the Extensions Marketplace", and nothing published since says otherwise. So this page is not a list of campaigns with names and hashes, as the VS Code and Hugging Face pages are. It is three things: what Docker itself documents an extension can do, what Docker itself has fixed and changed about extensions — up to pausing new Marketplace submissions on 16 June 2026 — and what our 11-check roster (D1–D11) reads and found when run against every one of the 50 extensions the Marketplace lists: 50 PASS, 0 REVIEW, 0 BLOCK, with no image pulled. Neither the absence of a reported incident nor the 50 passes is a guarantee — see "What this doesn't mean".
A Docker Desktop extension is a Docker Hub image. Its
metadata.json declares up to three parts: a
ui (a dashboard tab), a vm backend — "a
backend service that runs inside the Desktop VM", defined by an image
or a compose file — and host binaries, "executables that
Docker Desktop copies on the host". Docker's SDK security page, added
in October 2025, states the consequence without softening it:
"Extensions are executed with the same permissions as the Docker Desktop user. Extension capabilities include running any Docker commands (including running containers and mounting folders), running extension binaries, and accessing files on your machine that are accessible by the user running Docker Desktop."
"Note that extensions are not restricted to execute binaries that they list in the host section of the extension metadata: since these binaries can contain any code running as user, they can in turn execute any other commands as long as the user has rights to execute them."
The overview page's "Security and trust" section, added in April 2026, says the same in fewer words: extensions "run with elevated privileges on your host machine. They have direct access to the Docker Engine, can read and write files on your filesystem, and can install and run native binaries." Two further facts from Docker's own settings documentation shape the roster: containers created by extensions are "hidden from the list of containers in the Docker Desktop Dashboard and the Docker CLI" by default, and the backend's compose file may mount host paths, add privileges and mount the Docker socket — which is full control of the engine.
The research that put this together first is SensePost's "an
offensive look at docker desktop extensions" (Leon Jacobs, 30 May
2023, tested on Docker Desktop 4.19.0). Its findings, in its words: a
backend "can have more privileges than you would be comfortable to
give by adding extra port/volume/privilege labels to the extensions
docker-compose.yml file"; a malicious extension could omit
the UI and "have a service VM running without it being visible in
Docker Desktop"; and "Extensions can execute arbitrary operating
system commands, even if there isn't a specific binary shipped with
the extension" — a command injection Docker's security team called "a
non-issue" at the time, never assigned a CVE, and now described by
Docker's own documentation as the designed behaviour quoted above. Its
conclusion is the reason this roster exists: "Unless an extension
author makes their extension open source, the only way to see what it
is really doing is to manually inspect / reverse engineer the
extension itself."
Every entry below is from Docker's release notes, its security announcements page or its documentation's own change history; the CVE figures are the ones Docker filed as the numbering authority.
CVE-2023-0625 a year later.CVE-2023-5166,
"Access Token theft via a crafted extension icon URL".CVE-2024-6222, from
Pwn2Own: an attacker already inside the Docker Desktop VM "can
further escape to the host by passing extensions and dashboard
related IPC messages".CVE-2024-8695, "via
crafted extension description/changelog", rated Critical by Docker;
and CVE-2024-8696, "via crafted extension
publisher-url/additional-urls", rated High by Docker (NVD rates both
9.8 Critical). The first is the same field and the same class as the
2022 fix. Docker's advisory: "No existing extensions exploiting the
vulnerabilities were found in the Extensions Marketplace. The Docker
Team will be closely monitoring and diligently reviewing any requests
for publishing new extensions."What "reviewed" meant before the pause matters for
D1 and
D5. Docker's manual
review of extensions was paused on 9 January 2024 — "We are pausing
the extension manual validation process, and want publishers to go
directly to the automated submission form" — and from then until
June 2026 the gate was automated validation, which "checks if the
extension's Dockerfile specifies all the required labels
and if the metadata file is valid against the JSON schema file", plus
a Docker staff member adding a label to the submission. No security
criterion appears in either process. Docker's Marketplace page still
says it: "Marketplace extensions are reviewed by Docker, but are not
subject to a full security audit." And of anything outside the
Marketplace: "Extensions installed outside the Marketplace have not
been reviewed at all."
Three sources, all public. The Docker Hub API gives the repository
record (pull and star counts, registration date, last push), its
latest tag and the publisher's account (its badge, its join date).
Docker's marketplace index — desktop.docker.com/extensions/marketplace.json,
50 image references, frozen since the pause — answers whether the
image is listed at all. And the registry gives what the image
declares: a pull token, the OCI index, the linux/amd64 manifest, the
config blob with the listing labels, and then the twelve smallest
layers in parallel, because the Extensions SDK's build puts
metadata.json and the backend's compose file in their own
layers of a few hundred bytes. A 502 MB image (the SQLcl
extension, the largest listed) is read for a few kilobytes. No image is pulled, no layer
above 512 KB is fetched, and the code inside the image is never
read.
The gradings follow what the Marketplace actually looks like. On an extension that is listed and established (in Docker's index and at least 90 days on the Hub), a host binary, a VM backend, an unbadged publisher and a missing source label are notes — because, as the table below shows, that is the ordinary shape of the listed Marketplace. On an image that is not in the frozen index, or whose publisher joined the Hub recently, the same shapes are findings. Since the index cannot grow, an image not in it is sideloaded or private by definition, and D5 is the sharpest check on this platform.
Run on 18 September 2026 against all 50 listed extensions — the
whole Marketplace, 45 publishers — locally through the same code that
answers /v1/dde/score, anonymously against the registry,
in two halves of 25 because the registry allows 100 anonymous manifest
reads an hour: 50 PASS, 0 REVIEW, 0 BLOCK, no errors, no
partial scans, labels read on all 50, metadata.json read
on 49 (one extension's sits outside its twelve smallest layers, so its
D6 and D7 are listed as not checked). Median 3.1 seconds per
extension from Australia. The youngest listed repository is 853 days
old; the median is 1,447 days.
| What the roster found | Extensions (of 50) | Listed and established | Unlisted or new |
|---|---|---|---|
| Listed in Docker's index (D5) | 50 | INFO | HIGH — sideloaded or private |
| Publisher with no Hub badge (D1) | 39 | INFO | HIGH |
| Declares host binaries (D6) | 21 | INFO | HIGH per binary |
| Declares a VM backend (D7) | 29 | INFO | MED |
| … whose compose file mounts the Docker socket | 12 | INFO | HIGH |
| … joins the host network · adds capabilities · maps devices · runs privileged · binds a host path | 4 · 3 · 3 · 1 · 1 | INFO | HIGH each |
| No source repository in the labels (D8) | 23 | INFO | MED, or HIGH when new |
| Source declared — assessed through the 22 on the same pass | 27 (17 same owner, 10 another owner) | note: 25 REVIEW, 2 PASS, 0 BLOCK, none campaign-listed | HIGH on a BLOCK, CRIT when campaign-listed |
| Listing link to a site other than the publisher's, GitHub or Docker (D9) | 16 | INFO | INFO |
| Listing URL with a non-http scheme (D9) | 0 | HIGH | HIGH |
| Not pushed in over a year (D10) | 33 | INFO | INFO |
| Repository under 30 days · pulls without age · lookalike name (D2, D3, D4) | 0 | HIGH | HIGH |
Read plainly: half the listed Marketplace installs native code on
the host and more than half runs a backend in the VM, twelve of them
with the engine's socket mounted — Grafana's backend mounts the
socket, maps /dev/kmsg and binds the host's root
filesystem, /proc, /sys and
/var/lib/docker read-only; Tailscale's ships six host
binaries and joins the host network with NET_ADMIN and
/dev/net/tun; one, the Mesos extension, runs
privileged: true.
That is what the platform is for, and on a listed, four-year-old
extension the roster records it and moves on. Thirty-nine of the fifty
come from a publisher without Docker's verified-publisher or official
badge, Tailscale, Lens and ngrok among them, which is why the badge is
a note here and not a finding; and thirty-three have not been pushed in a year, which is
what a paused marketplace looks like from the inside. The 27 declared
source repositories were scored through the 22 GitHub checks on the
same pass: 2 PASS, none BLOCK, and 25 REVIEW on their own account —
six of them not assessable at all, because the repository the label
names no longer answers on GitHub (four of Docker's own among them),
the rest for a stale release, a missing licence, an archived
repository, a single contributor or a devcontainer — so
D8 carried each as a
note and none changed a verdict.
Two controls, run separately. library/nginx — a Docker
Hub image that is no Docker Desktop extension — comes back
REVIEW 64: not in the index, no verified badge on the
namespace, no source label; the sideloaded shape the roster is graded
for. And the fixture the test suite carries — an image not in the
index, from a publisher who joined the Hub last month, declaring a
host binary and a socket-mounting backend — is REVIEW on the personal
profile and BLOCK on org-strict, where an unlisted image is a
block.
Stated as inference, because there is no exemplar. An extension built to abuse the surface Docker documents would most likely arrive by image reference rather than through the frozen Marketplace, from a namespace created for it, and would declare — because the SDK makes it declare — a host binary or a backend beside the socket. That shape fires D5, D1 and D6 or D7 at HIGH, a REVIEW on the personal profile and a BLOCK on org-strict before anything is installed; a source repository that is campaign-listed is a BLOCK everywhere through D8. Since Docker Desktop 4.31.0 the same image needs the marketplace-only setting switched off first, and since 4.74.0 extensions themselves are off by default — two settings a person has to change, which is why the roster grades an unlisted image HIGH rather than CRIT.
What the roster would not see is what the binary or the
backend does. D6 lists
the executables the image declares, and Docker's own words above say
the list is not a limit; D7
reads the compose file's line shapes, not the container's behaviour.
A listed extension whose tag is repointed after we looked is a
separate case: Docker now installs Marketplace extensions by pinned
digest, and RepoGates scores the latest tag at the moment of asking,
so a verdict is about the image the tag named then. The HTML-bearing
description and changelog labels behind the 2022 and 2024 fixes are
not assessed at all. Reading the image is a deep scan, decided and not
started on the roadmap; until it
exists a PASS here means the provenance and the declared install
surface show none of what these checks look for, never that the
image's contents were inspected. There is no image-signature check
either: none of the sampled Marketplace images carries a cosign
signature, so a check for one would fire on all fifty and tell a
reader nothing. And no platform: dde entry exists in
RepoGates' campaign blocklist, because there is nothing to list.
Docker's own words: Marketplace extensions "are not subject to a full
security audit", and Docker "does not guarantee the security of any
extension". Neither does this page. An extension that scores PASS
today was checked today, on its publisher, its listing, its declared
install surface and its declared source — never a claim that its
binaries or its backend are benign, never a claim about the tag it is
repointed to tomorrow. RepoGates assesses a Docker Desktop extension
on request — through the API, the MCP server
(platform="dde") and the preflight for
docker extension install. It does not see an extension
installed from Docker Desktop's own Extensions Marketplace tab, which
is the app's own fetch; the board inside Docker Desktop is not built,
and cannot be — its marketplace is a native window no browser
extension sees. The image is never pulled and its code is not read: a
PASS means the provenance and the declared install surface are clean,
never that the backend or the host binaries were inspected. Every one
of the eleven checks has its own page under
the docs, stating what it reads and what it does
not.