Skip to main content
•11 min read

Docker Security Dispatch — Issue 7: Authority as Code and Zombie Actions 🧟

DSD 7 covers Docker Sandbox Kits for AI agent permissions, zombie GitHub Actions re-enabled with malicious tags intact, Docker Hardened Image security policies, and the GlassWorm VS Code extension campaign.

DockerNewsletterSecuritySupply Chain SecurityAI AgentsSandbox KitsGitHub ActionsGlassWormDocker Hardened Images2026

The worm was dead. Or so we thought.

In May, GitHub disabled two malicious Actions compromised by Mini Shai-Hulud. In September, they came back from the dead. No new exploit. No new malicious release. Just the same poisoned code, waiting to run again.

Meanwhile, Docker introduced a new way to package AI agents together with the permissions they request. Apparently, we are giving our agents permission slips now.

Docker Security Dispatch 7

Welcome to Docker Security Dispatch 7, reviewing September 2026. This month: Docker Sandbox Kits, zombie GitHub Actions, security policies for container images, and a worm hiding inside your favorite VS Code theme.

Plus, my adventures at the Docker Captains Summit in Cancún! 🐳🇲🇽

Key Takeaways

  • Docker Sandbox Kits (Specification v3) package software and its requested permissions into a single, pinnable OCI image.
  • Two GitHub Actions compromised by Mini Shai-Hulud in May were re-enabled in September with their malicious tags still intact; one alone had roughly 15,000 dependent repositories, potentially exposed.
  • Docker publishes the Rego policies behind Docker Hardened Images, so you can evaluate your own images with docker scout policy.
  • GitHub Actions cache-mode reached general availability, letting you restrict cache read/write access per workflow or job.
  • A GlassWorm-linked cluster of malicious VS Code and Open VSX theme extensions shows that even a color theme can execute code.

🤖 Docker Sandbox Kits: Authority as Code

At the Docker Captains Summit, I spent some time learning about Docker's new direction: sbx, Sandboxes, and Kits.

AI agents are basically overprivileged potential attackers. As they develop our code, they need access to Docker and other services, and putting them in a Docker container is not enough: privileged Docker in Docker weakens the isolation between the container and the host, and mounting the host's Docker socket is worse. That hands the container direct control over the host's Docker daemon. Security risks around both are covered in Chapter 5, "Docker-in-Docker," of Docker and Kubernetes Security.

That's why Docker introduced Sandboxes: a microVM-based isolation environment for running untrusted workloads, and by untrusted workloads, I mean AI agents.

But the agents still need to access external services, some directories on the host, and some credentials. How do we define what they can access?

Enter Docker Sandbox Kits.

On September 24, Docker published the open-source Sandbox Kit Specification v3.1

Here's what a Kit descriptor looks like in practice: part of the gh mixin, which gives an agent the GitHub CLI.

