Check D6 · execution family · automatic · one of the 11 Docker Desktop checks
The question this check asks: what does this extension say it will install onto the host — which files, for which operating systems? Listed from the extension's own metadata.json, read out of the image without pulling it; the files themselves are not fetched, not read and not run.
A Docker Desktop extension is a container image, but part of it does not stay in a container. Docker's architecture page: "Executables are binaries or shell scripts that are installed on the host when the extension is installed." The host section of metadata.json "defines executables that Docker Desktop copies on the host", and its binaries list is what Docker Desktop copies "from the extension image to the host" — one entry per operating system, each with a path inside the image. The extension's dashboard tab then runs them through the SDK's ddClient.extension.host.cli.exec. That is a native program on your machine, launched by a web page inside Docker Desktop.
It runs as you. Docker's SDK security page, rewritten on 10 October 2025: "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." The CLI's own confirmation before docker extension install says the same in one line — "Extensions can install binaries, invoke commands and access files on your machine. Are you sure you want to continue? [y/N]" — and is skipped with -f; the Marketplace tab has no per-capability prompt at all.
And the list is not a limit. The same SDK page: "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 rewrite removed the older sentence that "Only executables shipped as part of the extension can be invoked with the SDK." SensePost had demonstrated the gap on 30 May 2023 — "Extensions can execute arbitrary operating system commands, even if there isn't a specific binary shipped with the extension" — and Docker's response then was that "this is a non-issue"; it never received a CVE, and the documentation now describes it as designed. So host.binaries is the declared surface. An empty list is not the absence of native code, and this page says so before the scoring does. No malicious Docker Desktop extension has been publicly reported as of 18 September 2026; the threat model here is Docker's own words about what an extension is allowed to do.
The file comes out of the registry without a pull. RepoGates takes a registry pull token, reads the OCI index, picks the linux/amd64 manifest, and fetches the config blob and the twelve smallest layers in parallel — each at most 512 KB, 3 MB across all of them. The Extensions SDK's build makes a layer per COPY, so metadata.json sits in its own layer of 200 to 1,700 bytes; Tailscale's image has sixteen layers and the file was in the tenth-smallest. Each small layer is opened as a tar archive and searched for that one name. A 502 MB image (mochoa/sqlcl) is read for a few kilobytes, and no image is ever pulled. The registry counts every manifest GET against an anonymous budget of 100 an hour per address, two per extension; RepoGates keeps a floor on that budget and takes a read-only Docker Hub token of its own when one is configured.
One row per declared binary, every operating system, dde-host-binary:<os>:<path>, capped at three rows. The severity depends on one thing: whether the extension is listed and established — in Docker's Marketplace index (D5) and with a Hub repository at least 90 days old (dde_established_days). In that state each row is INFO, 0 points, and reads "installs a native executable onto the developer's machine — half the listed marketplace does; noted". Otherwise it is HIGH, 14 points, and reads "— on an image that is unlisted or new". The evidence note:
"D6; native code installed onto the host — half the listed marketplace does it (note); HIGH on an unlisted or new image"
A metadata.json with no host section is known-empty: the check ran and found nothing. A metadata.json that was not among the twelve smallest layers is unknown: the scan notes "extension metadata unavailable", D6 and D7 are reported as not checked rather than passed, and the scan is partial — it is retried, never cached as a PASS. There is no signature check, because none of the twelve images sampled from the marketplace carries a cosign signature; a check that fired on every image would say nothing.
The verdict engine is the one behind all 11 checks: any CRITICAL finding is a BLOCK, any HIGH or MEDIUM finding is a REVIEW, and a report with nothing above INFO is a PASS. The score is 100 minus every fired penalty, floored at zero — green at 80 and above, amber from 50 to 79, red below 50 — so a new image declaring three binaries and nothing else reads REVIEW at 58, amber. What the preflight does before docker extension install runs is the profile's decision: personal-default maps HIGH to warn, an ask; org-strict names dde-host-binary explicitly and also maps it to warn — an ask, not a deny, because half the marketplace ships them and the deny for an unlisted image already comes from D5. D6 feeds three dimensions: Open in an editor (D6, D7, D9), Install and run (D5–D7, D9) and Hand to an AI agent (D6, D7, D11), each taking the worst of its checks and reading PASS only when every one of them ran.
The grading exists because the measurement demanded it. Measured 18 September 2026 against all 50 listed extensions: 50 PASS, 0 REVIEW, 0 BLOCK; 21 declare host binaries, 29 a VM backend, 12 of those mount the Docker socket; 39 come from a publisher with no Hub badge; 33 have not been pushed in a year. Tailscale declares six — hostname and host-tailscale for darwin, hostname.cmd for windows, and so on — which the cap shows as three rows. The twelve-image sample had Meshery's mesheryctl for three operating systems, Lens's kubeconfig-writer-macos and Docker's own killlogs.sh. Every one of the 50 is listed and at least 853 days old, so every one of the 21 is a note. Weighted HIGH regardless of state, D6 alone would have turned 21 of the 50 into REVIEW, on a marketplace where half the extensions do exactly this by design.
Where the cost lands is stated rather than hidden. A genuinely new extension that ships a helper binary reads REVIEW on this check for its first 90 days — and an unlisted one for as long as it stays unlisted, which, with submissions paused, is indefinitely. On this frozen marketplace D6 is a note-taker; the same shape becomes a finding the moment the image is off the index or its Hub repository is under 90 days old, and that is the trade the weights make.
What the binary does. D6 knows a path and an operating system, nothing more: the file is not fetched, not hashed, and there is no signature to verify. What is not declared. Docker's own SDK page says execution is not restricted to the listed binaries, and the UI can run commands through the SDK without shipping any file; an extension with no host section still runs with your permissions, and this check reads only the declaration. More than three. Rows are capped at the first three declared, so Tailscale's six show as three. A file that was not there to read. When metadata.json is not among the twelve smallest layers, D6 is skipped and says so.
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.
The Hub page does not show metadata.json. RepoGates reads it from the registry's smallest layers; without that code the honest route is to pull the image — which RepoGates never does — and copy the file out of a container that is created but never started:
docker pull OWNER/NAME
id=$(docker create OWNER/NAME)
docker cp "$id":/metadata.json ./metadata.json
docker rm "$id" >/dev/null
jq '.host.binaries' metadata.json
What comes back is the declared list, per operating system. After an install, docker extension ls shows a HOST column — whether the extension runs a backend container or has deployed binaries to the host. Then check both halves of "listed and established": the index for the reference (D5) and date_registered on the Hub record (D2):
curl -s https://desktop.docker.com/extensions/marketplace.json \
| jq -r '(.extensions // .)[]' | grep -ix 'OWNER/NAME'
curl -s https://hub.docker.com/v2/repositories/OWNER/NAME/ | jq '{date_registered, last_updated}'
Three worked references: tailscale/docker-extension declares six binaries — three rows, all notes; docker/disk-usage-extension has no host section — no rows; library/nginx, which is no extension, has no metadata.json to read — D6 not checked, and its REVIEW 64 comes from provenance. RepoGates itself: GET /v1/dde/score/OWNER/NAME with a personal API token (Authorization: Bearer rgp1.…), check_repo("OWNER", "NAME", platform="dde") on the MCP server, or docker extension install OWNER/NAME typed in Claude Code with the plugin installed, where the preflight answers before the line runs.
Why is a host binary only a note on a listed extension? Because it is the platform's ordinary shape. In the 18 September 2026 measurement of all 50 listed extensions, 21 declare host binaries: Tailscale six of them, Meshery's mesheryctl for three operating systems, Lens's kubeconfig-writer-macos, Docker's own killlogs.sh. Weighted HIGH regardless, D6 alone would have turned 21 of the 50 into REVIEW. So each row is a note, no points, when the extension is listed and its Hub repository is 90 days or older, and HIGH at 14 points only on an unlisted or new image — where the same shape has earned nothing.
Does an empty host section mean the extension runs no native code? No, and Docker says so. Its SDK security page, rewritten on 10 October 2025, states that extensions are not restricted to execute binaries that they list in the host section of the extension metadata, and that they are executed with the same permissions as the Docker Desktop user. The same rewrite removed the older sentence that only executables shipped as part of the extension can be invoked with the SDK. SensePost had shown the same in May 2023. The host.binaries list is what the extension declares; D6 reads the declaration and nothing else.
Does RepoGates pull the image to read metadata.json? No. The Extensions SDK's build makes a layer per COPY, so metadata.json sits in its own layer of 200 to 1,700 bytes. RepoGates takes a pull token, reads the OCI index, the linux/amd64 manifest and the config blob, then fetches the twelve smallest layers in parallel — each at most 512 KB, 3 MB in total — and opens them as tar archives looking for one file. A 502 MB image is read for a few kilobytes. When metadata.json is not among those twelve, D6 and D7 are reported as not checked, which happened on one of the 50.
D7 VM backend — the other half of the install surface, read from the same file and graded the same way · D5 Marketplace listing — the switch that turns these notes into findings · V12 Package contents — the VS Code roster's listing of what executes inside a package, graded by age for the same reason · C15 Committed binaries — the GitHub roster's reading of native code in a tree.
Add RepoGates to Chrome Pricing
Numbers on this page: the 18 September 2026 measurement of all 50 extensions in Docker's Marketplace index, the twelve-image registry sample read the same day, and library/nginx as a control; Docker's own Extensions SDK documentation (security page, 10 October 2025; architecture and metadata pages); SensePost, 30 May 2023; weights from the product's scoring table.