# gh.yaml — part of the GitHub CLI mixin's descriptor
capabilities:
  - type: com.docker.sandbox/network-policy@2
    config:
      runtime:
        allow:
          - github.com
          - hosts: [api.github.com]
            methods: [GET, HEAD, POST, PATCH, PUT, DELETE]
        deny:
          - hosts: [api.github.com]
            methods: [DELETE]
            paths: [/repos/**]

  - type: com.docker.sandbox/credential@1
    optional: true
    config:
      service: github
      phase: runtime
      apiKey:
        name: GH_TOKEN
        proxyManaged: true
        inject:
          - { domain: api.github.com, header: Authorization, format: 'Bearer %s' }

It reads like a Dockerfile, except it declares requested authority instead of software: the Kit requests access to GitHub, but asks for DELETE requests under /repos/** to be denied, and asks to never see the real GH_TOKEN.

A Kit is an ordinary OCI image: the layers are its content, and the descriptor above becomes a single manifest annotation. That's why you can build, scan, sign, and digest-pin a Kit with tooling you already run.

If you want to try this yourself, e.g., running a sandbox, composing a published Kit, then building this exact mixin from source, I wrote a step-by-step tutorial with a companion repository:

Docker Sandbox Kits: A Hands-On Tutorial

Docker Sandbox Kits: A Hands-On Tutorial

A step-by-step walkthrough of Docker Sandboxes and Sandbox Kits: run a plain sandbox, compose a published Kit, then build your own GitHub CLI mixin.

containersecurity.dev

There are two kinds of Kits:

  • Workload: The base software that runs inside the sandbox, such as a coding agent.
  • Mixin: An overlay like the one above — credentials, network rules, or tools layered onto a workload.

A runtime can compose one workload with multiple mixins.

What Does That Mean for Security?

The gh Kit above requests access to GitHub only, requests that DELETE requests under /repos/** be denied, and requests that the agent never hold the real GH_TOKEN: the proxy injects it into authorized requests instead. Useful capabilities, without unrestricted access.

But those are requests, not guarantees. The Kit does not enforce anything by itself. The OCI annotation is metadata; a conforming runtime must enforce, reject, or skip those requests according to the specification. Docker Sandboxes is the first such runtime, and Docker is taking the specification toward CNCF governance, though it's still experimental.2

My takeaway: Dockerfiles made application packaging reproducible. Kits aim to do the same for the authority an application requests.


🧟 Mini Shai-Hulud: The Zombie GitHub Actions

Remember Mini Shai-Hulud?

Mini Shai-Hulud: The Next Evolution of NPM Supply Chain Worms

Mini Shai-Hulud: The Next Evolution of NPM Supply Chain Worms

A deep dive into the Mini Shai-Hulud attack, a sophisticated NPM worm that uses the Bun runtime to bypass security and targets developer agents for persistence.

containersecurity.dev

In May, the worm compromised several developer tools, including two GitHub Actions: actions-cool/issues-helper and actions-cool/maintain-one-comment.

GitHub disabled the compromised repositories on May 19, stopping workflows from downloading their malicious code.

Problem solved?

Not quite.

According to Socket, both repositories became accessible again on September 16, with their malicious release tags still intact.3

Any downstream workflow referencing those tags could execute the payload again.

For issues-helper alone, GitHub's dependency graph showed approximately 15,000 dependent repositories. That does not mean all 15,000 were compromised, but it illustrates the potential exposure.

The attacker didn't need to compromise anything again. The original payload was still waiting.

Fortunately, both repositories were disabled again on September 25.

What Can We Learn?

GitHub Actions referenced through version tags aren't immutable.

For example, uses: example/action@v1 can resolve to different code if someone moves the tag.

Pinning an Action to a verified, clean, full commit SHA prevents that particular attack path. Of course, pinning a malicious commit doesn't magically make it safe.

And remember to audit the permissions and secrets available to your workflows. The SIP example workflow pins every third-party Action to a commit SHA and scopes its permissions: block to exactly what the job needs, for this reason.

SIP: Five Immediate Software Supply Chain Controls

SIP: Five Immediate Software Supply Chain Controls

SIP is a five-step emergency plan for reducing software supply chain risk across AI agents, dependencies, containers, attestations, and releases.

containersecurity.dev

The zombie needed no new attack. It only needed someone to reopen the door.

For the full Shai-Hulud family tree and the trust assumption each worm broke, see the taxonomy of modern supply-chain worms.

The Shai-Hulud Family: A Taxonomy of Modern Supply Chain Worms 🪱

The Shai-Hulud Family: A Taxonomy of Modern Supply Chain Worms 🪱

Seven supply chain worm campaigns, from Shai-Hulud to malware with valid provenance, and what each one teaches us about software trust.

containersecurity.dev


🛡️ Docker Hardened Images: Bring Your Own Security Policy

Docker has also published the security policies used to evaluate Docker Hardened Images.

What makes this interesting is that you can evaluate your own container images against the same policy requirements.4

The policies include checks for non-root execution, vulnerability remediation deadlines, malware and secret-scan attestations, and signed SBOM and provenance attestations.

You can evaluate an image with Docker Scout. Try it against any image you already have pulled, public or private:

docker login
docker scout policy my-app:latest --policy-bundle dhi/policies:latest

docker scout ships with Docker Desktop, so there's nothing extra to install if you already have that. Standalone Docker Engine users need the Scout CLI plugin separately. The policy bundle itself is pulled and cached by digest on first use, so re-running the command doesn't re-download it.

To enforce the same check in CI and fail the build on violations, add exit-code: true to the Scout GitHub Action:

- name: Evaluate DHI policies
  uses: docker/scout-action@2688993af7bafd6ba8c6a74ec652442be91dd82b # v1.23.1
  with:
    command: policy
    image: my-app:${{ github.sha }}
    policy-bundle: dhi/policies:latest
    exit-code: true

The policy bundle is distributed as an OCI artifact, with its source available as Rego policies.

A failing result doesn't necessarily mean your image contains malware. For example, it might simply be missing a required scan attestation.

This distinction matters: evidence of security checks is not the same as proof that software is secure.

Nevertheless, having reusable policies that can run locally or in CI is a useful development.


GitHub Actions Gets More Granular Cache Permissions

On September 10, GitHub also introduced cache-mode, a generally available mechanism for controlling GitHub Actions cache access at the workflow or job level.5

It supports read, write, write-only, and none.

Set it per job, right next to runs-on:

jobs:
  build: # trusted: needs to save the cache for later jobs
    runs-on: ubuntu-latest
    cache-mode: write

  lint-pr: # untrusted: runs on pull_request, only ever restores
    runs-on: ubuntu-latest
    cache-mode: read

GitHub already defaults cache access to read-only for low-trust triggers like pull_request_target. The event still runs in the trusted base-repository context and can have access to secrets and a read/write token; only its cache access defaults to read-only. The point of setting cache-mode explicitly is to stop relying on that default: a job that genuinely never needs to save a cache can't poison one, even if someone widens its trigger later without noticing the cache implications.

After the supply-chain attacks we have covered in previous issues, this is a welcome addition.


🎨 GlassWorm: Even Your VS Code Theme Can Be Malicious

An early-October addition to this issue.

On October 2, Socket reported a cluster of suspicious VS Code and Open VSX theme extensions connected to previously identified malware. The investigation identified at least two confirmed malicious extensions and linked one to GlassWorm with high confidence.6

The malicious extension used obfuscated JavaScript and a staged loader to retrieve further payloads.

The broader cluster also contained apparently harmless extensions sharing development or publishing characteristics with the malicious ones. Not every extension in the cluster was confirmed to be malicious.

This illustrates another uncomfortable fact about developer environments: a VS Code theme isn't necessarily just colors.

Extensions may execute JavaScript with access to developer resources.

Your editor is part of your software supply chain.

Review installed extensions, remove those you no longer need, and pay attention to their publishers and updates. Start with a full inventory, which takes one command:

code --list-extensions --show-versions

For each theme or extension you don't immediately recognize, check its Marketplace listing for a verified-publisher badge and an actual install count, not just a plausible name. A theme published last month with a few hundred installs and no verification badge deserves more scrutiny than one with a decade of history.

Apparently, even going dark mode requires a threat model. 🌑


🎙️ Recent Work

🐳 Docker Captains Summit 2026

I spent the end of September in Cancún, Mexico, meeting Docker Captains from around the world.

You can see them in this photo from the summit:

Docker Captains Summit 2026

So, as you can see, Docker is going dark mode. But, we don't have cookies. 🍪

To celebrate the dark mode, Docker is also giving away $250 in sbx cloud credit to new sign-ups, through October 31, 2026, credit card required. Claim it here.

📚 Black Forest Commandos: Asgard Mission

The Commandos finally have their own graphic novel!

Black Forest Commandos: Asgard Mission brings the characters from my DevSecOps workshops into a new adventure inspired by Norse mythology.

The current version is purely narrative, and feels like Anton Chekhov meets Mortal Kombat with DLCs. Get the PDF here for free.

🇨🇭 Coming Up: BaselOne

On October 15, I'll be speaking at BaselOne in Switzerland.

My talk, Dockerize Java Securely: SBOMs + Attestations + Cosign, covers container supply-chain security for Java applications, including BuildKit-generated SBOMs, provenance, and image signing.

If you're attending, come say hello!


Until Next Time

Our software supply chain now includes dependencies, build workflows, IDE extensions, and autonomous agents.

Some of these tools can execute arbitrary code. Others hold credentials or decide what to do next.

The common challenge is not simply identifying what we trust. It's controlling how much authority that trust grants.

Until next time, pin your Actions, review your permissions, and watch out for the zombie worms.

And remember: the dark side doesn't always have cookies. 🍪🧟


Footnotes

  1. Christian Dupuis. "From Dockerfile to Kit: The Docker Sandboxes Kit Specification." Docker, September 24, 2026. See also the Sandbox Kit Specification repository. ↩

  2. Eli Aleyner and Srini Sekaran. "Docker and CNCF Partner on an Open Spec for Agent Permissions." Docker, September 24, 2026. ↩

  3. Karlo Zanki. "Re-Enabled GitHub Actions Expose Thousands of Repositories to Mini Shai-Hulud." Socket, September 24, 2026; updated September 25. ↩

  4. Docker Docs. "Apply Docker Hardened Image Policies to Your Images." ↩

  5. GitHub. "Control GitHub Actions Cache Access with cache-mode." September 10, 2026. ↩

  6. Kirill Boychenko. "Pretty Themes, Hidden Loaders: GlassWorm-Linked Extensions." Socket, October 2, 2026. ↩

Characters in this entry