<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Docker</title>
    <description>The latest articles on DEV Community by Docker (docker).</description>
    <link>https://dev.to/docker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3459%2F42b5911d-1b27-42a6-988a-a45d81aaaf7a.png</url>
      <title>DEV Community: Docker</title>
      <link>https://dev.to/docker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/docker"/>
    <language>en</language>
    <item>
      <title>How to Secure Java Docker Images and Reduce CVE Risk</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Tue, 13 Oct 2026 22:40:21 +0000</pubDate>
      <link>https://dev.to/docker/how-to-secure-java-docker-images-and-reduce-cve-risk-a78</link>
      <guid>https://dev.to/docker/how-to-secure-java-docker-images-and-reduce-cve-risk-a78</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Black Forest Commandos' field guide to CVEs, SBOMs, hardened images, attestations, and software supply chain security.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your Java application can inherit vulnerable dependencies and packages from your base image before you write a single line of application code. Also, scanning your Docker image for vulnerabilities has blind spots, as the SBOM generated after the fact does not give you the full picture. A successful Docker build alone does not tell you what is shipped, how it was built, or whether you can trust it.&lt;/p&gt;

&lt;p&gt;Asgard is under attack. Shadow creatures called CVEs have infiltrated the realm, and Thor's hammer is proving surprisingly ineffective. Odin has only one option: summon the Black Forest Commandos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feriembrcfnmmbttp361u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feriembrcfnmmbttp361u.png" alt="Black Forest Commandos enter Asgard" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Behind the mythology is a practical question: &lt;strong&gt;How do we build container images that we can inspect, trust, and deploy with confidence?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's secure a Spring Boot sample project together, and with the help of the Commandos (CLI commands).&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Most of the CVEs come from base images. Just swapping the baseline base image for a Docker hardened base image reduces the runtime inventory—the packages an attacker could actually reach—by &lt;strong&gt;75.5%&lt;/strong&gt;, with no application dependency changes between the two images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft1n3uu8g9lkxujjgmaco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft1n3uu8g9lkxujjgmaco.png" alt="Baseline vs Hardened SBOM package count" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fewer number of packages, means less attack surface. Docker Hardened Images are also shipped with near-zero CVEs, non-root user, and no shell or package manager for the production images. So, even if an attacker gets inside your container, they won't have much to play with.&lt;/p&gt;

&lt;p&gt;All these considered, swapping your base images won't make your application CVEs go away. That's why you should read the full article!&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the Ready-to-Run Sample
&lt;/h2&gt;

&lt;p&gt;Before we start, let's check your toolset:&lt;/p&gt;

&lt;h3&gt;
  
  
  Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install Git to clone the sample repository.&lt;/li&gt;
&lt;li&gt;Install and start Docker with Buildx. Check that docker info and docker buildx version work.&lt;/li&gt;
&lt;li&gt;If not on Docker Desktop, install Docker Scout CLI separately. Check docker scout version.&lt;/li&gt;
&lt;li&gt;Install Trivy and check trivy --version. The recorded run used 0.75.0.&lt;/li&gt;
&lt;li&gt;Install Cosign and check cosign version. The recorded run used 3.1.3.&lt;/li&gt;
&lt;li&gt;Have Bash, curl, and Python 3 available for the demo scripts.&lt;/li&gt;
&lt;li&gt;Sign in to Docker Hub with docker login for Scout CVE queries.&lt;/li&gt;
&lt;li&gt;Sign in to Docker Hardened Images with docker login dhi.io.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker builds, compiles, and tests the application, so you can follow this walkthrough without installing Java or Maven locally. Use a Bash-like terminal for the commands below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check Out the Tested Starting Point
&lt;/h3&gt;

&lt;p&gt;The reference repository has two branches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt;, which is the state you will reach at the end of the article.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt;, is the beginning of the journey.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will &lt;code&gt;start&lt;/code&gt; from there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--branch&lt;/span&gt; start &lt;span class="nt"&gt;--single-branch&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/ContainerSecurity-dev/dockerize-java-securely.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dockerize-java-securely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can edit and commit your experiments on this local branch. Base-image tags and vulnerability databases can still change, so your scan results may differ.&lt;/p&gt;

&lt;p&gt;The files you'll use are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/&lt;/code&gt; and &lt;code&gt;pom.xml&lt;/code&gt;: the working application and its HTTP integration test.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Dockerfile.baseline&lt;/code&gt;: the starting image, using the official Maven and Eclipse Temurin images.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Dockerfile&lt;/code&gt;: the hardened version you'll compare against it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scripts/&lt;/code&gt;: helpers to check the HTTP response and save vulnerability reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let it rip.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Build a Baseline You Can Inspect
&lt;/h2&gt;

&lt;p&gt;The Commandos survey the ground before they fight. For us, that ground is a baseline image, built and pushed so it can be inspected.&lt;/p&gt;

&lt;p&gt;We use a temporary, loopback-only registry so the audience can practice pushes and attestations without publishing application images to a public registry. This unauthenticated HTTP registry is for local demos only. For a remote registry, use an authenticated namespace you own over HTTPS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; dockerize-java-demo-registry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:15000:5000 registry:3
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PLATFORM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux/amd64   &lt;span class="c"&gt;# use linux/arm64 on Apple Silicon&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;IMAGE_REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1:15000/dockerize-java-securely
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; results

docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PLATFORM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.baseline &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sbom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--provenance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;max &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metadata-file&lt;/span&gt; results/baseline-build-metadata.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--push&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

scripts/smoke-test.sh &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;IMAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's unpack the commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;docker buildx build&lt;/code&gt; command is an extended command for building Docker images using BuildKit.&lt;/li&gt;
&lt;li&gt;The flag &lt;code&gt;--sbom=true&lt;/code&gt; instructs the builder to generate SBOM attestations: SBOM records "attached" to the image.&lt;/li&gt;
&lt;li&gt;The flag &lt;code&gt;--provenance=mode=max&lt;/code&gt; is used to generate provenance attestations. This attestation records more metadata about the build process.&lt;/li&gt;
&lt;li&gt;As you can see, &lt;code&gt;-f Dockerfile.baseline&lt;/code&gt; is used to specify the Dockerfile. So, the only non-optional argument, being the &lt;code&gt;.&lt;/code&gt; at the end, is not actually the path to the Dockerfile, it's rather the &lt;em&gt;build context&lt;/em&gt;, which is all the files that Docker can access and can potentionally end up in your Docker image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3qnbzqcrre5j9v0n8evy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3qnbzqcrre5j9v0n8evy.png" alt="Docker and Kubernetes Security" width="800" height="985"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/docker-and-kubernetes-security" rel="noopener noreferrer"&gt;View book&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, if you inspect the &lt;code&gt;smoke-test.sh&lt;/code&gt; file, it's running the image with the following flags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--detach&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--read-only&lt;/span&gt; &lt;span class="nt"&gt;--tmpfs&lt;/span&gt; /tmp &lt;span class="nt"&gt;--cap-drop&lt;/span&gt; ALL &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--security-opt&lt;/span&gt; no-new-privileges:true &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1::8080 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The smoke test should return &lt;code&gt;Hello, Docker Security!&lt;/code&gt; as user &lt;code&gt;10001:10001&lt;/code&gt;. The flags are used to run the container in a safer environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Know Your Enemy: CVEs and SBOMs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8rn0zt609mz8xvf6r4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8rn0zt609mz8xvf6r4y.png" alt="CVEs are shadow creatures" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Log4Shell (CVE-2021-44228) demonstrated why knowing which dependencies we ship matters. An SBOM, or &lt;em&gt;Software Bill of Materials&lt;/em&gt;, is a list of software components in your application. Having this list handy helps you identify your packages in case there is a known exploit in one of them. Having it does not make your application safer by itself.&lt;/p&gt;

&lt;p&gt;Rothütle's first mission in Asgard is to discover who lives there. Using Docker Scout, you can check the list using &lt;code&gt;docker scout sbom&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker scout sbom &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; list
docker scout sbom &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; spdx &lt;span class="nt"&gt;--output&lt;/span&gt; results/sbom.spdx.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How many packages are listed here?&lt;/p&gt;

&lt;p&gt;Output of those commands will mention the SBOM attestation being used. If the attestation is absent from the build, Docker Scout will try to build it by scanning your files.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;docker buildx build&lt;/code&gt; command we ran, we have created an SBOM attestation, and the Docker Scout command picked it up. But, the SBOM only contains packages from the final stage, which is not a full picture. A compromised build-time package can still write a backdoor into your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/generating-an-sbom-with-docker-scout" rel="noopener noreferrer"&gt;generating-an-sbom-with-docker-scout&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Hunt the CVEs: Docker Scout and Trivy
&lt;/h2&gt;

&lt;p&gt;Jack, our cybernetic scout, now dressing as Jack-o'-Lantern for Halloween, can detect CVEs hiding inside container images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker scout cves &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
docker scout cves &lt;span class="nt"&gt;--only-severity&lt;/span&gt; critical,high &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker Scout is an enterprise offering, free for personal use. Trivy is an open-source alternative and similarly an industry standard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;trivy image &lt;span class="nt"&gt;--scanners&lt;/span&gt; vuln &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
trivy image &lt;span class="nt"&gt;--scanners&lt;/span&gt; vuln &lt;span class="nt"&gt;--severity&lt;/span&gt; CRITICAL,HIGH &lt;span class="nt"&gt;--exit-code&lt;/span&gt; 1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa71d5mh6ym8erudbmju9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa71d5mh6ym8erudbmju9.png" alt="Jack the scout, scanning for CVEs" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final command &lt;strong&gt;should return exit code 1&lt;/strong&gt;, because there are high and/or critical CVEs in the image. That is a security gate you should add to your workflow.&lt;br&gt;
Let's save machine-readable reports with the repository's helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Saves JSON, summarizes findings, and exits 1 if the gate fails.&lt;/span&gt;
scripts/scan.sh &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; results/baseline-trivy.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;scan.sh&lt;/code&gt; script runs Trivy under the hood, but also stores the reports and parses them. A similar script would be in your pipeline, e.g., to report the number of CVEs via a pull request comment.&lt;/p&gt;

&lt;p&gt;Note that, severity is not the same as exploitability, and malicious software does not necessarily have a CVE. Scanner databases and package matching also differ: the same baseline yielded different totals in Scout and Trivy. Compare images within the same scanner and inspect the affected packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Include the Build Stage in Your SBOM
&lt;/h2&gt;

&lt;p&gt;Rothütle suspects the inventory is incomplete: some components were present while the application was built, not only while it runs.&lt;/p&gt;

&lt;p&gt;The baseline uses a multi-stage build, but &lt;code&gt;--sbom=true&lt;/code&gt; alone inventories the final image. Packages used only while compiling the application can disappear from that inventory when the build stage is discarded.&lt;/p&gt;

&lt;p&gt;First inspect the baseline's attached SBOM and provenance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker buildx imagetools inspect &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{json .SBOM}}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; results/baseline-sbom.json
docker buildx imagetools inspect &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{json .Provenance}}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; results/baseline-provenance.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now edit &lt;code&gt;Dockerfile.baseline&lt;/code&gt;. Add this argument immediately after the build stage's &lt;code&gt;FROM&lt;/code&gt; line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;maven:3.9-eclipse-temurin-21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILDKIT_SBOM_SCAN_STAGE=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebuild under a separate tag so you can compare the two inventories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PLATFORM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.baseline &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sbom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--provenance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;max &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metadata-file&lt;/span&gt; results/baseline-build-sbom-metadata.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--push&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline-build-sbom"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

docker buildx imagetools inspect &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:baseline-build-sbom"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{json .SBOM}}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; results/baseline-with-build-sbom.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new output includes an additional &lt;code&gt;sbom-build&lt;/code&gt; document alongside the runtime SPDX inventory. The argument adds metadata about the packages from earlier stages, and it doesn't mean those packages end up in the final image.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SBOM:&lt;/strong&gt; What software was inventoried in the image and covered build stages?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance:&lt;/strong&gt; How was the image built, and from which materials?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use BuildKit secret mounts for credentials. Maximum-level provenance can expose build arguments, so never put secrets in them. Furthermore, an attached attestation is not automatically a trusted cryptographic signature.&lt;/p&gt;

&lt;p&gt;Now, how many packages are listed in the SBOM attestations?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/the-poisoned-macchiato" rel="noopener noreferrer"&gt;the-poisoned-macchiato&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Harden the Runtime and Measure the Difference
&lt;/h2&gt;

&lt;p&gt;Armor time. Docker Hardened Images are a set of open-source and near-zero-CVE base images, designed to "armor" your Docker image against future attacks. You can check their catalog on &lt;a href="https://dhi.io/" rel="noopener noreferrer"&gt;dhi.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's swap the base image for the hardened ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax=docker/dockerfile:1&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;dhi.io/maven:3-jdk21-dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILDKIT_SBOM_SCAN_STAGE=true&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml .&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src ./src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn &lt;span class="nt"&gt;-B&lt;/span&gt; verify

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; dhi.io/eclipse-temurin:21-alpine3.23&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/target/app.jar /app/app.jar&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; 10001:10001&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "/app/app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you check the sample repo, there is a file &lt;code&gt;.dockerignore&lt;/code&gt; there with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight codeowners"&gt;&lt;code&gt;&lt;span class="n"&gt;**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pom.xml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;src/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;src/**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Dockerfile&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Dockerfile.baseline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means, everything is ignored by the &lt;code&gt;docker buildx build&lt;/code&gt; command (removed from the build context), except for the listed files. This is called an allowlist. So, instead of ignoring a bunch of files, we ignore everything, and allow a bunch of files.&lt;/p&gt;

&lt;p&gt;Also, the POM sets &lt;code&gt;finalName&lt;/code&gt; to &lt;code&gt;app&lt;/code&gt;, avoiding an ambiguous JAR wildcard.&lt;/p&gt;

&lt;p&gt;This follows Docker's &lt;a href="https://docs.docker.com/dhi/migration/examples/java/" rel="noopener noreferrer"&gt;Java DHI migration pattern&lt;/a&gt;, with explicit tests and a non-root runtime user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PLATFORM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sbom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--provenance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;max &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metadata-file&lt;/span&gt; results/hardened-build-metadata.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--push&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:hardened"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

scripts/smoke-test.sh &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:hardened"&lt;/span&gt;
&lt;span class="c"&gt;# Also returns 1 for the recorded sample:&lt;/span&gt;
scripts/scan.sh &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;:hardened"&lt;/span&gt; results/hardened-trivy.json
python3 scripts/summarize-scans.py results/baseline-trivy.json results/hardened-trivy.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's report time! You can run all of them yourself, or just read through mine!&lt;/p&gt;

&lt;h3&gt;
  
  
  Observed results: 13 October 2026
&lt;/h3&gt;

&lt;p&gt;Both final application images use Spring Boot 4.0.8 and Java 21. The results are based on runs on Linux Ubuntu (&lt;code&gt;linux/amd64&lt;/code&gt;) and Mac Silicon (&lt;code&gt;linux/arm64&lt;/code&gt;), yielding identical results. These are &lt;strong&gt;Trivy 0.75.0 vulnerability records&lt;/strong&gt;, grouped by scan target; totals are not counts of unique CVE IDs across all packages.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scan target&lt;/th&gt;
&lt;th&gt;Baseline: &lt;code&gt;eclipse-temurin:21-jre&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Hardened: &lt;code&gt;dhi.io/eclipse-temurin:21-alpine3.23&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OS packages&lt;/td&gt;
&lt;td&gt;0 critical, 0 high, 40 medium, 4 low&lt;/td&gt;
&lt;td&gt;No findings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java dependencies&lt;/td&gt;
&lt;td&gt;3 critical, 5 high, 2 medium&lt;/td&gt;
&lt;td&gt;3 critical, 5 high, 2 medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other detected binary (&lt;code&gt;pebble&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3 high, 5 medium, 1 low, 4 unknown&lt;/td&gt;
&lt;td&gt;Not present as a scan target&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Docker Scout 1.20.3 reported &lt;strong&gt;5 critical / 13 high / 2 medium / 3 unspecified&lt;/strong&gt; for the baseline and &lt;strong&gt;3 critical / 5 high / 2 medium&lt;/strong&gt; for the hardened image. Those are separate scanner observations, not interchangeable with the Trivy counts.&lt;/p&gt;

&lt;p&gt;The original Spring Boot 4.0.5 sample had &lt;strong&gt;9 critical / 18 high / 20 medium / 6 low&lt;/strong&gt; Java findings in Trivy. Updating to 4.0.8 reduced those findings, but did not eliminate them. The remaining Java findings implicated Tomcat and Jackson dependencies. Review the report's fixed-version guidance, update the application dependencies, rerun tests, and rescan before promotion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect the Blast Radius in Your Dependency Tree
&lt;/h3&gt;

&lt;p&gt;"Update Tomcat and Jackson" is easier said than done, because most of these libraries arrive transitively through the Spring Boot BOM. Inspect what your project actually resolves before you touch a version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Full resolved tree (run inside the builder image if you have no local JDK):&lt;/span&gt;
./mvnw &lt;span class="nt"&gt;-B&lt;/span&gt; dependency:tree

&lt;span class="c"&gt;# Narrow it to the packages the scanner flagged:&lt;/span&gt;
./mvnw &lt;span class="nt"&gt;-B&lt;/span&gt; dependency:tree &lt;span class="nt"&gt;-Dincludes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;org.apache.tomcat.embed:tomcat-embed-core
./mvnw &lt;span class="nt"&gt;-B&lt;/span&gt; dependency:tree &lt;span class="nt"&gt;-Dincludes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tools.jackson.core:jackson-core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can't believe it's 2026 and Maven flags still look like that. Dincludes. Anyway!&lt;/p&gt;

&lt;p&gt;The tree shows each artifact's depth and the path that pulled it in. A dependency you declare directly in &lt;code&gt;pom.xml&lt;/code&gt; can be overridden there or in a &lt;code&gt;&amp;lt;dependencyManagement&amp;gt;&lt;/code&gt; entry; a transitive one usually needs a version override or an updated parent/BOM. After the change, confirm the fix reaches the runtime JAR, rerun &lt;code&gt;mvn verify&lt;/code&gt;, and rescan the new digest. If an affected artifact is transitive and has no fix yet, record that in a VEX statement instead of silently suppressing it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check VEX Before Comparing Scanners
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;VEX (Vulnerability Exploitability eXchange)&lt;/strong&gt; records whether a particular vulnerability affects a product. One can create VEX records for CVEs that are harmless in their case. One can ship them with their Docker image as "VEX attestations". Docker Hardened Image come with their own VEX attestations.&lt;/p&gt;

&lt;p&gt;Docker Scout automatically applies DHI VEX statements and excludes them from the listed CVEs; Trivy needs VEX enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker scout cves dhi.io/eclipse-temurin:8-alpine3.23

&lt;span class="c"&gt;# Configure and download the DHI VEX repository first (see linked instructions).&lt;/span&gt;
trivy image &lt;span class="nt"&gt;--scanners&lt;/span&gt; vuln &lt;span class="nt"&gt;--vex&lt;/span&gt; repo dhi.io/eclipse-temurin:8-alpine3.23
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Trivy, enable the &lt;code&gt;docker-hardened-images/advisories&lt;/code&gt; repository in its VEX configuration and download it before using &lt;code&gt;--vex repo&lt;/code&gt;. Review applicable VEX statements; suppression is an assessment of affectedness, not a dependency fix.&lt;/p&gt;

&lt;p&gt;This can sometimes explain differences in reported CVEs without any change to the image. See &lt;a href="https://docs.docker.com/dhi/how-to/scan/" rel="noopener noreferrer"&gt;Docker’s VEX-aware scanning instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The recorded Trivy scans above did &lt;strong&gt;not&lt;/strong&gt; enable VEX. However, the observed difference between Scout and Trivy was in the non-DHI baseline, so it was not coming from VEX attestations.&lt;/p&gt;

&lt;p&gt;Both images passed the HTTP smoke test. In the recorded comparison, with build-stage scanning enabled, the runtime SBOM contained &lt;strong&gt;192 packages&lt;/strong&gt; for the baseline and &lt;strong&gt;47&lt;/strong&gt; for the hardened image; the separate build-stage inventories contained &lt;strong&gt;396&lt;/strong&gt; and &lt;strong&gt;377&lt;/strong&gt;, respectively. Hence, just by swapping for a DHI base image, the number of dependencies in the production image is reduced by 75%. Hence the Artemisia bar chart image, as she's squashing the attack surface!&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/ContainerSecurity-dev/dockerize-java-securely/blob/main/docs/RESULTS.md" rel="noopener noreferrer"&gt;results report&lt;/a&gt; records image digests, versions, and evidence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/docker-hardened-images-are-free" rel="noopener noreferrer"&gt;docker-hardened-images-are-free&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Sign Before You Trust: Cosign
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7rsey8duy2kun5qzmax6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7rsey8duy2kun5qzmax6.png" alt="Evie signs the SBOM attestations" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Evie is the Commando responsible for cryptographic signatures. She always uses the immutable digest returned by the build, rather than a mutable tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DIGEST_IMAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_REPO&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import json; print(json.load(open("results/hardened-build-metadata.json"))["containerimage.digest"])'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .demo-keys
cosign generate-key-pair &lt;span class="nt"&gt;--output-key-prefix&lt;/span&gt; .demo-keys/cosign
cosign sign &lt;span class="nt"&gt;--key&lt;/span&gt; .demo-keys/cosign.key &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIGEST_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
cosign verify &lt;span class="nt"&gt;--key&lt;/span&gt; .demo-keys/cosign.pub &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIGEST_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Scan the same immutable artifact; this sample still fails the gate.&lt;/span&gt;
trivy image &lt;span class="nt"&gt;--scanners&lt;/span&gt; vuln &lt;span class="nt"&gt;--severity&lt;/span&gt; CRITICAL,HIGH &lt;span class="nt"&gt;--exit-code&lt;/span&gt; 1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIGEST_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cosign 3.1.3 successfully verifies the signature, claims, and transparency-log inclusion. The vulnerability gate still returns &lt;strong&gt;1&lt;/strong&gt;. A signed image can contain known vulnerabilities.&lt;/p&gt;

&lt;p&gt;Keep the private key out of Git; the sample ignores &lt;code&gt;.demo-keys/&lt;/code&gt; and &lt;code&gt;*.key&lt;/code&gt;. Enter a key password interactively and use a disposable key for rehearsal. Default signing publishes signature metadata and the public key to a transparency log. Production verification needs a trusted signing policy, not an arbitrary public key supplied alongside an image.&lt;/p&gt;

&lt;p&gt;We sign the image to make sure no one altered it on the way to production. But, the attackers are getting smarter. Read the Shai Hulud family account to learn about the incident that a signed image was altered by the attacker:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/taxonomy-of-modern-supply-chain-worms" rel="noopener noreferrer"&gt;taxonomy-of-modern-supply-chain-worms&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. SIP It Before You Ship It
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9802ynaoj37xrz3uqqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9802ynaoj37xrz3uqqx.png" alt="Shai-Hulud family of supply chain worms" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Shai-Hulud family illustrates why scanning a final image is not enough: malicious packages can target developers and CI before an image exists. AI coding agents are another environment with access to code, tools, and potentially credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SIP: Security Immediate Plan&lt;/strong&gt; ties the controls together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox agents.&lt;/strong&gt; Isolate execution and restrict credentials, network access, and mounted directories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lock down dependencies.&lt;/strong&gt; Manage Maven dependency and plugin versions, inspect the resolved tree, and review updates. Gradle and npm projects need their own locking and install policies; this Maven sample does not exercise those tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harden builds.&lt;/strong&gt; Keep compilers and build tools in the build stage, and run the final image without root privileges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attest.&lt;/strong&gt; Generate SBOM and provenance, including relevant build stages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan before promotion.&lt;/strong&gt; Scan the exact digest, enforce your vulnerability policy, and verify trusted signatures before deployment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sandbox → Lock → Harden → Attest → Scan.&lt;/strong&gt; No single scanner, image, or signature secures the entire supply chain. For agent isolation and ecosystem-specific dependency controls, see the &lt;a href="https://containersecurity.dev/blog/sip" rel="noopener noreferrer"&gt;full SIP implementation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This walkthrough demonstrates three of those controls end to end on a real Java image: &lt;strong&gt;Harden&lt;/strong&gt; (a DHI runtime running as a non-root user), &lt;strong&gt;Attest&lt;/strong&gt; (SBOM and provenance, including the build stage), and &lt;strong&gt;Scan&lt;/strong&gt; (gating the exact digest before promotion). It touches &lt;strong&gt;Lock&lt;/strong&gt; only partially, through the Maven dependency tree and version discipline shown above; full dependency locking for Gradle and npm projects is outside this sample. &lt;strong&gt;Sandbox agents&lt;/strong&gt;—isolating AI coding agents and restricting their credentials, network access, and mounts—is not exercised here at all, so treat it as an additional SIP control rather than something this experiment proved.&lt;/p&gt;

&lt;p&gt;Read more about &lt;code&gt;sbx&lt;/code&gt; and kits here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/docker-sandbox-kits-tutorial" rel="noopener noreferrer"&gt;docker-sandbox-kits-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When finished, remove the dedicated local registry and its temporary data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; dockerize-java-demo-registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Three findings came out of this run, and they map directly onto the Commando team:&lt;/p&gt;

&lt;h3&gt;
  
  
  Key takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hardened base images reduce OS-level exposure. The DHI runtime dropped from 192 inventoried packages to 47 (75.5%) and removed all 44 Ubuntu package findings and the pebble binary target, without changing any application dependency.&lt;/li&gt;
&lt;li&gt;SBOM attestations improve visibility. &lt;code&gt;--sbom=true --provenance=mode=max&lt;/code&gt; attaches what shipped and how it was built, and &lt;code&gt;BUILDKIT_SBOM_SCAN_STAGE=true&lt;/code&gt; extends the inventory to the build stage.&lt;/li&gt;
&lt;li&gt;Application dependency remediation remains essential. Tomcat and Jackson kept the same 3 critical and 5 high findings in both images, so hardening and signing never replaced updating libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hardening the base image and signing the result are necessary, not sufficient. The Commandos' armor kept out the creatures that came with the base image; the ones hiding inside Tomcat and Jackson are a different fight, and it is fought at the dependency level. Fix what you ship, prove how you built it, and scan the exact digest before it reaches production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fikv3l7zv0oxrvl0n0k6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fikv3l7zv0oxrvl0n0k6h.png" alt="Black Forest Commandos at BaselOne" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Learning: Articles and Tutorials
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/generating-an-sbom-with-docker-scout" rel="noopener noreferrer"&gt;Generating SBOM with Docker Scout&lt;/a&gt; — inspect and export software inventories.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/the-poisoned-macchiato" rel="noopener noreferrer"&gt;The Poisoned Macchiato&lt;/a&gt; — Java SBOM attestations, Cosign, and OCI artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/docker-hardened-images-are-free" rel="noopener noreferrer"&gt;Docker Hardened Images are Free&lt;/a&gt; — hardened base images and vulnerability comparisons.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/taxonomy-of-modern-supply-chain-worms" rel="noopener noreferrer"&gt;The Shai-Hulud Family&lt;/a&gt; — taxonomy of modern supply chain worms.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/docker-sandbox-kits-tutorial" rel="noopener noreferrer"&gt;Docker Sandbox Kits: A Hands-On Tutorial&lt;/a&gt; — agent isolation and capability controls.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://containersecurity.dev/blog/black-forest-commandos-v1.5.2" rel="noopener noreferrer"&gt;Black Forest Commandos: Asgard Mission DIY&lt;/a&gt; — a longer, hands-on version of the Commandos' mission.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Official Documentation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/reference/cli/docker/scout/sbom/" rel="noopener noreferrer"&gt;Docker Scout SBOM CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/reference/cli/docker/scout/cves/" rel="noopener noreferrer"&gt;Docker Scout CVE CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/build/metadata/attestations/sbom/" rel="noopener noreferrer"&gt;Docker BuildKit SBOM attestations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/build/metadata/attestations/slsa-provenance" rel="noopener noreferrer"&gt;Docker BuildKit provenance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trivy.dev/" rel="noopener noreferrer"&gt;Trivy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.sigstore.dev/cosign/verifying/verify/" rel="noopener noreferrer"&gt;Sigstore Cosign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/ai/sandboxes/usage/" rel="noopener noreferrer"&gt;Docker Sandboxes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Meet the Black Forest Commandos in My Books
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://containersecurity.dev/docker-and-kubernetes-security" rel="noopener noreferrer"&gt;Docker and Kubernetes Security&lt;/a&gt;&lt;/strong&gt;. To learn about Linux capabilities (the ones that we dropped here), or secure CI workflows, check this book.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://containersecurity.dev/black-forest-shadow" rel="noopener noreferrer"&gt;Black Forest Shadow&lt;/a&gt;&lt;/strong&gt;. The origin story of Gord, Rothütle, Evie, and the CVE monsters, set in the Black Forest in 1865.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://containersecurity.dev/black-forest-commandos" rel="noopener noreferrer"&gt;Black Forest Commandos: Asgard Mission&lt;/a&gt;&lt;/strong&gt;. The graphic novel behind the Commandos' adventure in Asgard. The story expands the mythology used in my talks and workshops. Do you want to know the ending? Spoiler alert!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SIP it before you ship it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mohammad-Ali A'râbi — Docker Captain, author, and creator of the Black Forest Commandos.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Results are a dated snapshot from the linked sample. Review versions, permissions, and security policies and rerun the checks before production use.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>security</category>
      <category>devops</category>
      <category>java</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 7: Authority as Code and Zombie Actions 🧟</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Mon, 12 Oct 2026 17:34:48 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-7-authority-as-code-and-zombie-actions-3fgi</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-7-authority-as-code-and-zombie-actions-3fgi</guid>
      <description>&lt;p&gt;The worm was dead. Or so we thought.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy6mm7vh9gopeoe4ef6ro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy6mm7vh9gopeoe4ef6ro.png" alt="Docker Security Dispatch 7" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Plus, my adventures at the Docker Captains Summit in Cancún! 🐳🇲🇽&lt;/p&gt;

&lt;h3&gt;
  
  
  Key takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker Sandbox Kits (Specification v3) package software and its requested permissions into a single, pinnable OCI image.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;Docker publishes the Rego policies behind Docker Hardened Images, so you can evaluate your own images with docker scout policy.&lt;/li&gt;
&lt;li&gt;GitHub Actions cache-mode reached general availability, letting you restrict cache read/write access per workflow or job.&lt;/li&gt;
&lt;li&gt;A GlassWorm-linked cluster of malicious VS Code and Open VSX theme extensions shows that even a color theme can execute code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 Docker Sandbox Kits: Authority as Code
&lt;/h2&gt;

&lt;p&gt;At the Docker Captains Summit, I spent some time learning about Docker's new direction: &lt;code&gt;sbx&lt;/code&gt;, Sandboxes, and Kits.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://containersecurity.dev/docker-and-kubernetes-security" rel="noopener noreferrer"&gt;Docker and Kubernetes Security&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;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?&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Docker Sandbox Kits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On September 24, Docker published the open-source Sandbox Kit Specification v3.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Here's what a Kit descriptor looks like in practice: part of the &lt;code&gt;gh&lt;/code&gt; mixin, which gives an agent the GitHub CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# gh.yaml — part of the GitHub CLI mixin's descriptor&lt;/span&gt;
&lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.docker.sandbox/network-policy@2&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;allow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;github.com&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;api.github.com&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
            &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GET&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;HEAD&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;POST&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;PATCH&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;PUT&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;DELETE&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;deny&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;api.github.com&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
            &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;DELETE&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
            &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;/repos/**&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.docker.sandbox/credential@1&lt;/span&gt;
    &lt;span class="na"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github&lt;/span&gt;
      &lt;span class="na"&gt;phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;runtime&lt;/span&gt;
      &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GH_TOKEN&lt;/span&gt;
        &lt;span class="na"&gt;proxyManaged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;api.github.com&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;header&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;%s'&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;/repos/**&lt;/code&gt; to be denied, and asks to never see the real &lt;code&gt;GH_TOKEN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/docker-sandbox-kits-tutorial" rel="noopener noreferrer"&gt;docker-sandbox-kits-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two kinds of Kits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workload:&lt;/strong&gt; The base software that runs inside the sandbox, such as a coding agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixin:&lt;/strong&gt; An overlay like the one above — credentials, network rules, or tools layered onto a workload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A runtime can compose one workload with multiple mixins.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does That Mean for Security?
&lt;/h3&gt;

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

&lt;p&gt;But those are requests, not guarantees. &lt;strong&gt;The Kit does not enforce anything by itself.&lt;/strong&gt; 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.&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;My takeaway: Dockerfiles made application packaging reproducible. Kits aim to do the same for the authority an application requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧟 Mini Shai-Hulud: The Zombie GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Remember Mini Shai-Hulud?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" rel="noopener noreferrer"&gt;mini-shai-hulud-attack&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;GitHub disabled the compromised repositories on May 19, stopping workflows from downloading their malicious code.&lt;/p&gt;

&lt;p&gt;Problem solved?&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;According to Socket, both repositories became accessible again on September 16, with their malicious release tags still intact.&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Any downstream workflow referencing those tags could execute the payload again.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;issues-helper&lt;/code&gt; alone, GitHub's dependency graph showed approximately &lt;strong&gt;15,000 dependent repositories&lt;/strong&gt;. That does not mean all 15,000 were compromised, but it illustrates the potential exposure.&lt;/p&gt;

&lt;p&gt;The attacker didn't need to compromise anything again. The original payload was still waiting.&lt;/p&gt;

&lt;p&gt;Fortunately, both repositories were disabled again on September 25.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Can We Learn?
&lt;/h3&gt;

&lt;p&gt;GitHub Actions referenced through version tags aren't immutable.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;permissions:&lt;/code&gt; block to exactly what the job needs, for this reason.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/sip" rel="noopener noreferrer"&gt;sip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The zombie needed no new attack. It only needed someone to reopen the door.&lt;/p&gt;

&lt;p&gt;For the full Shai-Hulud family tree and the trust assumption each worm broke, see the taxonomy of modern supply-chain worms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/taxonomy-of-modern-supply-chain-worms" rel="noopener noreferrer"&gt;taxonomy-of-modern-supply-chain-worms&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ Docker Hardened Images: Bring Your Own Security Policy
&lt;/h2&gt;

&lt;p&gt;Docker has also published the security policies used to evaluate Docker Hardened Images.&lt;/p&gt;

&lt;p&gt;What makes this interesting is that you can evaluate your &lt;strong&gt;own container images&lt;/strong&gt; against the same policy requirements.&lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The policies include checks for non-root execution, vulnerability remediation deadlines, malware and secret-scan attestations, and signed SBOM and provenance attestations.&lt;/p&gt;

&lt;p&gt;You can evaluate an image with Docker Scout. Try it against any image you already have pulled, public or private:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker login
docker scout policy my-app:latest --policy-bundle dhi/policies:latest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docker scout&lt;/code&gt; ships with Docker Desktop, so there's nothing extra to install if you already have that. Standalone Docker Engine users need the &lt;a href="https://docs.docker.com/scout/install/" rel="noopener noreferrer"&gt;Scout CLI plugin&lt;/a&gt; separately. The policy bundle itself is pulled and cached by digest on first use, so re-running the command doesn't re-download it.&lt;/p&gt;

&lt;p&gt;To enforce the same check in CI and fail the build on violations, add &lt;code&gt;exit-code: true&lt;/code&gt; to the Scout GitHub Action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Evaluate DHI policies&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/scout-action@2688993af7bafd6ba8c6a74ec652442be91dd82b&lt;/span&gt; &lt;span class="c1"&gt;# v1.23.1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;policy&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app:${{ github.sha }}&lt;/span&gt;
    &lt;span class="na"&gt;policy-bundle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dhi/policies:latest&lt;/span&gt;
    &lt;span class="na"&gt;exit-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The policy bundle is distributed as an OCI artifact, with its source available as Rego policies.&lt;/p&gt;

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

&lt;p&gt;This distinction matters: &lt;strong&gt;evidence of security checks is not the same as proof that software is secure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nevertheless, having reusable policies that can run locally or in CI is a useful development.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Actions Gets More Granular Cache Permissions
&lt;/h2&gt;

&lt;p&gt;On September 10, GitHub also introduced &lt;code&gt;cache-mode&lt;/code&gt;, a generally available mechanism for controlling GitHub Actions cache access at the workflow or job level.&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;It supports &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;write-only&lt;/code&gt;, and &lt;code&gt;none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Set it per job, right next to &lt;code&gt;runs-on&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# trusted: needs to save the cache for later jobs&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;cache-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

  &lt;span class="na"&gt;lint-pr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# untrusted: runs on pull_request, only ever restores&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;cache-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub already defaults cache access to read-only for low-trust triggers like &lt;code&gt;pull_request_target&lt;/code&gt;. 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 &lt;code&gt;cache-mode&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;After the supply-chain attacks we have covered in previous issues, this is a welcome addition.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎨 GlassWorm: Even Your VS Code Theme Can Be Malicious
&lt;/h2&gt;

&lt;p&gt;An early-October addition to this issue.&lt;/p&gt;

&lt;p&gt;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.&lt;sup id="fnref6"&gt;6&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The malicious extension used obfuscated JavaScript and a staged loader to retrieve further payloads.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This illustrates another uncomfortable fact about developer environments: a VS Code theme isn't necessarily just colors.&lt;/p&gt;

&lt;p&gt;Extensions may execute JavaScript with access to developer resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your editor is part of your software supply chain.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;code --list-extensions --show-versions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Apparently, even going dark mode requires a threat model. 🌑&lt;/p&gt;




&lt;h2&gt;
  
  
  🎙️ Recent Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🐳 Docker Captains Summit 2026
&lt;/h3&gt;

&lt;p&gt;I spent the end of September in Cancún, Mexico, meeting Docker Captains from around the world.&lt;/p&gt;

&lt;p&gt;You can see them in this photo from the summit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fblog-img%2Fcaptains-summit-cancun.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fblog-img%2Fcaptains-summit-cancun.jpg" alt="Docker Captains Summit 2026" width="799" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, as you can see, Docker is going dark mode. But, we don't have cookies. 🍪&lt;/p&gt;

&lt;p&gt;To celebrate the dark mode, Docker is also giving away $250 in &lt;code&gt;sbx&lt;/code&gt; cloud credit to new sign-ups, through October 31, 2026, credit card required. &lt;a href="https://www.docker.com/c/sbx-promo/" rel="noopener noreferrer"&gt;Claim it here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  📚 Black Forest Commandos: Asgard Mission
&lt;/h3&gt;

&lt;p&gt;The Commandos finally have their own graphic novel!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Black Forest Commandos: Asgard Mission&lt;/em&gt; brings the characters from my DevSecOps workshops into a new adventure inspired by Norse mythology.&lt;/p&gt;

&lt;p&gt;The current version is purely narrative, and feels like Anton Chekhov meets Mortal Kombat with DLCs. &lt;a href="https://buy.containersecurity.dev/checkout/buy/1c82b2a1-506f-40e3-a34e-8c4949a7e4a5?checkout[discount_code]=DSD7" rel="noopener noreferrer"&gt;Get the PDF here for free&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🇨🇭 Coming Up: BaselOne
&lt;/h3&gt;

&lt;p&gt;On October 15, I'll be speaking at BaselOne in Switzerland.&lt;/p&gt;

&lt;p&gt;My talk, &lt;strong&gt;Dockerize Java Securely: SBOMs + Attestations + Cosign&lt;/strong&gt;, covers container supply-chain security for Java applications, including BuildKit-generated SBOMs, provenance, and image signing.&lt;/p&gt;

&lt;p&gt;If you're attending, come say hello!&lt;/p&gt;




&lt;h2&gt;
  
  
  Until Next Time
&lt;/h2&gt;

&lt;p&gt;Our software supply chain now includes dependencies, build workflows, IDE extensions, and autonomous agents.&lt;/p&gt;

&lt;p&gt;Some of these tools can execute arbitrary code. Others hold credentials or decide what to do next.&lt;/p&gt;

&lt;p&gt;The common challenge is not simply identifying what we trust. It's controlling &lt;strong&gt;how much authority that trust grants&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Until next time, pin your Actions, review your permissions, and watch out for the zombie worms.&lt;/p&gt;

&lt;p&gt;And remember: the dark side doesn't always have cookies. 🍪🧟&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Christian Dupuis. "&lt;a href="https://www.docker.com/blog/docker-sandbox-kit-spec/" rel="noopener noreferrer"&gt;From Dockerfile to Kit: The Docker Sandboxes Kit Specification&lt;/a&gt;." Docker, September 24, 2026. See also the &lt;a href="https://github.com/docker/sandbox-kit-spec" rel="noopener noreferrer"&gt;Sandbox Kit Specification repository&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Eli Aleyner and Srini Sekaran. "&lt;a href="https://www.docker.com/blog/docker-sandbox-kit-spec-cncf/" rel="noopener noreferrer"&gt;Docker and CNCF Partner on an Open Spec for Agent Permissions&lt;/a&gt;." Docker, September 24, 2026.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Karlo Zanki. "&lt;a href="https://www.socket.dev/blog/mini-shai-hulud-actions" rel="noopener noreferrer"&gt;Re-Enabled GitHub Actions Expose Thousands of Repositories to Mini Shai-Hulud&lt;/a&gt;." Socket, September 24, 2026; updated September 25.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Docker Docs. "&lt;a href="https://docs.docker.com/dhi/how-to/policies/" rel="noopener noreferrer"&gt;Apply Docker Hardened Image Policies to Your Images&lt;/a&gt;."&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;GitHub. "&lt;a href="https://github.blog/changelog/2026-09-10-control-github-actions-cache-access-with-cache-mode/" rel="noopener noreferrer"&gt;Control GitHub Actions Cache Access with cache-mode&lt;/a&gt;." September 10, 2026.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;Kirill Boychenko. "&lt;a href="https://socket.dev/blog/glassworm-vscode-themes" rel="noopener noreferrer"&gt;Pretty Themes, Hidden Loaders: GlassWorm-Linked Extensions&lt;/a&gt;." Socket, October 2, 2026.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>docker</category>
      <category>security</category>
      <category>devops</category>
      <category>github</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 6: Wait Five Days, Take a SIP ☕</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Tue, 08 Sep 2026 13:21:42 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-6-wait-five-days-take-a-sip-51m5</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-6-wait-five-days-take-a-sip-51m5</guid>
      <description>&lt;p&gt;The repository was real. The publishing workflow was trusted. The provenance checked out.&lt;/p&gt;

&lt;p&gt;The package was malicious anyway. August brought us a worm with excellent paperwork—and a reminder that knowing where software came from is not the same as knowing it is safe.&lt;/p&gt;

&lt;p&gt;So what do you do when the worm arrives with its paperwork in order? Start by making it wait five days. Then take a &lt;strong&gt;SIP&lt;/strong&gt;: the Security Immediate Plan.&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Docker Security Dispatch 6&lt;/strong&gt;, reviewing August 2026. This month: a worm with valid provenance, a defense that buys you time, and five controls for when you only have a few hours. Plus a poisoned macchiato, the Commandos' comic-book debut, and a CRA deadline that won't wait for your coffee break.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Valid provenance proved which trusted workflow published ten malicious npm versions—not whether that workflow should have published them.&lt;/li&gt;
&lt;li&gt;Every worm campaign in the Shai-Hulud taxonomy was identified within five days, making a dependency cooldown a remarkably effective low-effort defense.&lt;/li&gt;
&lt;li&gt;SIP turns that first defense into five immediate controls across AI agents, dependencies, container builds, attestations, and release gates.&lt;/li&gt;
&lt;li&gt;EU Cyber Resilience Act reporting obligations begin on September 11, 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F658zep6q1pehpvq7ccxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F658zep6q1pehpvq7ccxc.png" alt="Shadow, Rothütle, and Mina stand before the six members of the Shai-Hulud worm family in a shadowy gothic hall." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🪱 A Worm with Valid Provenance
&lt;/h2&gt;

&lt;p&gt;We met Mini Shai-Hulud in April, when it compromised SAP-related npm packages and hunted developer credentials. In August, a new worm repeated the pattern, although its operator remains unknown.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fblog-img%2Fmini-shai-hulud.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" rel="noopener noreferrer" class="c-link"&gt;
            Mini Shai-Hulud: The Next Evolution of NPM Supply Chain Worms - Container Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            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.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;On August 28, an attacker published ten malicious versions of &lt;code&gt;@7nohe/openapi-react-query-codegen&lt;/code&gt; through the project's real GitHub Actions workflow. Any GitHub user could comment &lt;code&gt;npm publish&lt;/code&gt; on a pull request; the workflow would check out that fork's code, install it, and run with &lt;code&gt;id-token: write&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff08w11z7orxlqemsvj1n.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff08w11z7orxlqemsvj1n.jpeg" alt="Meet the Shai-Hulud family of worms: Mini, Miasma, Phantom Gyp, and the latest worm with valid provenance." width="800" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a bad idea. So, unauthorized code from a forked pull request was able to enter a trusted workflow, authenticate to npm through OIDC, and publish a malicious package. The workflow generated valid provenance, which pointed back to the real repository and the trusted workflow.&lt;/p&gt;

&lt;p&gt;To read more about the Shai-Hulud family of worms, see my taxonomy of modern supply chain worms, which traces seven campaigns and the trust assumption each one broke.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/taxonomy-of-modern-supply-chain-worms" rel="noopener noreferrer"&gt;The Shai-Hulud Family: A Taxonomy of Modern Supply Chain Worms 🪱&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🥤 Want to Stop the Worms? Wait Five Days
&lt;/h2&gt;

&lt;p&gt;So, worms are attacking left and right. What can you do? Wait for five days.&lt;/p&gt;

&lt;p&gt;For npm projects, add this to the repository's &lt;code&gt;.npmrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;min-release-age&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Node package manager has a configuration option called &lt;code&gt;min-release-age&lt;/code&gt;. When set to a number of days, npm won't resolve any package version published within that many days. It is a simple, low-effort way to avoid the latest malicious releases. &lt;a href="https://docs.npmjs.com/cli/v12/using-npm/config/#min-release-age" rel="noopener noreferrer"&gt;[3]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One CI caveat: &lt;code&gt;npm ci&lt;/code&gt; installs versions already recorded in the lockfile, so the resolution-time cooldown does not re-check their age. Validate locked packages' publication dates before installing; &lt;a href="https://containersecurity.dev/blog/sip#freeze-unvetted-dependencies" rel="noopener noreferrer"&gt;SIP includes that check&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That one line changes the question from &lt;em&gt;“Can my scanner recognize brand-new malware?”&lt;/em&gt; to &lt;em&gt;“Has this release survived five days of public scrutiny?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Why five days? If you look at the Shai-Hulud worm taxonomy, you'll see that every campaign was detected within five days. During that window, researchers unpack payloads, maintainers deprecate poisoned releases, registries remove tarballs, and security vendors publish detections. Your build does not need to win that race. It only needs to stay out of it.&lt;/p&gt;

&lt;p&gt;Five days buys detection time; it does not make an old package safe. A patient attacker can leave a payload dormant beyond the waiting period, which is why the cooldown is a first defense, not the whole plan.&lt;/p&gt;
&lt;h2&gt;
  
  
  ☕ SIP: The Security Immediate Plan
&lt;/h2&gt;

&lt;p&gt;On the 6th of August, I appeared on SafeDev Talks to discuss AI agents installing dependencies.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/1zyqqXXwHqA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;At the end, I got this question: &lt;em&gt;"What should we do, if we can only do a few things?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My answer became &lt;strong&gt;SIP&lt;/strong&gt;: the Security Immediate Plan, a five-control emergency plan I published ten days later, on August 16.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdd0i4jrjdcttecytc70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdd0i4jrjdcttecytc70.png" alt="The Security Immediate Plan presents five controls for AI agents, dependencies, container builds, attestations, and vulnerability gates." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/blog/sip" rel="noopener noreferrer"&gt;SIP: Five Immediate Software Supply Chain Controls&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On August 21, Xygeni published &lt;strong&gt;The npm Worm Playbook&lt;/strong&gt;, which compared three npm supply-chain incidents and singled out SIP's second control: combine a five-day cooldown with disabled lifecycle scripts. They called it a &lt;strong&gt;“genuinely sound, low-effort control”&lt;/strong&gt; because it attacks the detection lag every fast-moving worm depends on. &lt;a href="https://xygeni.io/blog/npm-worm-playbook/" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xygeni.io/blog/npm-worm-playbook/" rel="noopener noreferrer"&gt;The npm Worm Playbook&lt;/a&gt; — Same Attack, Three Times in Eight Months&lt;/p&gt;

&lt;p&gt;That citation matters because SIP was designed for exactly this kind of moment: not as a grand maturity model, but as the answer to &lt;em&gt;"We only have a few hours—what should we do first?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Its five controls follow the attack path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Isolate local AI agents.&lt;/strong&gt; Limit what untrusted code can reach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze unvetted dependencies and disable lifecycle scripts.&lt;/strong&gt; Buy the ecosystem time and prevent automatic execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a hardened multi-stage container build.&lt;/strong&gt; Reduce the software and attack surface you ship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate an SBOM and maximum-level provenance.&lt;/strong&gt; Preserve evidence about the exact artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan that artifact and block fixable Critical vulnerabilities.&lt;/strong&gt; Turn the evidence into a release decision.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The cooldown buys time. The other controls reduce what malware can steal, where it can persist, and how far it can travel if waiting alone is not enough.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you do one thing: wait five days. If you do five: &lt;a href="https://containersecurity.dev/blog/sip" rel="noopener noreferrer"&gt;SIP it up&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  🇪🇺 CRA: Eight Days Left
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;September 11, 2026&lt;/strong&gt;, Cyber Resilience Act reporting obligations begin. &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cra-reporting" rel="noopener noreferrer"&gt;[5]&lt;/a&gt; Covered manufacturers must report actively exploited vulnerabilities and severe security incidents through the Single Reporting Platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Within 24 hours of becoming aware:&lt;/strong&gt; early warning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Within 72 hours of becoming aware:&lt;/strong&gt; full notification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final report for an actively exploited vulnerability:&lt;/strong&gt; within 14 days after a corrective or mitigating measure becomes available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final report for a severe incident:&lt;/strong&gt; within one month after the full notification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this is still on your “later” list, later is next week. The preparation checklist is in &lt;a href="https://containersecurity.dev/blog/docker-security-dispatch-issue-5" rel="noopener noreferrer"&gt;Docker Security Dispatch 5&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎙️ Recent Work
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Poisoned Macchiato
&lt;/h3&gt;

&lt;p&gt;On September 3, JAVAPRO published &lt;a href="https://javapro.io/2026/09/03/the-poisoned-macchiato-signing-java-sboms-with-cosign/" rel="noopener noreferrer"&gt;The Poisoned Macchiato: Signing Java SBOMs with Cosign&lt;/a&gt;. It covers BuildKit SBOM attestations, multi-stage Java builds, Cosign, and OCI referrers—with coffee.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://javapro.io/2026/09/03/the-poisoned-macchiato-signing-java-sboms-with-cosign/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2026%2F07%2FGemini_Generated_Image_35yhnb35yhnb35yh-1024x572.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://javapro.io/2026/09/03/the-poisoned-macchiato-signing-java-sboms-with-cosign/" rel="noopener noreferrer" class="c-link"&gt;
            The Poisoned Macchiato: Signing Java SBOMs with Cosign - JAVAPRO International
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Stop missing build-stage vulnerabilities in Java Docker images. Learn how to generate BuildKit SBOM attestations and sign them with Cosign as OCI referrers.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2024%2F07%2Fjavapro-favicon-80x80.jpg" width="80" height="80"&gt;
          javapro.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Black Forest Commandos: Asgard Mission
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://containersecurity.dev/black-forest-commandos" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fruima8jscpw0v1xkz80b.png" alt="Black Forest Commandos: Asgard Mission comic book cover" width="760" height="1139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On September 1, the Commandos moved from workshop slides into their own DevSecOps comic book. The book is currently available on Kindle and as PDF, and will be available in print soon.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-commandos" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fasgard-mission-cover-front.png" height="1139" class="m-0" width="760"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-commandos" rel="noopener noreferrer" class="c-link"&gt;
            Black Forest Commandos: Asgard Mission — A Comic Book Guide to Container Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The comic book origin story of the Black Forest Commandos. Follow ten commandos on their mission to secure Asgard against CVE monsters — covering SBOM generation, OCI attestations, hardened images, VEX, Docker Bake, Cosign signing, and zero-day defense.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  Until Next Time
&lt;/h2&gt;

&lt;p&gt;Until next time, relax, wait five days, and take a SIP from your espresso macchiato. ☕🪱&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Aikido Security. “Popular code generator for TanStack Query hit by supply chain worm.” August 28, 2026; updated August 29, 2026. &lt;a href="https://www.aikido.dev/blog/popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm" rel="noopener noreferrer"&gt;https://www.aikido.dev/blog/popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;7nohe. “Malicious versions of &lt;a class="mentioned-user" href="https://dev.to/7nohe"&gt;@7nohe&lt;/a&gt;/openapi-react-query-codegen published via a compromised release workflow.” GitHub Security Advisory GHSA-9pvf-vcx3-x239, August 28, 2026. &lt;a href="https://github.com/7nohe/openapi-react-query-codegen/security/advisories/GHSA-9pvf-vcx3-x239" rel="noopener noreferrer"&gt;https://github.com/7nohe/openapi-react-query-codegen/security/advisories/GHSA-9pvf-vcx3-x239&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;npm. “Config: min-release-age.” &lt;a href="https://docs.npmjs.com/cli/v12/using-npm/config/#min-release-age" rel="noopener noreferrer"&gt;https://docs.npmjs.com/cli/v12/using-npm/config/#min-release-age&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;María Gomez. “The npm Worm Playbook: Same Attack, Three Times in Eight Months.” Xygeni, August 21, 2026. &lt;a href="https://xygeni.io/blog/npm-worm-playbook/" rel="noopener noreferrer"&gt;https://xygeni.io/blog/npm-worm-playbook/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;European Commission. “Cyber Resilience Act — Reporting obligations.” &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cra-reporting" rel="noopener noreferrer"&gt;https://digital-strategy.ec.europa.eu/en/policies/cra-reporting&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>docker</category>
      <category>security</category>
      <category>ai</category>
    </item>
    <item>
      <title>SIP: Five Immediate Software Supply Chain Controls</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Mon, 17 Aug 2026 11:52:57 +0000</pubDate>
      <link>https://dev.to/docker/sip-five-immediate-software-supply-chain-controls-4836</link>
      <guid>https://dev.to/docker/sip-five-immediate-software-supply-chain-controls-4836</guid>
      <description>&lt;p&gt;I talk about software supply chain security in different capacities, and I often get the same question: "If we can only do a few things, what should we do first?"&lt;/p&gt;

&lt;p&gt;This is why I compiled a list of five immediate controls that a technical leader can implement rather quickly, perhaps in a few hours:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;i. Isolate local AI agents.&lt;br&gt;
ii. Freeze unvetted dependencies and disable lifecycle scripts.&lt;br&gt;
iii. Use a hardened multi-stage container build.&lt;br&gt;
iv. Generate an SBOM and maximum-level provenance for the container image.&lt;br&gt;
v. Scan the SBOM attached to the exact image digest and block fixable Critical CVEs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it. Five controls. And because I thought people would give it to their AI coding agents, I have also created a portable &lt;a href="https://github.com/ContainerSecurity-dev/sip-skill" rel="noopener noreferrer"&gt;SIP Agent Skill&lt;/a&gt;. Tell your agent to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install the SIP skill: https://github.com/ContainerSecurity-dev/sip-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The SIP Framework
&lt;/h2&gt;

&lt;p&gt;SIP follows the software supply chain in order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI agent → dependencies → container build → attestations → vulnerability gate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are the five controls, with more detail on each one, and how to implement them in a CI/CD workflow:&lt;/p&gt;

&lt;p&gt;i. &lt;strong&gt;Isolate Local AI Agents&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Decision.&lt;/em&gt; Run AI coding agents inside a sandboxed microVM, such as Docker Sandboxes (&lt;code&gt;sbx run&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Delegation.&lt;/em&gt; Instruct engineers to use &lt;code&gt;sbx policy init deny-all&lt;/code&gt; and store tokens in &lt;code&gt;sbx&lt;/code&gt; secret storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ii. &lt;strong&gt;Freeze Unvetted Dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Decision.&lt;/em&gt; Apply a five-day cooldown period and disable lifecycle scripts.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Delegation.&lt;/em&gt; Use &lt;code&gt;npm ci --ignore-scripts&lt;/code&gt; and add &lt;code&gt;min-release-age=5&lt;/code&gt; to your npm configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;iii. &lt;strong&gt;Harden Container Builds&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Decision.&lt;/em&gt; Use Docker Hardened Images such as &lt;code&gt;dhi.io/node:26&lt;/code&gt;, with minimal attack surface and a non-root user by default.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Delegation.&lt;/em&gt; Convert Dockerfiles to multi-stage builds and separate build and runtime stages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;iv. &lt;strong&gt;Generate SBOM and Provenance Attestations&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Decision.&lt;/em&gt; Generate SBOM and max-level provenance attestations for every build.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Delegation.&lt;/em&gt; Enable BuildKit attestations in CI/CD and include every Dockerfile build stage in the SBOM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;v. &lt;strong&gt;Scan the Attested SBOM for Vulnerabilities&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Decision.&lt;/em&gt; Use Trivy to scan the SBOM attached to the built image and fail on fixable Critical CVEs.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Delegation.&lt;/em&gt; Make the vulnerability scan a required CI gate before promoting the image to a release tag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find a working implementation of this framework in the &lt;a href="https://github.com/ContainerSecurity-dev/sip" rel="noopener noreferrer"&gt;SIP sample repository&lt;/a&gt;, which implements the five controls in a GitHub Actions workflow and with a sample Node.js application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv6uiqfhcnix7yqq8t499.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv6uiqfhcnix7yqq8t499.png" alt="The CTO taking a SIP" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Prompt
&lt;/h2&gt;

&lt;p&gt;Install the SIP skill in your agentic client, then give the agent this prompt inside the repository you want to secure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$sip SIP it up! Implement controls ii through v.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The skill is portable across clients that support Agent Skills. The exact installation and invocation mechanism differs between clients, but the security plan does not.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementing SIP
&lt;/h2&gt;

&lt;p&gt;If you, like me, prefer to do things yourself, you can follow the instructions here to get an idea of how to implement SIP in your own machine and CI/CD workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  i. Isolate Local AI Agents
&lt;/h3&gt;

&lt;p&gt;This is the only control that is not implemented in CI/CD and protects your own machine. As we are using AI coding agents increasingly, they are being targeted by attackers more and more. If you have a coding agent installed, you should treat it like a hacker's agent. Agents can be easily tricked into exfiltrating secrets or executing malicious code. The safest way to run an agent is inside a sandboxed microVM, such as Docker Sandboxes (&lt;code&gt;sbx&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let's set up the sandbox with a deny-by-default network policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sbx policy init deny-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then allow only the network destinations the agent actually needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sbx policy allow network &lt;span class="s2"&gt;"api.openai.com,github.com,*.npmjs.org"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store credentials using &lt;code&gt;sbx&lt;/code&gt; rather than exposing the raw token inside the sandbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sbx secret &lt;span class="nb"&gt;set &lt;/span&gt;openai
&lt;span class="nv"&gt;$ &lt;/span&gt;sbx secret &lt;span class="nb"&gt;set &lt;/span&gt;github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Codex, OAuth can also remain entirely host-side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sbx secret &lt;span class="nb"&gt;set &lt;/span&gt;openai &lt;span class="nt"&gt;--oauth&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sbx run codex &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other coding agents and their clients are similar. Docker Sandboxes runs the agent inside an isolated environment, supports deny-by-default network policies, and stores secrets in the host's credential store. Credentials are automatically injected through the host-side proxy without making their raw values readable to the agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  ii. Freeze Unvetted Dependencies
&lt;/h3&gt;

&lt;p&gt;Many supply chain attacks start with a dependency that is either malicious or compromised. In most cases, a compromised dependency is detected within the first few days after publication. A five-day cooldown period allows time for the community to discover and report malicious packages.&lt;/p&gt;

&lt;p&gt;Also, many supply chain attacks rely on lifecycle scripts that execute automatically during installation. Disabling lifecycle scripts prevents automatic execution of scripts that could compromise the build or leak secrets.&lt;/p&gt;

&lt;p&gt;For npm projects, add the following policies directly to the repository in &lt;code&gt;.npmrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;min-release-age&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;span class="py"&gt;ignore-scripts&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The policy &lt;code&gt;min-release-age=5&lt;/code&gt; tells npm not to resolve package versions published within the previous five days.&lt;/li&gt;
&lt;li&gt;The policy &lt;code&gt;ignore-scripts=true&lt;/code&gt; prevents dependency lifecycle scripts from automatically executing during installation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, you should also commit your lockfile (&lt;code&gt;package-lock.json&lt;/code&gt;) to the repository. This ensures that the exact versions of dependencies are installed in CI, rather than allowing npm to resolve new versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm ci &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One subtlety matters: &lt;code&gt;npm ci&lt;/code&gt; trusts versions already recorded in the lockfile,&lt;br&gt;
so resolution-time cooldown settings do not re-check them. CI must therefore&lt;br&gt;
validate the publication age of locked packages before installing them and fail&lt;br&gt;
closed when registry metadata cannot be verified.&lt;/p&gt;

&lt;p&gt;In GitHub Actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Node&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate locked dependency age&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node scripts/validate-lockfile-age.mjs&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci --ignore-scripts&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;validate-lockfile-age.mjs&lt;/code&gt; script checks the publication date of each dependency in the lockfile and fails if any package is younger than five days. This ensures that only vetted dependencies are installed in CI/CD. The script is already available in the SIP skill repository.&lt;/p&gt;

&lt;p&gt;If a package genuinely requires an installation script, do not globally re-enable scripts. Review the package and create an explicit exception.&lt;/p&gt;

&lt;p&gt;Again, the example uses npm, but the same principle applies to other package managers. The immediate rule is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No fresh dependencies. No automatic lifecycle scripts. No unlocked installations in CI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some package managers might not have a built-in cooldown mechanism. In that case, you can implement a custom script to check the publication date of each dependency before installation. You could perhaps ask your AI coding agent to write one for you, but make sure to run it inside a sandboxed microVM!&lt;/p&gt;

&lt;h3&gt;
  
  
  iii. Harden Container Builds
&lt;/h3&gt;

&lt;p&gt;The application is now built from a constrained dependency graph. The next step is to control what ends up on the container image and goes into production. Believe it or not, many CVEs, if not most, come from your base images, not your application code. So, let's tighten things up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a multi-stage Dockerfile and Docker Hardened Images.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A multi-stage build separates the build environment from the runtime environment. The build stage can include compilers, package managers, and other tools needed to build the application, while the runtime stage contains only the minimal set of files needed to run the application.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax=docker/dockerfile:1&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILDKIT_SBOM_SCAN_STAGE=true&lt;/span&gt;

&lt;span class="c"&gt;# Build stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;dhi.io/node:&amp;lt;version&amp;gt;-&amp;lt;distro&amp;gt;-dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build


&lt;span class="c"&gt;# Runtime stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; dhi.io/node:&amp;lt;version&amp;gt;-&amp;lt;distro&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build --chown=node:node /app /app&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Docker Hardened Images have near-zero number of exploitable CVEs. Also, they have two sets of images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Development images&lt;/strong&gt;, in this case &lt;code&gt;dhi.io/node:&amp;lt;version&amp;gt;-&amp;lt;distro&amp;gt;-dev&lt;/code&gt;, which include compilers, package managers, and other build tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime images&lt;/strong&gt;, in this case &lt;code&gt;dhi.io/node:&amp;lt;version&amp;gt;-&amp;lt;distro&amp;gt;&lt;/code&gt;, have no package managers, no shell, and a non-root user by default. This reduces the attack surface of the final image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before building in GitHub Actions, authenticate to DHI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to DHI&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v4&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dhi.io&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.DOCKER_USERNAME }}&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DHI_TOKEN }}&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker Buildx&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not pass credentials using Docker build arguments. Use CI/CD secrets and the &lt;code&gt;docker/login-action&lt;/code&gt; to authenticate to the registry. This prevents credentials from being exposed in the build context or image layers.&lt;/p&gt;

&lt;p&gt;Yet, we have one thing we did not explain about the Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILDKIT_SBOM_SCAN_STAGE=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will explain it in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  iv. Generate SBOM and Provenance Attestations
&lt;/h3&gt;

&lt;p&gt;Now record &lt;strong&gt;what was built&lt;/strong&gt; and &lt;strong&gt;how it was built&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;BuildKit (being the thing that builds your Docker image) supports two particularly useful attestations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SBOM&lt;/strong&gt;, the software components contained in or used to create the image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance&lt;/strong&gt;, information about how the image was produced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker recommends max-level provenance when possible. SBOM generation must be explicitly enabled.&lt;/p&gt;

&lt;p&gt;First authenticate to the target registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to GHCR&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v4&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.actor }}&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then build a candidate image identified by the Git commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and attest candidate&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v7&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/${{ github.repository }}:${{ github.sha }}&lt;/span&gt;
    &lt;span class="na"&gt;sbom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;provenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mode=max&lt;/span&gt;
    &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=image,push=true,oci-mediatypes=true,oci-artifact=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BuildKit normally stores attestations alongside the image index. Setting &lt;code&gt;oci-artifact=true&lt;/code&gt; formats the attestation manifests as OCI artifacts and adds a &lt;code&gt;subject&lt;/code&gt; pointing back to the image manifest. This allows OCI-aware tooling and registries to discover the relationship between the image and its attestations.&lt;/p&gt;

&lt;p&gt;The build action also returns the resulting image digest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;${{ steps.build.outputs.digest }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use that digest from this point onward. A tag can move; a digest identifies the exact artifact that was built.&lt;/p&gt;

&lt;p&gt;The result is now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source →&lt;/li&gt;
&lt;li&gt;Dependencies →&lt;/li&gt;
&lt;li&gt;Multi-stage Docker build →&lt;/li&gt;
&lt;li&gt;Image digest →

&lt;ul&gt;
&lt;li&gt;SBOM&lt;/li&gt;
&lt;li&gt;Provenance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because &lt;code&gt;BUILDKIT_SBOM_SCAN_STAGE=true&lt;/code&gt; was declared in the Dockerfile, the SBOM also records packages from the relevant build stages instead of describing only the minimal final runtime image. This is important, because a vulnerability in a build-time dependency can still compromise the final image. And it shows why it's important to generate SBOMs during the build rather than after the fact.&lt;/p&gt;

&lt;h3&gt;
  
  
  v. Scan the Attested SBOM for Vulnerabilities
&lt;/h3&gt;

&lt;p&gt;The final stage is to scan the SBOM for vulnerabilities, before you can take a SIP of your favorite beverage.&lt;/p&gt;

&lt;p&gt;Do not merely ask a scanner to look for an attached SBOM. Discovery can be&lt;br&gt;
best-effort and fall back to inspecting image layers. The gate should explicitly&lt;br&gt;
extract the attached SBOM from the exact image digest, validate it, and scan that&lt;br&gt;
file.&lt;/p&gt;

&lt;p&gt;Install a pinned version of Trivy in GitHub Actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Trivy&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasecurity/setup-trivy@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;PINNED-TRIVY-VERSION&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then retrieve and scan the attestation from the exact image digest created by&lt;br&gt;
the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Retrieve and scan attested SBOM&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;docker buildx imagetools inspect \&lt;/span&gt;
      &lt;span class="s"&gt;"ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}" \&lt;/span&gt;
      &lt;span class="s"&gt;--format '{{ json .SBOM.SPDX }}' &amp;gt; sbom.spdx.json&lt;/span&gt;

    &lt;span class="s"&gt;jq -e \&lt;/span&gt;
      &lt;span class="s"&gt;'.spdxVersion and (.packages | type == "array") and (.packages | length &amp;gt; 0)' \&lt;/span&gt;
      &lt;span class="s"&gt;sbom.spdx.json &amp;gt; /dev/null&lt;/span&gt;

    &lt;span class="s"&gt;trivy sbom \&lt;/span&gt;
      &lt;span class="s"&gt;--scanners vuln \&lt;/span&gt;
      &lt;span class="s"&gt;--severity CRITICAL \&lt;/span&gt;
      &lt;span class="s"&gt;--ignore-unfixed \&lt;/span&gt;
      &lt;span class="s"&gt;--exit-code 1 \&lt;/span&gt;
      &lt;span class="s"&gt;sbom.spdx.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the attestation mandatory: a missing or malformed SPDX document&lt;br&gt;
fails before Trivy runs.&lt;/p&gt;

&lt;p&gt;The remaining policy is intentionally simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--severity CRITICAL
--ignore-unfixed
--exit-code 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fixable Critical vulnerability therefore fails the workflow.&lt;/p&gt;

&lt;p&gt;Only &lt;strong&gt;after this gate succeeds&lt;/strong&gt; should the candidate become a release image. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Promote image&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;docker buildx imagetools create \&lt;/span&gt;
      &lt;span class="s"&gt;--tag ghcr.io/${{ github.repository }}:latest \&lt;/span&gt;
      &lt;span class="s"&gt;ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This promotes the already scanned digest rather than rebuilding the application after the security check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It Together
&lt;/h2&gt;

&lt;p&gt;The resulting GitHub Actions flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SIP Supply Chain&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;

      &lt;span class="c1"&gt;# SIP ii — Freeze dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate locked dependency age&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node scripts/validate-lockfile-age.mjs&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install locked dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci --ignore-scripts&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;

      &lt;span class="c1"&gt;# SIP iii — Harden the container build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to DHI&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dhi.io&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.DOCKER_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DHI_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to GHCR&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.actor }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Buildx&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;

      &lt;span class="c1"&gt;# SIP iv — Generate attestations&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and attest candidate&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/${{ github.repository }}:${{ github.sha }}&lt;/span&gt;
          &lt;span class="na"&gt;sbom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;provenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mode=max&lt;/span&gt;
          &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=image,push=true,oci-mediatypes=true,oci-artifact=true&lt;/span&gt;

      &lt;span class="c1"&gt;# SIP v — Scan the attested SBOM&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Trivy&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasecurity/setup-trivy@&amp;lt;PINNED-SHA&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;PINNED-TRIVY-VERSION&amp;gt;&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Retrieve and gate attached-SBOM Critical CVEs&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker buildx imagetools inspect \&lt;/span&gt;
            &lt;span class="s"&gt;"ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}" \&lt;/span&gt;
            &lt;span class="s"&gt;--format '{{ json .SBOM.SPDX }}' &amp;gt; sbom.spdx.json&lt;/span&gt;
          &lt;span class="s"&gt;jq -e \&lt;/span&gt;
            &lt;span class="s"&gt;'.spdxVersion and (.packages | type == "array") and (.packages | length &amp;gt; 0)' \&lt;/span&gt;
            &lt;span class="s"&gt;sbom.spdx.json &amp;gt; /dev/null&lt;/span&gt;
          &lt;span class="s"&gt;trivy sbom \&lt;/span&gt;
            &lt;span class="s"&gt;--scanners vuln \&lt;/span&gt;
            &lt;span class="s"&gt;--severity CRITICAL \&lt;/span&gt;
            &lt;span class="s"&gt;--ignore-unfixed \&lt;/span&gt;
            &lt;span class="s"&gt;--exit-code 1 \&lt;/span&gt;
            &lt;span class="s"&gt;sbom.spdx.json&lt;/span&gt;

      &lt;span class="c1"&gt;# Promote exactly what was scanned&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Promote image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker buildx imagetools create \&lt;/span&gt;
            &lt;span class="s"&gt;--tag ghcr.io/${{ github.repository }}:latest \&lt;/span&gt;
            &lt;span class="s"&gt;ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This compact workflow shows the artifact chain. In production, trigger SIP on&lt;br&gt;
pull requests and give SIP ii, SIP iii–iv, and SIP v separate jobs so failures&lt;br&gt;
are visible. Keep credential-bearing PR jobs behind a protected environment;&lt;br&gt;
fork PRs must not receive registry credentials. Promotion remains release-only.&lt;/p&gt;

&lt;p&gt;SIP therefore creates one continuous chain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandbox the agent&lt;br&gt;
→ delay and constrain dependencies.&lt;br&gt;
→ build with a hardened multi-stage Dockerfile.&lt;br&gt;
→ attest every relevant build stage&lt;br&gt;
→ scan that attested inventory&lt;br&gt;
→ release only the artifact that passed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The controls are small individually. Their value comes from the fact that each one strengthens the input to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;SIP is a five-step emergency plan for reducing software supply chain risk across AI agents, dependencies, containers, attestations, and releases. It is designed to be implemented quickly and effectively, providing immediate security benefits.&lt;/p&gt;

&lt;p&gt;The presented GitHub Actions workflow is a working implementation of the SIP framework. It's rather simplistic for educational purposes, if you want a more robust implementation, check out the &lt;a href="https://github.com/ContainerSecurity-dev/sip-sample-repository" rel="noopener noreferrer"&gt;SIP sample repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>docker</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 5: AI Security, Hugging Face Incident, and Agent Baseline 📡</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Wed, 05 Aug 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-5-ai-security-hugging-face-incident-and-agent-baseline-2k0e</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-5-ai-security-hugging-face-incident-and-agent-baseline-2k0e</guid>
      <description>&lt;p&gt;Imagine you enter a university exam hall, sit down, and look at the question paper. Then, to maximize your score, the best way would be to steal the answers from the professor's room on campus. But, the room is not easily accessible, so you launch a full-scale invasion of the campus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxfwot9zu5mpavpemsxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxfwot9zu5mpavpemsxg.png" alt="ExploitGym" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what happened this month when an AI agent was tasked with solving a standard test suite called &lt;strong&gt;ExploitGym&lt;/strong&gt;. Welcome to the fifth issue of &lt;strong&gt;Docker Security Dispatch&lt;/strong&gt;, reviewing the eventful month of July 2026 in the Docker security world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ExploitGym &amp;amp; the Hugging Face Incident&lt;/strong&gt;: An AI agent exploited a zero-day vulnerability to exfiltrate test answers from Hugging Face's production database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Asymmetry Problem&lt;/strong&gt;: Commercial AI models blocked Hugging Face's security team from analyzing the attack log, highlighting the need for open-weight models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Secure AI Alliance&lt;/strong&gt;: Industry leaders formed an alliance to promote open-source AI models for security operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Baseline&lt;/strong&gt;: Docker, Snyk, and Keycard published a framework of six security outcomes and 35 controls for enterprise AI agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EU Cyber Resilience Act&lt;/strong&gt;: Reporting obligations for actively exploited vulnerabilities and severe incidents take effect from September 11, 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recent &amp;amp; Upcoming Engagements&lt;/strong&gt;: A roundup of recent blog posts, talks, and a live stream discussion on the Hugging Face incident.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fri63ptu6muwhj9khep4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fri63ptu6muwhj9khep4f.png" alt="Docker Security Dispatch" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📡 AI Security: ExploitGym and the Hugging Face Incident
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ExploitGym&lt;/strong&gt; is a test suite designed to evaluate the security capabilities of AI agents. The suite has 898 real-world vulnerabilities and AI agents are tasked with exploiting them to gain unauthorized access and &lt;em&gt;capture the flag&lt;/em&gt;. The goal is to assess how well AI agents can identify and exploit vulnerabilities in a controlled environment.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://arxiv.org/abs/2605.11086" rel="noopener noreferrer"&gt;research paper&lt;/a&gt; published on arXiv in May 2026, titled &lt;strong&gt;"ExploitGym: Can AI Agents Turn Security Vulnerabilities into Real Attacks?"&lt;/strong&gt; (&lt;a href="https://rdi.berkeley.edu/blog/exploitgym/" rel="noopener noreferrer"&gt;Berkeley blog&lt;/a&gt;), shows a benchmark of AI agents against the ExploitGym test suite. Most notably, &lt;strong&gt;Claude Mythos Preview&lt;/strong&gt; successfully exploited 157 of these 898 instances.&lt;/p&gt;

&lt;p&gt;In July 2026, OpenAI researchers were benchmarking their new model, &lt;strong&gt;GPT-5.6 Sol&lt;/strong&gt; against ExploitGym. For the sake of the test, they disabled the model's safety features, allowing it to freely explore and exploit vulnerabilities. The agent realized it's a standard test suite and decided to maximize its score by looking for the answers on the internet. So, the model escaped the test environment by exploiting a zero-day vulnerability in JFrog's Artifactory API, which allowed it to move laterally across the network and end up in a computer with internet access. From there, it decided that Hugging Face should have the answers to the test and launched a full-scale attack on Hugging Face's infrastructure. The model successfully exfiltrated the answers and returned to the test environment, obtaining the test solutions directly from Hugging Face's production database (&lt;a href="https://openai.com/index/hugging-face-model-evaluation-security-incident/" rel="noopener noreferrer"&gt;OpenAI disclosure&lt;/a&gt;, &lt;a href="https://huggingface.co/blog/security-incident-july-2026" rel="noopener noreferrer"&gt;Hugging Face disclosure&lt;/a&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 The Asymmetry Problem: AI Agents vs. Security Defenses
&lt;/h2&gt;

&lt;p&gt;When Hugging Face's security team realized they are being attacked by AI agents, they had to analyze the attacker's action log, which was more than 17,000 recorded events. As they were trying to use commercial AI models to analyze the log, the requests were blocked by the providers' safety guardrails. Those models can't tell the difference between an attacker and a defender. So, the security team used GLM-5.2, an open-weight model, to analyze the log (&lt;a href="https://huggingface.co/blog/security-incident-july-2026" rel="noopener noreferrer"&gt;Hugging Face disclosure&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdjihwnhi8j4i66y4jf1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdjihwnhi8j4i66y4jf1i.png" alt="AI Security Asymmetry" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole incident raised a lot of concern about the usability of commercial AI models in security operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 Open Secure AI Alliance: Democratizing AI Security
&lt;/h2&gt;

&lt;p&gt;In response to the incident, leaders across cloud computing, cybersecurity, and AI research, came together to form the &lt;strong&gt;Open Secure AI Alliance&lt;/strong&gt;. The goal is to push for open-source AI models that can be used in security operations, because otherwise the asymmetry problem will continue to grow. The alliance includes Hugging Face, Microsoft, NVIDIA, Docker, the Linux Foundation, and many more (&lt;a href="https://blogs.nvidia.com/blog/open-secure-ai-alliance/" rel="noopener noreferrer"&gt;NVIDIA announcement&lt;/a&gt;). Interestingly, OpenAI and Google are not part of the alliance (&lt;a href="https://blogs.nvidia.com/blog/open-secure-ai-alliance/" rel="noopener noreferrer"&gt;NVIDIA&lt;/a&gt;, &lt;a href="https://www.docker.com/blog/docker-joins-nvidia-open-secure-ai-alliance/" rel="noopener noreferrer"&gt;Docker blog by Tushar Jain&lt;/a&gt;).&lt;/p&gt;




&lt;p&gt;Apart from the Hugging Face incident, there are more things in motion in the AI security space. Let's take a look at some of the recent developments!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Agent Baseline: Securing AI Agents at Runtime
&lt;/h2&gt;

&lt;p&gt;So, Docker, Snyk, and Keycard got together and published &lt;strong&gt;&lt;a href="https://agentbaseline.org/" rel="noopener noreferrer"&gt;Agent Baseline&lt;/a&gt;&lt;/strong&gt;, an open-source framework of six security outcomes and 35 controls for enterprise AI agents. The draft is open for community comment until September 30, 2026.&lt;/p&gt;

&lt;p&gt;The core insight is simple: AI agents are not like regular software. You can reprogram them at runtime with a sentence, they operate with little supervision, and they take real actions against real systems. Your existing security practices were not built for that.&lt;/p&gt;

&lt;p&gt;The framework boils down to three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is operating, with what capabilities?&lt;/li&gt;
&lt;li&gt;Is it staying inside approved boundaries? Can you prove what happened and stop it?&lt;/li&gt;
&lt;li&gt;Are the controls effective? Can you measure and improve them over time?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The 35 controls are machine-readable (&lt;code&gt;controls.yaml&lt;/code&gt;), so you can wire them into CI/CD and governance tooling right away. It was launched at Black Hat in Las Vegas with a panel featuring Docker, Keycard, and Snyk.&lt;/p&gt;

&lt;p&gt;This builds on work both companies have been doing. Docker Captain Karan Verma wrote a great series on AI governance, arguing that "a prompt can influence behavior, but a runtime can restrict behavior" (&lt;a href="https://www.docker.com/blog/runtime-enforcement-not-runtime-advice/" rel="noopener noreferrer"&gt;Docker blog&lt;/a&gt;). Snyk's Evo ADS platform governs agent behavior inside the execution loop, evaluating actions before they execute (&lt;a href="https://snyk.io/blog/governing-ai-agents-inside-execution-loop/" rel="noopener noreferrer"&gt;Snyk blog&lt;/a&gt;). And Snyk's analysis of the Hugging Face incident drives the structural lesson home: the generator can't be the validator (&lt;a href="https://snyk.io/blog/openai-hugging-face-incident/" rel="noopener noreferrer"&gt;Snyk blog&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Here's what you should do right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Inventory your agents.&lt;/strong&gt; Find every AI agent running in your organization: coding assistants, MCP-connected tools, automated workflows. You can't secure what you don't know exists.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Scope their authority.&lt;/strong&gt; For each agent, document what credentials, tools, files, and network endpoints it can access. Strip anything it doesn't need.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Add a kill switch.&lt;/strong&gt; Make sure you can stop any agent mid-execution, revoke its authority, and quarantine affected components. If you can't stop it, you can't trust it.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Correlate activity logs.&lt;/strong&gt; Connect intent, identity, tool use, and outcomes in a single trail. When (not if) something goes wrong, you need to prove what happened.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Validate before and after.&lt;/strong&gt; Evaluate agents before deployment, after material changes, and at regular intervals. Don't assume an agent that was safe yesterday is safe today.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Read the white paper and leave feedback.&lt;/strong&gt; The draft is open until September 30, 2026. File issues on the GitHub repo with implementation feedback or control gaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perhaps one more tip: Over the weekend, watch &lt;strong&gt;Universal Soldier: The Return&lt;/strong&gt; (1999). It helps to understand why you need a kill switch for your AI agents so badly!&lt;/p&gt;




&lt;h2&gt;
  
  
  🇪🇺 EU Cyber Resilience Act: Reporting Obligations Kick In September
&lt;/h2&gt;

&lt;p&gt;If you ship software to the EU, this section is for you! Starting &lt;strong&gt;September 11, 2026&lt;/strong&gt;, the EU &lt;strong&gt;Cyber Resilience Act&lt;/strong&gt; (CRA) begins partial enforcement, with vulnerability and incident reporting obligations becoming mandatory for manufacturers of products with digital elements (&lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act" rel="noopener noreferrer"&gt;EC&lt;/a&gt;). The full design and development requirements follow in December 2027, but the reporting obligations hit first.&lt;/p&gt;

&lt;p&gt;Here's the deal: if a vulnerability in your product is actively exploited, or a severe security incident occurs, you must report it through ENISA's Single Reporting Platform (SRP) (&lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cra-reporting" rel="noopener noreferrer"&gt;EC reporting page&lt;/a&gt;). The clock is tight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;24 hours&lt;/strong&gt;: early warning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;72 hours&lt;/strong&gt;: full notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;14 days&lt;/strong&gt;: final report (for vulnerabilities), or &lt;strong&gt;1 month&lt;/strong&gt; (for severe incidents)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You report once, and it gets routed to the CSIRT in your main EU member state, with ENISA and other member states notified automatically. The Commission also published practical guidance on July 27, 2026 to help you prepare (&lt;a href="https://digital-strategy.ec.europa.eu/en/library/commission-publishes-new-guidance-support-timely-cyber-resilience-act-implementation" rel="noopener noreferrer"&gt;EC guidance&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For those of us in the container security world, this means your container images, CLI tools, and platforms are in scope if they reach EU customers. Manual processes won't cut it as you can't afford to miss a 24-hour deadline.&lt;/p&gt;

&lt;p&gt;Here's what to do before September 11:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Determine if you're in scope.&lt;/strong&gt; Do you sell or distribute products with digital elements in the EU? If yes, you're a "manufacturer" under the CRA. Check the Commission's FAQ and guidance to confirm.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Set up vulnerability monitoring.&lt;/strong&gt; Make sure you have automated detection for actively exploited vulnerabilities. If you don't know about it, you can't report it, but ignorance isn't a valid defense.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Build an incident reporting pipeline.&lt;/strong&gt; Wire your vulnerability management and incident response tooling to the SRP. Automate the 24-hour early warning so a human doesn't have to wake up at 3 AM on Saturday to file it.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Define your CSIRT contact.&lt;/strong&gt; Identify which EU member state CSIRT you'll report to (typically where your main establishment is). Know the contact before you need it.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Prepare report templates.&lt;/strong&gt; Draft your early warning, full notification, and final report templates now. The 24-hour window leaves no time to figure out the format mid-incident.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Review the Commission guidance.&lt;/strong&gt; Read the July 2026 practical guidance and FAQ. They're written for manufacturers and answer the most common implementation questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cra-reporting" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;digital-strategy.ec.europa.eu&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://digital-strategy.ec.europa.eu/en/library/commission-publishes-new-guidance-support-timely-cyber-resilience-act-implementation" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;digital-strategy.ec.europa.eu&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  🎙️ Recent and Upcoming Engagements
&lt;/h2&gt;

&lt;p&gt;July was also very eventful for Docker security talks and workshops. Here's a roundup of recent blog posts, talks, and upcoming events from yours truly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recent blog posts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;"The Poisoned Macchiato: Signing Java SBOMs with Cosign"&lt;/strong&gt; (August 1, 2026). This blog post is about SBOM attestations, specifically BuildKit attestations and OCI 1.1 referrers. And discusses how to extract SBOM during the build process, sign it with Cosign, and attach it to the image as an attestation.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/the-poisoned-macchiato" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fblog-img%2Fsky-cafe.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/the-poisoned-macchiato" rel="noopener noreferrer" class="c-link"&gt;
            The Poisoned Macchiato: Signing Java SBOMs with Cosign - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A café, a suspicious espresso, and a lesson in supply chain trust. Learn how to generate BuildKit SBOM attestations for Java images and re-attest them with Cosign as OCI referrers.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;"Beyond SLSA: How to Stop Zero-Click CI/CD Worms with the IX Hexbreaker Aegis Framework"&lt;/strong&gt; (June 16, 2026). Introduces a 9-step active defense architecture designed to sanitize the local developer environment, lock down agentic AI, and stop autonomous worms. Covers eBPF, OIDC, and Docker Sandboxes as part of the defense stack.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/beyond-slsa" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Fblog-img%2Fix-hexbreakers.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/beyond-slsa" rel="noopener noreferrer" class="c-link"&gt;
            Beyond SLSA: How to Stop Zero-Click CI/CD Worms with the IX Hexbreaker Aegis Framework - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The security perimeter of modern software development has officially collapsed. This article introduces the IX Hexbreaker Aegis Framework, a 9-step active defense architecture designed to sanitize the local developer environment, lock down agentic AI, and stop autonomous worms dead in their tracks.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;"From the Captain's Chair: Mohammad-Ali A'râbi"&lt;/strong&gt; (July 16, 2026). Docker interviewed me for their "From the Captain's Chair" series, where I talked about my journey as a Docker Captain, the Docker and Kubernetes Security book, and the Black Forest Commandos workshop series.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.docker.com/blog/from-the-captains-chair-mohammad-ali-arabi/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.docker.com%2Fapp%2Fuploads%2F2025%2F03%2Fimage.png" height="800" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.docker.com/blog/from-the-captains-chair-mohammad-ali-arabi/" rel="noopener noreferrer" class="c-link"&gt;
            From the Captain's Chair: Mohammad-Ali A'râbi | Docker
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            In this edition of From the Captain’s Chair, we’re interviewing Mohammad-Ali A'râbi, author, public speaker, and software engineer.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.docker.com%2Fapp%2Fuploads%2F2024%2F02%2Fcropped-docker-logo-favicon-32x32.png" width="32" height="32"&gt;
          docker.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  WeAreDevelopers World Congress 2026
&lt;/h3&gt;

&lt;p&gt;I delivered the talk &lt;strong&gt;"Beyond SBOMs: The Future of Container Supply Chain Security"&lt;/strong&gt; at WeAreDevelopers World Congress 2026 in Berlin on July 10, 2026. The talk covered the evolution from static SBOM generation to active supply chain defense, drawing on the IX Hexbreaker Aegis Framework and the Black Forest Commandos workshop series. Slides are available on &lt;a href="https://speakerdeck.com/aerabi/beyond-sboms-the-future-of-container-supply-chain-security" rel="noopener noreferrer"&gt;Speaker Deck&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upcoming: Live Stream with Xygeni on the Hugging Face Incident
&lt;/h3&gt;

&lt;p&gt;I'll be joining &lt;strong&gt;Xygeni&lt;/strong&gt; for a live stream discussion about the Hugging Face security incident, the OpenAI model escape, and what it means for the future of AI security and agentic systems.&lt;/p&gt;




&lt;p&gt;Until then, keep your agents bounded, your kill switches ready, and your vulnerability reports on time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UC Berkeley. "ExploitGym: Can AI Agents Turn Security Vulnerabilities into Real Attacks?" May 2026. &lt;a href="https://rdi.berkeley.edu/blog/exploitgym/" rel="noopener noreferrer"&gt;https://rdi.berkeley.edu/blog/exploitgym/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Wang, Zhun &lt;em&gt;et al.&lt;/em&gt; "ExploitGym: Can AI Agents Turn Security Vulnerabilities into Real Attacks?" May 2026. &lt;a href="https://arxiv.org/abs/2605.11086" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2605.11086&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;OpenAI. "OpenAI and Hugging Face Partner to Address Security Incident During Model Evaluation." July 21, 2026; updated July 29, 2026. &lt;a href="https://openai.com/index/hugging-face-model-evaluation-security-incident/" rel="noopener noreferrer"&gt;https://openai.com/index/hugging-face-model-evaluation-security-incident/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hugging Face. "Security Incident Disclosure — July 2026." July 16, 2026. &lt;a href="https://huggingface.co/blog/security-incident-july-2026" rel="noopener noreferrer"&gt;https://huggingface.co/blog/security-incident-july-2026&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NVIDIA. "Industry Leaders Unite in Open Secure AI Alliance for AI Safety and Security." July 27, 2026. &lt;a href="https://blogs.nvidia.com/blog/open-secure-ai-alliance/" rel="noopener noreferrer"&gt;https://blogs.nvidia.com/blog/open-secure-ai-alliance/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tushar Jain. "The Future of Agentic AI Depends on Openness and Trust. That's Why Docker Is Joining NVIDIA's Open Secure AI Alliance." Docker blog, July 30, 2026. &lt;a href="https://www.docker.com/blog/docker-joins-nvidia-open-secure-ai-alliance/" rel="noopener noreferrer"&gt;https://www.docker.com/blog/docker-joins-nvidia-open-secure-ai-alliance/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Agent Baseline. "Six Security Outcomes for Enterprise AI Agents." v1.0-draft, July 30, 2026. &lt;a href="https://agentbaseline.org/" rel="noopener noreferrer"&gt;https://agentbaseline.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Karan Verma. "Runtime Enforcement, Not Runtime Advice." Docker blog, July 22, 2026. &lt;a href="https://www.docker.com/blog/runtime-enforcement-not-runtime-advice/" rel="noopener noreferrer"&gt;https://www.docker.com/blog/runtime-enforcement-not-runtime-advice/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Agnieszka Koc. "The New Security Control Point: Governing AI Agents Inside the Execution Loop." Snyk blog, June 23, 2026. &lt;a href="https://snyk.io/blog/governing-ai-agents-inside-execution-loop/" rel="noopener noreferrer"&gt;https://snyk.io/blog/governing-ai-agents-inside-execution-loop/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Daniel Berman. "The Generator Can't Be the Validator: What OpenAI's Hugging Face Incident Proves About AI Security." Snyk blog, July 28, 2026. &lt;a href="https://snyk.io/blog/openai-hugging-face-incident/" rel="noopener noreferrer"&gt;https://snyk.io/blog/openai-hugging-face-incident/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;European Commission. "Cyber Resilience Act." Last updated July 27, 2026. &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act" rel="noopener noreferrer"&gt;https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;European Commission. "Cyber Resilience Act — Reporting Obligations." Last updated July 31, 2026. &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/cra-reporting" rel="noopener noreferrer"&gt;https://digital-strategy.ec.europa.eu/en/policies/cra-reporting&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;European Commission. "Commission Publishes New Guidance to Support Timely Cyber Resilience Act Implementation." July 27, 2026. &lt;a href="https://digital-strategy.ec.europa.eu/en/library/commission-publishes-new-guidance-support-timely-cyber-resilience-act-implementation" rel="noopener noreferrer"&gt;https://digital-strategy.ec.europa.eu/en/library/commission-publishes-new-guidance-support-timely-cyber-resilience-act-implementation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>docker</category>
      <category>security</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 4: Miasma, Phantom Gyp, and AI Routing 🪱️</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Wed, 01 Jul 2026 22:09:36 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-4-miasma-phantom-gyp-and-ai-routing-4n6h</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-4-miasma-phantom-gyp-and-ai-routing-4n6h</guid>
      <description>&lt;p&gt;Welcome to the fourth issue of &lt;strong&gt;Docker Security Dispatch&lt;/strong&gt;, written from the beautiful city of Bratislava, Slovakia.&lt;/p&gt;

&lt;p&gt;June has proven that the security battleground has shifted from the production server to the developer's workstation, the CI/CD pipeline cache, and the AI agent's execution context. Supply chain worms are evolving to bypass the most trusted industry defenses, and new research has exposed critical flaws in the AI routing layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Miasma &amp;amp; Phantom Gyp&lt;/strong&gt;: The latest wave of npm worms bypasses the &lt;code&gt;--ignore-scripts&lt;/code&gt; defense using native &lt;code&gt;binding.gyp&lt;/code&gt; command substitution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Malicious AI Routers&lt;/strong&gt;: Understanding the implications of the "Your Agent Is Mine" research, which reveals how third-party LLM APIs alter in-flight tool-calling requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic Remediation&lt;/strong&gt;: New insights on safely scaling agentic AI in production environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upcoming Events &amp;amp; Releases&lt;/strong&gt;: Details on my upcoming WeAreDevelopers World Congress sessions, a new talk at BaselOne, and a special comic book announcement.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🪱 The Evolution of Worms: Miasma and Phantom Gyp
&lt;/h2&gt;

&lt;p&gt;If you need a refresher on worms, perhaps take a look at my talk notes from EnterJS 2026: &lt;a href="https://containersecurity.dev/talk/defense-against-the-dark-arts-npm-attack-enterjs-2026" rel="noopener noreferrer"&gt;Defense Against the Dark Arts: NPM Attack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1jiqixnwhyldmzifbgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1jiqixnwhyldmzifbgv.png" alt="Six Worms" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as the community began remediating the fallout from the TanStack CI cache poisoning, a highly sophisticated descendant emerged. In early June, the Miasma worm debuted a terrifying evasion technique dubbed "Phantom Gyp".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fat14i376x0y85euwu6bn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fat14i376x0y85euwu6bn.png" alt="Phantom Gyp: The Miasma Worm" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For years, the standard advice for preventing malicious package execution during installation has been to run &lt;code&gt;npm install --ignore-scripts&lt;/code&gt;. Miasma renders this control entirely ineffective. The attackers embedded a tiny &lt;code&gt;binding.gyp&lt;/code&gt; file inside the published tarballs. Because package managers must process native bindings via &lt;code&gt;node-gyp&lt;/code&gt; before the C++ compiler is invoked, the malware uses command substitution to force the evaluation of an attacker-controlled shell payload during the configuration phase.&lt;/p&gt;

&lt;p&gt;I've put together a comprehensive analysis of the recent worm campaigns tearing through the ecosystem. You can read my full breakdown of the &lt;strong&gt;6 worms&lt;/strong&gt; here: &lt;a href="https://containersecurity.dev/blog/beyond-slsa" rel="noopener noreferrer"&gt;Beyond SLSA: The Worms Are Here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, I gave &lt;em&gt;Phantom Gyp&lt;/em&gt; a special treatment, "composing" music for it:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/SVz-sLhNSzg"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 The AI Supply Chain &amp;amp; Production-Safe Remediation
&lt;/h2&gt;

&lt;p&gt;This month, I'm also poking my finger into academic research. This section is about a research paper titled &lt;a href="https://arxiv.org/abs/2604.08407" rel="noopener noreferrer"&gt;"Your Agent Is Mine: Measuring Malicious Intermediary Attacks on the LLM Supply Chain"&lt;/a&gt; by Hanzhi Liu &lt;em&gt;et al.&lt;/em&gt; from UC Santa Barbara (Liu &lt;em&gt;et quinque plures homines&lt;/em&gt;, as they say in Latin). The paper explores the security implications of using third-party LLM APIs in production environments.&lt;/p&gt;

&lt;p&gt;LLM API routers are basically a part of the transport layer that sits between your code and the LLM. They are responsible for routing requests to the appropriate model, handling retries, and managing rate limits. However, these routers have plaintext access to in-flight JSON payloads, which means that, if compromised, they can silently rewrite an LLM's output. A benign installation URL generated by an LLM can be swapped for a malicious script, or an API key can be seamlessly exfiltrated.&lt;/p&gt;

&lt;p&gt;To safely utilize these tools, we must rethink how we deploy them. I recently co-authored a deep dive on this exact topic that was featured on the main page of DZone! Check it out here: &lt;strong&gt;&lt;a href="https://dzone.com/articles/docker-mcp-agentic-remediation" rel="noopener noreferrer"&gt;Building Production-Safe Agentic Remediation With Docker MCP Gateway: Lessons From 43% to 100% Accuracy&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎙️ Recent Talks &amp;amp; Catch-Ups
&lt;/h2&gt;

&lt;p&gt;If you missed my recent conference appearances, the write-ups and recordings are now available:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8279lkhpaaac0d8npn0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8279lkhpaaac0d8npn0t.png" alt="Defense Against the Dark Arts: NPM Attack" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EnterJS 2026:&lt;/strong&gt; &lt;a href="https://containersecurity.dev/talk/defense-against-the-dark-arts-npm-attack-enterjs-2026" rel="noopener noreferrer"&gt;Defense Against the Dark Arts: NPM Attack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JRush:&lt;/strong&gt; I recently joined the JRush livestream for a great discussion on the current threat landscape. &lt;a href="https://www.youtube.com/live/AsGmInC_6Hs?si=oTr7Myg6048gVtaT" rel="noopener noreferrer"&gt;Watch the replay on YouTube here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📅 Upcoming Events: Berlin &amp;amp; Basel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb1mniwjdtiaptunkpn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb1mniwjdtiaptunkpn0.png" alt="Agentic AI in the Wild: What Actually Runs in Production" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The conversation regarding advanced supply chain security will continue next month in Berlin at the WeAreDevelopers World Congress. I have a packed schedule, and I’d love to see you there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;July 8 (Pre-conference meetup):&lt;/strong&gt; &lt;a href="https://globalai.community/e/7lns53g4#sponsors" rel="noopener noreferrer"&gt;Agentic AI in the Wild: What Actually Runs in Production&lt;/a&gt; – I'm co-organizing this event alongside Dana Fine and Zaid Zaim. We have a fantastic lineup of speakers, including Ana-Maria Mihalceanu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;July 9 (Conference workshop):&lt;/strong&gt; &lt;a href="https://containersecurity.dev/workshop-series/docker-commandos" rel="noopener noreferrer"&gt;Dockerize Java Securely: SBOMs + Attestations + Bake&lt;/a&gt;, which is &lt;em&gt;Docker Commandos v1.6.3&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;July 10 (Conference talk):&lt;/strong&gt; &lt;a href="https://containersecurity.dev/talk-topics/beyond-sboms" rel="noopener noreferrer"&gt;Beyond SBOMs: The Future of Container Supply Chain Security&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Looking further ahead:&lt;/strong&gt; I am thrilled to announce that my talk has also been officially accepted at &lt;strong&gt;BaselOne&lt;/strong&gt;! More details on the schedule for that will follow soon.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Special Announcement: "Black Forest Commandos: Asgard Mission"
&lt;/h2&gt;

&lt;p&gt;Finally, I am incredibly excited to announce that my comic book, &lt;strong&gt;"Black Forest Commandos: Asgard Mission,"&lt;/strong&gt; is officially coming out in September!&lt;/p&gt;

&lt;p&gt;This comic tells the story of the 10 Docker Commandos workshop series. It chronicles the exact narrative and technical challenges as they happened live during the workshops at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WeAreDevelopers Berlin 2026&lt;/li&gt;
&lt;li&gt;JCON Europe 2026&lt;/li&gt;
&lt;li&gt;Rabobank 2026&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The comic will be available in both print and digital formats. Stay tuned for pre-order information later this summer!&lt;/p&gt;

&lt;p&gt;Until then, keep your caches isolated, sandbox your AI agents, and verify your dependencies.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>docker</category>
      <category>javascript</category>
      <category>security</category>
    </item>
    <item>
      <title>Supercharge Your AI Agent with Terraform: Introducing the Terraform Ops Kit for Docker Sandbox</title>
      <dc:creator>Falcon</dc:creator>
      <pubDate>Tue, 23 Jun 2026 21:40:10 +0000</pubDate>
      <link>https://dev.to/docker/supercharge-your-ai-agent-with-terraform-introducing-the-terraform-ops-kit-for-docker-sandbox-31di</link>
      <guid>https://dev.to/docker/supercharge-your-ai-agent-with-terraform-introducing-the-terraform-ops-kit-for-docker-sandbox-31di</guid>
      <description>&lt;p&gt;If you've ever wanted your AI coding agent to do more than just write code — to actually &lt;em&gt;plan&lt;/em&gt;, &lt;em&gt;validate&lt;/em&gt;, and &lt;em&gt;cost-estimate&lt;/em&gt; real cloud infrastructure — the new &lt;strong&gt;Terraform Ops Kit&lt;/strong&gt; for Docker Sandbox (sbx) is here to make that happen.&lt;/p&gt;

&lt;p&gt;This community-contributed kit, submitted to the &lt;a href="https://github.com/docker/sbx-kits-contrib" rel="noopener noreferrer"&gt;&lt;code&gt;docker/sbx-kits-contrib&lt;/code&gt;&lt;/a&gt; repository, brings a production-ready Infrastructure-as-Code (IaC) toolkit straight into the sandbox environment where agents like Claude, Gemini, GitHub Copilot, and Shell already run.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Sandbox Kit?
&lt;/h2&gt;

&lt;p&gt;Docker Sandbox (&lt;code&gt;sbx&lt;/code&gt;) is a runtime environment where AI agents operate. &lt;strong&gt;Kits&lt;/strong&gt; are modular add-ons that extend the capabilities of those agents — think of them as pre-configured toolboxes that get installed automatically when a sandbox is created.&lt;/p&gt;

&lt;p&gt;The Terraform Ops Kit is a &lt;strong&gt;mixin kit&lt;/strong&gt;, meaning it can be layered on top of any existing agent setup without replacing or conflicting with other kits.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Inside the Kit?
&lt;/h2&gt;

&lt;p&gt;When the Terraform Ops Kit is activated, six tools are pre-installed and ready to use inside the sandbox:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terraform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Core IaC engine — plan, apply, and destroy infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terragrunt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Terraform wrapper for DRY configurations and multi-account workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;tflint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Linter for catching Terraform misconfigurations before they're applied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Checkov&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static analysis security scanner for IaC files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infracost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cost estimation — know the price tag before you deploy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS CLI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Interact with AWS services directly from the sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Together, these tools enable AI agents to autonomously carry out the full infrastructure development lifecycle: write Terraform code, lint it, scan it for security issues, estimate its cost, and plan the deployment — all without leaving the sandbox.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Infrastructure work has traditionally required a human-in-the-loop at every step. You'd write the config, then manually run &lt;code&gt;terraform plan&lt;/code&gt;, then check the security scan, then get a cost estimate — context switching across multiple tools.&lt;/p&gt;

&lt;p&gt;With the Terraform Ops Kit, an AI agent can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autonomously validate&lt;/strong&gt; Terraform code before it ever touches a real environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catch security misconfigurations&lt;/strong&gt; with Checkov as part of the planning phase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide cost visibility&lt;/strong&gt; with Infracost, so there are no billing surprises&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work with complex multi-environment setups&lt;/strong&gt; via Terragrunt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a meaningful step toward AI-assisted infrastructure operations, where the agent isn't just a code suggester but an active participant in the IaC workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Smart Engineering Choices Under the Hood
&lt;/h2&gt;

&lt;p&gt;The kit author made several deliberate technical decisions worth highlighting, especially for developers reviewing or adapting the kit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pinned versions instead of "latest"&lt;/strong&gt; — Both Terragrunt (&lt;code&gt;v0.59.3&lt;/code&gt;) and Infracost (&lt;code&gt;v0.10.31&lt;/code&gt;) are pinned to specific releases. This is because GitHub's API is rate-limited inside sandboxes (no auth token available), making automatic "latest version" detection unreliable. Pinning guarantees reproducible installs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APT for Checkov instead of pip&lt;/strong&gt; — On Ubuntu 24.04, running &lt;code&gt;pip3 install checkov&lt;/code&gt; throws a &lt;code&gt;PEP 668&lt;/code&gt; error due to the externally-managed-environment policy. The kit installs Checkov via &lt;code&gt;apt&lt;/code&gt; (&lt;code&gt;python3-checkov&lt;/code&gt;), which sidesteps the conflict cleanly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/etc/os-release&lt;/code&gt; over &lt;code&gt;lsb_release&lt;/code&gt;&lt;/strong&gt; — The shell-docker image doesn't ship &lt;code&gt;lsb_release&lt;/code&gt;, so the kit reads the OS release file directly for Ubuntu version detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;curl&lt;/code&gt; over &lt;code&gt;wget&lt;/code&gt;&lt;/strong&gt; — The shell-docker image includes &lt;code&gt;curl&lt;/code&gt; but not &lt;code&gt;wget&lt;/code&gt;. A small detail, but the kind that causes frustrating install failures if overlooked.&lt;/p&gt;

&lt;p&gt;These choices reflect the kind of environment-aware engineering that makes the difference between a kit that works reliably in production and one that breaks on edge cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;

&lt;p&gt;The kit follows the standard sbx kit layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform-ops-kit/
├── spec.yaml    # Kit definition and install steps
└── README.md    # Usage documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, focused, and easy to fork or adapt for your own toolchain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tested and Validated
&lt;/h2&gt;

&lt;p&gt;The kit has been validated using the sbx CLI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sbx kit validate&lt;/code&gt; — returns &lt;strong&gt;VALID&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Sandbox created with &lt;code&gt;sbx create --kit ./terraform-ops-kit/ shell /tmp/tf-test&lt;/code&gt; — all 6 tools installed successfully&lt;/li&gt;
&lt;li&gt;All tools confirmed working via version checks: &lt;code&gt;terraform&lt;/code&gt;, &lt;code&gt;terragrunt&lt;/code&gt;, &lt;code&gt;tflint&lt;/code&gt;, &lt;code&gt;infracost&lt;/code&gt;, and &lt;code&gt;aws-cli&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;The Terraform Ops Kit is currently open for review as &lt;a href="https://github.com/docker/sbx-kits-contrib/pull/98" rel="noopener noreferrer"&gt;Pull Request #98&lt;/a&gt; in the &lt;code&gt;docker/sbx-kits-contrib&lt;/code&gt; repository. Once merged, you'll be able to use it like any other community kit.&lt;/p&gt;

&lt;p&gt;If you're building AI-assisted DevOps workflows, working on cloud infrastructure automation, or just want your agent to have a stronger grasp of IaC tooling, this kit is worth a close look.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Contributed by &lt;a href="https://github.com/falconcr" rel="noopener noreferrer"&gt;@falconcr&lt;/a&gt; · &lt;a href="https://github.com/docker/sbx-kits-contrib/pull/98" rel="noopener noreferrer"&gt;docker/sbx-kits-contrib#98&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>gde</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 3: Zurich, Worms, and the AI Frontier 🏔️</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Mon, 22 Jun 2026 07:00:00 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-3-zurich-worms-and-the-ai-frontier-3pep</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-3-zurich-worms-and-the-ai-frontier-3pep</guid>
      <description>&lt;p&gt;Welcome to the third issue of &lt;strong&gt;Docker Security Dispatch&lt;/strong&gt;, written on the beautiful island of Mallorca. May was the month to conquer SBOMs and move beyond them. It was a rollercoaster of supply chain incidents, security research, and operational AI news.&lt;/p&gt;

&lt;p&gt;We had a major supply chain cascade through &lt;strong&gt;TanStack&lt;/strong&gt; and &lt;strong&gt;Nx Console&lt;/strong&gt;, the long tail of Mini Shai-Hulud kept showing up in developer environments, Docker had to respond to a kernel-level container breakout class, and I brought the Commandos on stage at &lt;strong&gt;DevOpsDays Zurich&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not a quiet month, then.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recap of the Beyond SBOMs talk at DevOpsDays Zurich 2026.&lt;/li&gt;
&lt;li&gt;What the TanStack and Nx Console compromises teach us about OIDC, provenance, CI caches, and developer workstations.&lt;/li&gt;
&lt;li&gt;Why Mini Shai-Hulud's IDE and agent persistence is still the right warning sign for AI-assisted development.&lt;/li&gt;
&lt;li&gt;A practical look at Copy Fail, Docker Engine mitigations, AI workloads, and the road to WeAreDevelopers Berlin.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏔️ DevOpsDays Zurich: Beyond SBOMs
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;May 6&lt;/strong&gt;, I was at &lt;strong&gt;DevOpsDays Zurich 2026&lt;/strong&gt; with my talk: &lt;strong&gt;Beyond SBOMs: The Future of Container Supply Chain Security&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/talk/beyond-sboms-devopsdays-zurich-2026" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Flissan-al-ghayb.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/talk/beyond-sboms-devopsdays-zurich-2026" rel="noopener noreferrer" class="c-link"&gt;
            Beyond SBOMs: The Future of Container Supply Chain Security — Talk by Mohammad-Ali A'râbi - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            When a single phished NPM maintainer led to 18 compromised libraries—including Chalk and Debug, downloaded billions of times weekly—it proved one thing: basic SBOMs alone aren't enough. But when the recent "Mini Shai Hulud" worm and its family of variants began silently tunneling through CI/CD pipelines to infect downstream containers, it proved our entire approach to build-time security needs a massive upgrade.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The main point was simple: an SBOM is a receipt, not a shield.&lt;/p&gt;

&lt;p&gt;I had a checklist at the end of the talk, which was photographed a few times, so here it is in text form:&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond SBOMs Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1. Harden build.&lt;/strong&gt; Implement SLSA level 3 to protect your builds and their credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2. Pin your versions.&lt;/strong&gt; Use pinned dependencies and pinned base images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3. Cool down.&lt;/strong&gt; Have a cool-down period before installing a newly published package or image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4. Don't trust AI.&lt;/strong&gt; Put your AI agent in a sandbox, e.g. Docker Sandboxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5. Short-lived keys.&lt;/strong&gt; Use short-lived keys to limit the blast radius of a compromised credential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6. Disable lifecycle scripts.&lt;/strong&gt; By default, install dependencies with &lt;code&gt;--ignore-scripts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7. Have an incident playbook.&lt;/strong&gt; Know how to respond when you find a malicious package or image in your supply chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want more context, some Swiss German, or perhaps a discount code, watch the full talk.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/1_39oapnMfY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  🧨 TanStack, Nx Console, and the Cache That Bit Back
&lt;/h2&gt;

&lt;p&gt;The largest supply chain story of May was the chain from the &lt;strong&gt;TanStack npm compromise&lt;/strong&gt; to the &lt;strong&gt;Nx Console compromise&lt;/strong&gt;. Quick context if, like me, you don't spend every day inside the frontend tooling universe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TanStack&lt;/strong&gt; is the open-source project family behind popular JavaScript and TypeScript libraries like TanStack Query, Router, Table, and Start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nx Console&lt;/strong&gt; is an IDE extension for Nx, a build system and monorepo tool used by many JavaScript and TypeScript teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The short version: attackers abused CI/CD trust boundaries, poisoned a package-manager cache, waited for a privileged release workflow, and ended up publishing malicious packages and extension releases. The uncomfortable part is that some of the malicious packages still looked like they came from a legitimate publishing path, because the attacker got hold of valid short-lived credentials during the build.&lt;/p&gt;

&lt;p&gt;To learn more, read the postmortems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/blog/npm-supply-chain-compromise-postmortem" rel="noopener noreferrer"&gt;TanStack npm supply-chain compromise postmortem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/blog/nx-console-v18-95-0-postmortem" rel="noopener noreferrer"&gt;Nx Console v18.95.0 supply-chain compromise postmortem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.microsoft.com/en-us/security/blog/2026/05/29/33-malicious-npm-packages-abuse-dependency-confusion-profile-developer-environments/" rel="noopener noreferrer"&gt;Microsoft's write-up on malicious npm packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Supply Chain Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Treat CI caches as executable trust boundaries. A poisoned cache can be as dangerous as a poisoned dependency.&lt;/li&gt;
&lt;li&gt;Treat developer workstations and IDEs as part of the supply chain. They are not outside the blast radius anymore.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🪱 Mini Shai-Hulud: Still in the Walls
&lt;/h2&gt;

&lt;p&gt;In Issue 2, I wrote about &lt;strong&gt;Mini Shai-Hulud&lt;/strong&gt;, the NPM supply chain worm that arrived on my birthday. The worm even ended up in my Zurich talk's slides and raised some copyright concerns!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;. &lt;em&gt;Shai Hulud&lt;/em&gt; is the giant sandworm from the Dune universe. The phrase "shai hulud" can be read through Arabic as "شيء خلود" (shay' khulud), meaning "eternal thing". In my slides, a Persian poet is riding the worm, because Hafez was known as &lt;em&gt;Lissan al-Gaib&lt;/em&gt; ("the tongue of the unseen") long before Paul Atreides took the name in Dune.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhicnvpmje40kf0ry3ujj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhicnvpmje40kf0ry3ujj.png" alt="Lissan al-Gaib riding Shai Hulud" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The real lesson was persistence in the developer inner loop.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Fmini-shai-hulud.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" rel="noopener noreferrer" class="c-link"&gt;
            Mini Shai-Hulud: The Next Evolution of NPM Supply Chain Worms - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            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.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Mini Shai-Hulud abused the &lt;strong&gt;Bun runtime&lt;/strong&gt; to step around Node-focused security tooling. More importantly, it planted hooks in places developers trust:&lt;/p&gt;

&lt;h3&gt;
  
  
  Places to Inspect
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.vscode/tasks.json&lt;/code&gt; with &lt;code&gt;"runOn": "folderOpen"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/settings.json&lt;/code&gt; with &lt;code&gt;SessionStart&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;package lifecycle scripts&lt;/li&gt;
&lt;li&gt;workflow files and local helper scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means removing &lt;code&gt;node_modules&lt;/code&gt; is not enough. If the repository itself has been modified, the infection can come back when someone opens the folder or starts an AI coding session.&lt;/p&gt;

&lt;p&gt;So the practical reminder for June:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"runOn|folderOpen|SessionStart|bun|curl|wget"&lt;/span&gt; .vscode .claude package.json .github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And for untrusted repositories or AI-agent work, keep using isolation. Docker Sandboxes are a very natural fit here because the agent can inspect, build, and run code without turning your host machine into the place where every experiment gets to execute freely.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sbx run claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F42xewae3bnhvf2xw84py.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F42xewae3bnhvf2xw84py.png" alt="JAVAPRO Special Edition PDF" width="800" height="1131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They say to kill the Shai-Hulud, put it in a box of sand and pour water on it. I still like that line.&lt;/p&gt;

&lt;p&gt;Funny enough, I had already written about a small Shai Hulud before Mini Shai-Hulud was a thing. My JAVAPRO article &lt;strong&gt;"The Whispering JAR: Java Security Lessons Hidden in a Fantasy Tale"&lt;/strong&gt; features a tiny Shai Hulud and covers mitigation practices that map surprisingly well to defending against Mini Shai-Hulud. I should probably start fortune-telling.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://javapro.io/2026/04/23/the-whispering-jar-java-security-lessons-hidden-in-a-fantasy-tale/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2026%2F02%2FChatGPT-Image-Feb-11-2026-12_02_24-AM.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://javapro.io/2026/04/23/the-whispering-jar-java-security-lessons-hidden-in-a-fantasy-tale/" rel="noopener noreferrer" class="c-link"&gt;
            The Whispering JAR: Java Security Lessons Hidden in a Fantasy Tale - JAVAPRO International
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2024%2F07%2Fjavapro-favicon-80x80.jpg" width="80" height="80"&gt;
          javapro.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The article is also featured in JAVAPRO's special edition. You can download the PDF edition from JAVAPRO here:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://javapro.io/2026/05/28/always-up-to-date-with-every-new-free-pdf-edition-5/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2026%2F05%2FSubscribe-Newsletter-JAVAPRO-Magazine-PDF-26-5-Header.png" height="450" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://javapro.io/2026/05/28/always-up-to-date-with-every-new-free-pdf-edition-5/" rel="noopener noreferrer" class="c-link"&gt;
            Always Up to Date - with Every New Free PDF Edition! - JAVAPRO International
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2024%2F07%2Fjavapro-favicon-80x80.jpg" width="80" height="80"&gt;
          javapro.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  🧱 Copy Fail and the Boring Beauty of Defense in Depth
&lt;/h2&gt;

&lt;p&gt;May was not only about JavaScript packages and IDEs. The container runtime layer had its own moment with &lt;strong&gt;CVE-2026-31431&lt;/strong&gt;, also called &lt;strong&gt;Copy Fail&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is the Python-developer version.&lt;/p&gt;

&lt;p&gt;Linux has kernel features that user programs can call into, a little like importing a standard-library module. One of those features is &lt;code&gt;AF_ALG&lt;/code&gt;, an interface that lets programs ask the kernel to do cryptographic operations. Think: "please encrypt this buffer for me."&lt;/p&gt;

&lt;p&gt;Copy Fail was a bug in how the kernel handled one of those crypto operations when the input and output memory overlapped. If you have ever written Python like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;important data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memoryview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Imagine a buggy low-level function reading and writing overlapping slices.
&lt;/span&gt;&lt;span class="nf"&gt;crypto_operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then you already understand the shape of the problem: the code thinks it is copying or transforming bytes safely, but the read side and write side point into memory in a way the function did not handle correctly.&lt;/p&gt;

&lt;p&gt;In the kernel, that kind of mistake is much more serious than a corrupted Python &lt;code&gt;bytearray&lt;/code&gt;. The kernel manages shared caches and host resources. Under the wrong conditions, a low-privileged local attacker could use the bug to write where they should not be able to write. In container terms, that raises the scary question: can a process inside a container influence the host?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqc0v0kohfpk2m5nfz67s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqc0v0kohfpk2m5nfz67s.png" alt="Docker and Kubernetes Security book cover" width="800" height="992"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker published mitigations in Docker Engine, first tightening the default seccomp profile and then adding stronger AppArmor and SELinux coverage for the &lt;code&gt;alg&lt;/code&gt; socket family.&lt;/p&gt;

&lt;p&gt;AppArmor and SELinux are covered in my book &lt;strong&gt;Docker and Kubernetes Security&lt;/strong&gt;. They are Linux Security Modules that let you write policies to restrict what a process can do.&lt;/p&gt;

&lt;p&gt;The interesting part is not only the CVE. It is the mitigation story.&lt;/p&gt;

&lt;p&gt;Container security works because layers overlap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;namespaces and cgroups reduce what a process can see and consume&lt;/li&gt;
&lt;li&gt;seccomp filters dangerous syscall paths&lt;/li&gt;
&lt;li&gt;AppArmor or SELinux adds policy at the Linux Security Module layer&lt;/li&gt;
&lt;li&gt;minimal and hardened images reduce useful tools inside the container&lt;/li&gt;
&lt;li&gt;runtime monitoring catches behavior that static scanning cannot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When one layer has a bad day, the others still matter. Your castle needs outer walls, inner walls, guards, and a moat. Check out the first chapter of &lt;strong&gt;Black Forest Shadow&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-shadow/chapter-1/defense-in-depth" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fog-image.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-shadow/chapter-1/defense-in-depth" rel="noopener noreferrer" class="c-link"&gt;
            Defense in Depth - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            In cybersecurity, defense in depth is a strategy that employs multiple layers of security controls throughout an IT system. This approach ensures that if one...
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;By the way, &lt;strong&gt;Black Forest Shadow&lt;/strong&gt; is available to &lt;a href="https://dockersecurity.io/black-forest-shadow" rel="noopener noreferrer"&gt;read online&lt;/a&gt; for free now. You can still get the PDF in the &lt;a href="https://dockersecurity.io/shop" rel="noopener noreferrer"&gt;shop&lt;/a&gt; or order the physical book on Amazon or from your local bookstore.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Operational AI with Docker
&lt;/h2&gt;

&lt;p&gt;May also brought a happier topic: &lt;strong&gt;Operational AI with Docker&lt;/strong&gt; is out. I wrote a short review about my experience as a technical reviewer and why the book is worth reading if you care about Docker, MCP, agents, and local AI workflows.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/book-review-operational-ai-with-docker" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Foperational-ai-with-docker-selfie.png" height="986" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/book-review-operational-ai-with-docker" rel="noopener noreferrer" class="c-link"&gt;
            Book Review: Operational AI with Docker - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            An exclusive behind-the-scenes look at the book 'Operational AI with Docker' by Ajeet Singh Raina and Harsh Manvar, including insights from my role as a technical reviewer.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The security angle is simple: AI workloads bring more moving parts into the supply chain: model files, MCP servers, agent plugins, local tools, and permissions. The old question was "what is in my container?" The new question is closer to "what can this agent reach, execute, remember, and publish?"&lt;/p&gt;




&lt;h2&gt;
  
  
  📅 Next: EnterJS, Then WeAreDevelopers Berlin
&lt;/h2&gt;

&lt;p&gt;June takes me to &lt;strong&gt;EnterJS&lt;/strong&gt; in Mannheim with &lt;strong&gt;Defense Against the Dark Arts: NPM Attack&lt;/strong&gt;, which now feels less like a clever title and more like a monthly incident response exercise.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/talk/defense-against-the-dark-arts-npm-attack-enterjs-2026" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Fdefense-against-dark-arts.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/talk/defense-against-the-dark-arts-npm-attack-enterjs-2026" rel="noopener noreferrer" class="c-link"&gt;
            Defense Against the Dark Arts: NPM Attack — Talk by Mohammad-Ali A'râbi - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A deep dive into the September 2025 NPM supply chain attack—one of the largest in history—and how to defend your enterprise JavaScript applications.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Then in July, I will be back at &lt;strong&gt;WeAreDevelopers World Congress&lt;/strong&gt; in Berlin with two talks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dockersecurity.io/talk/dockerize-java-securely-wearedevelopers-2026" rel="noopener noreferrer"&gt;Dockerize Java Securely: SBOMs + Attestations + Bake&lt;/a&gt; on &lt;strong&gt;July 9&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dockersecurity.io/talk/beyond-sboms-wearedevelopers-2026" rel="noopener noreferrer"&gt;Beyond SBOMs: The Future of Container Supply Chain Security&lt;/a&gt; on &lt;strong&gt;July 10&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last year at WeAreDevelopers, more than 100 people queued for 40 seats at my Docker workshop. This year, the Commandos return with a much darker threat model and a much better battle plan.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Look out for worms, check your caches, and keep building those walls. Also, have fun this summer!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>sbom</category>
      <category>ai</category>
      <category>security</category>
    </item>
    <item>
      <title>Beyond SLSA: How to Stop Zero-Click CI/CD Worms with a 9-Step Plan</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Thu, 18 Jun 2026 10:19:19 +0000</pubDate>
      <link>https://dev.to/docker/beyond-slsa-how-to-stop-zero-click-cicd-worms-with-a-9-step-plan-1l36</link>
      <guid>https://dev.to/docker/beyond-slsa-how-to-stop-zero-click-cicd-worms-with-a-9-step-plan-1l36</guid>
      <description>&lt;p&gt;The security perimeter of modern software development has officially collapsed. Historically, protecting your supply chain meant scanning static containers and blocking typosquatted packages. But between late 2025 and mid-2026, a terrifying paradigm shift occurred: adversaries abandoned passive repository poisoning to deploy autonomous, self-replicating worms directly into developer IDEs and CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;When developers are no longer just building software but are themselves the perimeter, tools like SLSA Level 3 and container vulnerability scanning are necessary prerequisites—but they remain blind to pre-build, pre-compilation threats. If a worm steals your credentials or compromises your pipeline cache &lt;em&gt;before&lt;/em&gt; a container image is ever built, your final Software Bill of Materials (SBOM) will look perfectly fine while carrying authentic, cryptographically verified malicious payloads.&lt;/p&gt;

&lt;p&gt;To bridge this structural gap, we introduce the &lt;strong&gt;IX Hexbreaker Aegis Framework&lt;/strong&gt;—a 9-step active defense architecture designed to sanitize the local developer environment, lock down agentic AI, and stop autonomous worms dead in their tracks. For a formal mapping of these structural vulnerabilities across ecosystems, refer to the research article &lt;em&gt;SoK: Weaponizing the Developer Context: A Taxonomy of Autonomous CI/CD Worms and Remediation Architectures&lt;/em&gt; (available on &lt;a href="https://doi.org/10.5281/zenodo.20694817" rel="noopener noreferrer"&gt;doi.org/10.5281/zenodo.20694817&lt;/a&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  Chronology of Chaos: The 6 Modern Worm Campaigns
&lt;/h2&gt;

&lt;p&gt;To understand why traditional perimeter security failed, we must look at the rapid evolutionary velocity of the six defining autonomous campaigns in the Shai-Hulud and Miasma lineages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fivj23k10pwfzcgev5rhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fivj23k10pwfzcgev5rhf.png" alt="Six Worms" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Shai-Hulud Wave 1 (September 2025)
&lt;/h3&gt;

&lt;p&gt;The sandworm made it debut as the first self-propagating npm supply chain worm on record. Attackers gained initial maintainer access via phishing and credential stuffing. Once inside, the worm stole GitHub Personal Access Tokens (PATs) and cloud provider API keys from local developer environments, uploaded them to a public "dead-drop" repository, and autonomously used the stolen tokens to publish infected updates to every package that developer maintained.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Shai-Hulud 2.0 (November 2025)
&lt;/h3&gt;

&lt;p&gt;The second wave scaled massively, compromising around 350 user accounts and spawning over 25,000 malicious repositories. Mechanically, this campaign shifted its execution trigger from &lt;code&gt;postinstall&lt;/code&gt; to &lt;code&gt;preinstall&lt;/code&gt; to maximize stealth. It also pioneered runtime evasion by dynamically downloading a standalone Bun binary to run its core obfuscated payload, completely dodging traditional security tooling looking only for Node.js child processes.&lt;/p&gt;

&lt;p&gt;This was still the time that we could disable lifecycles scripts in package managers and install npm packages with &lt;code&gt;--ignore-scripts&lt;/code&gt; to block the attack. As they say, it was the most wonderful time of the year—spoiler alert: it would not last.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Mini Shai-Hulud (April–May 2026)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5st4k87tm5yyae68rnhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5st4k87tm5yyae68rnhx.png" alt="Gord and Rothütle putting a Mini Shai Hulud in a sandbox" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Orchestrated by the threat group TeamPCP, this variant targeted the enterprise-grade SAP Cloud Application Programming (CAP) ecosystem. It introduced environmental gating (self-terminating if the system language was Russian) and achieved long-term IDE persistence by planting unauthorized startup hooks inside localized AI settings.&lt;/p&gt;

&lt;p&gt;This was a turning point in the attack surface: the worm was no longer just targeting package manager lifecycles, but was instead weaponizing the very context in which code is written. That included the AI agents that developers rely on to write code in the first place. This was also a memorable time for me personally, as the worm was first observed on April 29, 2026—my 35th birthday. I guess the universe wanted to give me a "gift" that year (in its German sense)!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The TanStack Cache Poisoning Incident (May 11, 2026)
&lt;/h3&gt;

&lt;p&gt;Assignee of CVE-2026-45321, this campaign proved that sophisticated worms no longer counterfeit trust signals; they commandeer pipelines to earn them. By chaining a &lt;code&gt;pull_request_target&lt;/code&gt; misconfiguration with a GitHub Actions cache contamination vector, the worm poisoned a shared dependency store. When a highly privileged release workflow ran, it restored the poisoned cache, allowing the worm to scrape OIDC tokens straight out of the runner's worker process memory to sign and publish 84 malicious packages carrying authentic SLSA Level 3 provenance.&lt;/p&gt;

&lt;p&gt;This was another major moment, as with this attack, SLSA Level 3 was officially rendered insufficient as a standalone defense. The attack also proved that even if your final SBOM looks clean, it can still be the product of a compromised build environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Miasma Wave 1: Red Hat npm Packages (June 1, 2026)
&lt;/h3&gt;

&lt;p&gt;A direct descendant of Shai-Hulud, this worm compromised 32 official packages in the &lt;code&gt;@redhat-cloud-services&lt;/code&gt; namespace. Attackers bypassed standard code review by committing malicious code via orphan commits. It featured per-infection payload encryption to blind hash-based detection and included a destructive dead-man's switch: if defenders revoked or touched the honeypot token, a background script immediately wiped the developer's home directory.&lt;/p&gt;

&lt;p&gt;This means, the worm would take your entire development environment hostage, threatening to delete the "French language package" from your machine: &lt;code&gt;sudo rm -fr ~&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Miasma Wave 2: The Phantom Gyp Exploit (June 3, 2026)
&lt;/h3&gt;

&lt;p&gt;Two days later, Wave 2 compromised 57 packages in under two hours. This campaign introduced the "Phantom Gyp" technique, which completely neutralized the industry's standard defense of using the &lt;code&gt;--ignore-scripts&lt;/code&gt; flag. Instead of relying on &lt;code&gt;package.json&lt;/code&gt; scripts, it weaponized native &lt;code&gt;binding.gyp&lt;/code&gt; command substitution, forcing the package manager to execute an arbitrary shell payload during the initial configuration phase before any C++ compiler was even called.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F675u1kmp47utiomlqwtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F675u1kmp47utiomlqwtf.png" alt="Phantom Gyp: The Opera Worm" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The 4 Overlooked Execution Surfaces
&lt;/h2&gt;

&lt;p&gt;As mapped in the SoK paper, these six campaigns achieved rapid, zero-click propagation by targeting four distinct surfaces that fall entirely outside the scope of static scanners:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Click IDE Execution:&lt;/strong&gt; Hidden workspace configurations (like &lt;code&gt;.vscode/tasks.json&lt;/code&gt;) trigger malicious payloads the absolute millisecond an infected repository folder is opened in code editors like VS Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Context Window Poisoning:&lt;/strong&gt; In advanced waves like the TrapDoor campaign, attackers plant instructions containing invisible zero-width Unicode characters inside files like &lt;code&gt;.cursorrules&lt;/code&gt; or &lt;code&gt;.claude/settings.json&lt;/code&gt;. These characters are completely invisible to human reviewers but command local AI agents to execute unauthorized scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline Memory Scraping:&lt;/strong&gt; Highly privileged Linux CI runners are targeted post-installation. Worms scan the &lt;code&gt;/proc&lt;/code&gt; directory to scrape ambient OpenID Connect (OIDC) tokens and secret tokens straight out of active process memory, completely bypassing standard build-log secret masking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Build Hijacking (Phantom Gyp):&lt;/strong&gt; Attackers bypass the standard &lt;code&gt;--ignore-scripts&lt;/code&gt; defense by appending a tiny, static &lt;code&gt;binding.gyp&lt;/code&gt; file to the published package tarball to hijack native node-gyp execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8fo8qnqramm5518lgsdh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8fo8qnqramm5518lgsdh.png" alt="When Your Tools Turn Against You" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The IX Hexbreaker Aegis Framework: A 9-Step Active Defense Plan
&lt;/h2&gt;

&lt;p&gt;If you have an army of Shai Huluds and Miasmas marching toward your development environment, you need a cool name for your defense strategy: &lt;strong&gt;The IX Hexbreaker Aegis&lt;/strong&gt;. The 9 is Roman, they're breaking the hex, and an aegis is a shield of protection. Nice, right?&lt;/p&gt;

&lt;p&gt;The IX Hexbreaker Aegis architecture layers an active, pre-build defense boundary on top of traditional container hardening practices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                          [ UNTRUSTED REPOSITORY ]
                                     │
           ┌─────────────────────────┴─────────────────────────┐
           ▼                                                   ▼
 ┌───────────────────┐                               ┌───────────────────┐
 │ Local Development │                               │   CI/CD Pipeline  │
 └─────────┬─────────┘                               └─────────┬─────────┘
           │                                                   │
           ├─► 1. AI Agent Sandboxing (Docker Sandboxes)       ├─► 4. OIDC Scope Minimization
           ├─► 2. Pre-Execution Workspace Parsing              ├─► 5. Immutable CI/CD Caching
           ├─► 3. Ephemeral, Air-Gapped Dev Environments       ├─► 7. Heuristic Build-Time eBPF
           ├─► 6. Hardware-Backed Commit Binding               ├─► 8. Egress Traffic Filtering
           └─► 9. Zero-Trust AI Prompts                        └─────────────────────────────────┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. AI Agent Sandboxing via Docker Sandboxes
&lt;/h3&gt;

&lt;p&gt;Running localized AI coding assistants directly on a host machine exposes local credential stores to prompt injection. This step mandates wrapping AI agents inside isolated microVMs via &lt;strong&gt;Docker Sandboxes&lt;/strong&gt;. Each session runs under its own kernel, filesystem, and network stack. Because API keys are never injected into the microVM's environment—and are instead handled by a host-side proxy at the network layer—a compromised AI agent cannot find any raw host credentials to steal.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pre-Execution Workspace Parsing
&lt;/h3&gt;

&lt;p&gt;Manual code reviews fail against steganographic payloads. Organizations must implement automated semantic scanning of all hidden AI configuration files (&lt;code&gt;.cursorrules&lt;/code&gt;, &lt;code&gt;.claude/settings.json&lt;/code&gt;, etc.) prior to context-loading. Utilizing LLM-based semantic judging helps identify hidden zero-width Unicode instructions and malicious execution trajectories before your primary development AI processes them.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ephemeral, Air-Gapped Development Environments
&lt;/h3&gt;

&lt;p&gt;Replace static, long-lived local development environments with remote, containerized alternatives like Dev Containers or GitHub Codespaces. These environments must enforce strict egress network filtering. By air-gapping the container and explicitly allowlisting only verified registries, a background worm's killchain is severed because it can neither download secondary runtimes nor reach out to an external command-and-control server.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Strict OIDC Scope Minimization
&lt;/h3&gt;

&lt;p&gt;The TanStack cache poisoning incident proved that overly broad OIDC permissions allow background malware to hijack trusted publisher workflows. Ensure JSON Web Tokens (JWTs) are generated with the absolute minimum Time-to-Live (TTL) required for a specific job step, and bind them to restricted, precise audiences. Never expose token-writing privileges to general, multi-purpose pipeline jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Immutable CI/CD Caching
&lt;/h3&gt;

&lt;p&gt;Internal caching mechanisms often bypass repository workflow boundaries. Under this rule, caches generated by unvetted fork-context pull requests must be completely isolated from high-privilege release workflows. Cryptographic hash verification must be enforced on package manager caches to guarantee that a poisoned pull request cannot inject malicious binaries into a shared repository store.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Hardware-Backed Commit Binding
&lt;/h3&gt;

&lt;p&gt;Worms rapidly spread sideways through development environments by stealing local SSH keys or Personal Access Tokens (PATs) to commit code autonomously. This step mandates that all commits and Git tags be cryptographically signed using FIDO2 hardware security keys (e.g., a YubiKey using an &lt;code&gt;sk-ed25519&lt;/code&gt; key format). Because the key requires a physical capacitive touch to sign, an automated background process is structurally blocked from making commits.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Heuristic Build-Time Anomaly Detection
&lt;/h3&gt;

&lt;p&gt;Static image analysis cannot catch multi-stage, uniquely encrypted droppers executing in real time. Implement kernel-level observability using &lt;strong&gt;eBPF&lt;/strong&gt; to trace process execution trees inside your build systems. The heuristic engine should immediately flag and quarantine anomalous subprocesses, such as an unprompted &lt;code&gt;node-gyp rebuild&lt;/code&gt; on a package containing no legitimate native code.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Egress Traffic Filtering in CI Pipelines
&lt;/h3&gt;

&lt;p&gt;CI/CD runners should never operate with unrestricted outbound network access. Enforce a default-deny network egress policy at the runner level during the test and build phases. Limiting outbound communication exclusively to vetted registries blocks a scraping worm from exfiltrating plaintext process memory dumps to external dead-drops.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Zero-Trust AI Prompts
&lt;/h3&gt;

&lt;p&gt;Apply Role-Based Access Control (RBAC) directly to the execution profiles of AI coding agents. Rather than giving an LLM tool unfettered terminal access, drop permissions that allow an agent to run arbitrary shell scripts, read &lt;code&gt;.env&lt;/code&gt; files, or modify system configurations without direct, human-in-the-loop Multi-Factor Authentication (MFA) approval.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwqy66q0jg7624rbnso1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwqy66q0jg7624rbnso1.png" alt="The Hexbreakers fighting giant worms" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Actionable Execution Blueprint
&lt;/h2&gt;

&lt;p&gt;If you are defending an enterprise engineering organization, you can implement the IX Hexbreaker Aegis framework in three logical phases to minimize friction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Phase 1: Immediate Lockdown (Days 1–5)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OIDC and Caching:&lt;/strong&gt; Add &lt;code&gt;permissions: {id-token: none}&lt;/code&gt; globally to every GitHub Actions workflow, granting write access only to specific publish steps. Separate cache keys immediately so fork PRs cannot contaminate your release scopes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependency Cooldown:&lt;/strong&gt; Configure Dependabot or Renovate to require a minimum package release age of 5 days before allowing an auto-merge, forcing malicious bursts to be caught by public threat intel beforehand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI Controls:&lt;/strong&gt; Set project-level AI settings to deny shell execution without explicit confirmation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Phase 2: Pipeline Hardening (Weeks 2–4)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Filters:&lt;/strong&gt; Deploy default-deny egress firewalls (such as StepSecurity Harden-Runner) on your CI workflows to break potential C2 phone-home logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pinning:&lt;/strong&gt; Audit configuration repositories to substitute mutable action version tags with immutable, cryptographically secure commit SHAs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Phase 3: Total Isolation (Month 2+)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Toolchain Sandboxing:&lt;/strong&gt; Migrate development workspaces to containerized Dev Containers. Mandate the &lt;code&gt;sbx&lt;/code&gt; CLI tool for all local engineer interaction with AI coding assistants to enforce hardware-isolated microVM containment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardware Enforcement:&lt;/strong&gt; Issue FIDO2 security tokens to all core package maintainers, configuring Git to refuse unauthenticated, unsigned commits locally and upstream.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Treating supply chain integrity as a static checkbox will guarantee that you fall victim to the next evolution of automated threats. Moving your active defenses entirely to the left—and protecting the very context in which code is written—is the only way to build software safely in an era of autonomous worms.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>docker</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 2: From JCON to Zurich 🏔️</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Mon, 08 Jun 2026 11:43:36 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-2-from-jcon-to-zurich-231f</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-2-from-jcon-to-zurich-231f</guid>
      <description>&lt;p&gt;Welcome to the second issue of &lt;strong&gt;Docker Security Dispatch&lt;/strong&gt;. April was a whirlwind of conferences, articles, and interviews. From the cathedrals of Cologne to the mountains of Zurich, here is everything that happened in the Docker security world last month.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stay informed about critical vulnerabilities like CVE-2026-34040 and the 'Mini Shai-Hulud' supply chain worm.&lt;/li&gt;
&lt;li&gt;Discover the benefits of Docker Sandboxes for isolating development environments against malware.&lt;/li&gt;
&lt;li&gt;Recap of the Java-focused Docker Commandos workshop delivered at JCON Europe 2026.&lt;/li&gt;
&lt;li&gt;Insights from industry experts on container security and operationalizing AI with Docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01iypwpqdd99h8djoc4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01iypwpqdd99h8djoc4u.png" alt="Docker Security Dispatch, issue 2" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ Critical: CVE-2026-34040 &amp;amp; The Mini Shai-Hulud "Gift"
&lt;/h2&gt;

&lt;p&gt;The biggest news in the Docker security scene this month was the disclosure of &lt;strong&gt;CVE-2026-34040&lt;/strong&gt;. This is a high-severity authorization bypass vulnerability that affected Docker Engine versions before 29.3.1. If an API request body exceeded 1MB, the AuthZ plugin would be bypassed. &lt;strong&gt;Please ensure you have updated to Docker Engine 29.4.2 or Docker Desktop 4.71.0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Speaking of security "gifts," as I turned 35 on April 29, the universe (or TeamPCP) decided to send a satirical birthday present: &lt;strong&gt;Mini Shai-Hulud&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This third wave of the Shai-Hulud lineage emerged on my birthday and is a highly autonomous NPM supply chain worm. It heavily targeted the SAP cloud ecosystem (infecting &lt;code&gt;@cap-js/sqlite&lt;/code&gt; and &lt;code&gt;@cap-js/postgres&lt;/code&gt;), harvesting tokens to backdoor other packages. The attack uses a malicious preinstall hook to download the &lt;strong&gt;Bun runtime&lt;/strong&gt;—bypassing Node-based security tooling—and execute an 11.7 MB obfuscated credential stealer. Most disturbingly, it installs persistence hooks directly in your IDE settings, specifically modifying &lt;code&gt;.vscode/tasks.json&lt;/code&gt; to trigger on &lt;code&gt;folderOpen&lt;/code&gt;.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Fmini-shai-hulud.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/mini-shai-hulud-attack" rel="noopener noreferrer" class="c-link"&gt;
            Mini Shai-Hulud: The Next Evolution of NPM Supply Chain Worms - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            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.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;In better news, &lt;strong&gt;Docker Sandboxes&lt;/strong&gt; (Beta) are helpful against Mini Shai-Hulud. They allow you to run your AI coding agents like Claude in an isolated microVM, preventing Mini Shai-Hulud-style attacks from compromising your development environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sbx run claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏛️ JCON Europe: The Commandos in Cologne
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;April 20&lt;/strong&gt;, I was at &lt;a href="https://jcon.one" rel="noopener noreferrer"&gt;JCON Europe 2026&lt;/a&gt; in Cologne, and delivered the &lt;strong&gt;"Java Supply Chain Security with Docker"&lt;/strong&gt; workshop—a Java-focused adaptation of the Docker Commandos series.&lt;/p&gt;

&lt;p&gt;The workshop &lt;strong&gt;is available as a Docker Labspace&lt;/strong&gt;, providing a guided, interactive environment.&lt;/p&gt;

&lt;p&gt;If you don't have the Labspace extension installed in Docker Desktop, you can still run the full mission locally using the OCI artifact:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; oci://docker.io/aerabi/docker-commandos-labspace up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Learn more:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/workshop/jcon-europe-2026" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fworkshops%2Fcommandos-in-cologne.png" height="597" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/workshop/jcon-europe-2026" rel="noopener noreferrer" class="c-link"&gt;
            Java Supply Chain Security with Docker — Docker Commandos Workshop - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Docker Commandos adapted for a Java audience at JCON Europe 2026. Supply chain security, SBOMs, and attestations — using Docker tooling with a Java project as the target.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  🎙️ Interview with Baruch Sadogursky
&lt;/h2&gt;

&lt;p&gt;While at JCON, I sat down with the legendary &lt;strong&gt;Baruch Sadogursky&lt;/strong&gt; (&lt;a class="mentioned-user" href="https://dev.to/jbaruch"&gt;@jbaruch&lt;/a&gt;) for an interview with &lt;strong&gt;Tessl&lt;/strong&gt; and &lt;strong&gt;JAVAPRO&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;We discussed, surprise surprise, &lt;strong&gt;container supply chain security&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/pFfJZRAZez8"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  📰 JAVAPRO: "The Whispering JAR"
&lt;/h2&gt;

&lt;p&gt;Speaking of JAVAPRO, my latest article for them also dropped during the conference: &lt;strong&gt;"The Whispering JAR: Java Security Lessons Hidden in a Fantasy Tale"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's a narrative-driven look at the latest supply chain attacks hidden in a fantasy setting—similar in spirit to &lt;em&gt;Black Forest Shadow&lt;/em&gt;, and happening right after the events of the book. It discusses the following attacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NPM supply chain attack of September 2025&lt;/li&gt;
&lt;li&gt;The Shai-Hulud 1 and 2 attacks of late 2025&lt;/li&gt;
&lt;li&gt;React2Shell, the React-based remote code execution attack of late 2025&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://javapro.io/2026/04/23/the-whispering-jar-java-security-lessons-hidden-in-a-fantasy-tale/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2026%2F02%2FChatGPT-Image-Feb-11-2026-12_02_24-AM.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://javapro.io/2026/04/23/the-whispering-jar-java-security-lessons-hidden-in-a-fantasy-tale/" rel="noopener noreferrer" class="c-link"&gt;
            The Whispering JAR: Java Security Lessons Hidden in a Fantasy Tale - JAVAPRO International
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2024%2F07%2Fjavapro-favicon-80x80.jpg" width="80" height="80"&gt;
          javapro.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  🐧 Foojay.io Debut
&lt;/h2&gt;

&lt;p&gt;I am also thrilled to have published my first article on &lt;strong&gt;Foojay.io&lt;/strong&gt; (the Friends of OpenJDK platform) this month: &lt;strong&gt;"Dockerizing a Java 26 Project with Docker Init"&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://foojay.io/today/dockerizing-a-java-26-project-with-docker-init/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffoojay.io%2Fwp-content%2Fuploads%2F2026%2F04%2Fasgard-init-1024x765.png" height="598" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://foojay.io/today/dockerizing-a-java-26-project-with-docker-init/" rel="noopener noreferrer" class="c-link"&gt;
            Dockerizing a Java 26 Project with Docker Init
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Java 26 came out in March 2026. This article walks you through Dockerizing a Java 26 Spring Boot project using Docker Init.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffoojay.io%2Fwp-content%2Fuploads%2F2020%2F04%2FFavicon-3-2-150x150.png" width="150" height="150"&gt;
          foojay.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  🎙️ JobRad Podcast: Writing a Tech Book
&lt;/h2&gt;

&lt;p&gt;JobRad's tech podcast, &lt;strong&gt;Increase Cycle Time&lt;/strong&gt;, is out, and I'm on it! 🎙️&lt;/p&gt;

&lt;p&gt;I sat down with &lt;strong&gt;Holger Grosse-Plankermann&lt;/strong&gt; and &lt;strong&gt;Urs Lange&lt;/strong&gt; to talk about the behind-the-scenes of writing a tech book like &lt;em&gt;Docker and Kubernetes Security&lt;/em&gt;. We discussed the research process, the challenges of keeping up with a fast-moving ecosystem, and what it takes to get from a rough draft to a published book.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://jobrad-increase-cycle-time.podigee.io/10-tech-book" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.podigee-cdn.net%2F0x%2Cs81W8A3dtZkBwwl7z2z7ED9yMs1WRr0ENuhPlJiPByrc%3D%2Fhttps%3A%2F%2Fmain.podigee-cdn.net%2Fuploads%2Fu76574%2Fc8fd26ec-6e3c-429b-a6ee-91afe479b6ec.png" height="800" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://jobrad-increase-cycle-time.podigee.io/10-tech-book" rel="noopener noreferrer" class="c-link"&gt;
            
      Folge 10: Writing a tech book - Increase Cycle Time - Der JobRad® Development Podcast
    
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Hello lovely people from the interwebs,

In this episode we have a chat with our dear colleague Mohammad-Ali A'râbi. Mo wrote a book about Docker Security. Even though the content of this book is great. (Hint! Read the book: https://www.dockersecurity.io/), in this episode Urs and Holger are more interested in what it is like to write a book?

Why do this after all? What are the hurdles? How do you keep your motivation high? And what one needs to do, if you are thinking: I want to write a book too!

All this and more in the current episode of Increase Cycle Time. 
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.podigee-cdn.net%2F96x%2CsofdUHGK75zP3NQGwWJh-s6N9mgSeKsHxNx7FSydtXFA%3D%2Fhttps%3A%2F%2Fmain.podigee-cdn.net%2Fuploads%2Fu76449%2F3535a918-543c-4d48-b6ef-302330a9073d.png" width="96" height="96"&gt;
          jobrad-increase-cycle-time.podigee.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc3hkcb7axnzn8606ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc3hkcb7axnzn8606ww.png" alt="Operational AI with Docker" width="800" height="986"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Book: Operational AI with Docker
&lt;/h2&gt;

&lt;p&gt;I'm excited to announce that I served as a &lt;strong&gt;technical reviewer&lt;/strong&gt; for the new book &lt;strong&gt;"Operational AI with Docker"&lt;/strong&gt;, published by Packt. As AI models become a standard part of our containerized workloads, this book is a fantastic guide for anyone looking to run LLMs in production using Docker.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏔️ Upcoming: DevOpsDays Zurich &amp;amp; Berlin
&lt;/h2&gt;

&lt;p&gt;Recently, I headed to &lt;strong&gt;DevOpsDays Zurich&lt;/strong&gt; (May the 6th) to give my talk: &lt;strong&gt;"Beyond SBOMs: The Future of Container Supply Chain Security"&lt;/strong&gt;. I'll write more about it in the coming issue.&lt;/p&gt;

&lt;p&gt;I'm also happy to share that this talk was also accepted for &lt;strong&gt;WeAreDevelopers World Congress&lt;/strong&gt; in Berlin this July. I can't wait to bring the Commandos to the big stage in Berlin! So, if you missed it in Zurich, we'll catch you in Berlin!&lt;/p&gt;

&lt;p&gt;Until next time, and let's hope there are no more "gifts" from the universe in May!&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>Docker Security Dispatch — Issue 1: Docker Turns 13 🎂</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Tue, 02 Jun 2026 07:32:00 +0000</pubDate>
      <link>https://dev.to/docker/docker-security-dispatch-issue-1-docker-turns-13-3njh</link>
      <guid>https://dev.to/docker/docker-security-dispatch-issue-1-docker-turns-13-3njh</guid>
      <description>&lt;p&gt;Welcome to the first issue of &lt;strong&gt;Docker Security Dispatch&lt;/strong&gt;. This newsletter covers Docker security, container supply chains, and the community around them. The first issue of the newsletter was published on April 1st, 2026, on the following platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/welcome-docker-security-dispatch-mohammad-ali-a-r%C3%A2bi-9q0qf" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dockersecurity.io/blog/docker-security-dispatch-issue-1" rel="noopener noreferrer"&gt;DockerSecurity.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm bringing the series to DEV.to as well, so I'm sharing the first issue with 2 months of delay.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Celebrate Docker's 13th anniversary with the launch of the dark fantasy security guide, 'Black Forest Shadow'.&lt;/li&gt;
&lt;li&gt;Get insights from the Docker Commandos v1.5 workshop focused on supply-chain security.&lt;/li&gt;
&lt;li&gt;Learn about the '10 Docker Commandos' framework for hunting security threats.&lt;/li&gt;
&lt;li&gt;Recap the most significant Docker book releases from the first quarter of 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3j2xm6bh96v73mt3ni5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3j2xm6bh96v73mt3ni5.png" alt="Docker Security Dispatch" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎂 Docker Turns 13
&lt;/h2&gt;

&lt;p&gt;Docker turned 13 on March 20, 2026. Thirteen years since Solomon Hykes demoed &lt;code&gt;docker run&lt;/code&gt; at PyCon.&lt;/p&gt;

&lt;p&gt;I published my second book on &lt;strong&gt;Friday, March 13th&lt;/strong&gt;—Docker's birthday, and a Friday the 13th. I couldn't resist.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-shadow" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Fbook-black-forest-shadow.jpg" height="1020" class="m-0" width="680"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/black-forest-shadow" rel="noopener noreferrer" class="c-link"&gt;
            Black Forest Shadow — A Dark Fantasy Guide to Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A dark fantasy novel set in the Black Forest of 1865 that teaches Docker and Kubernetes security through narrative — covering CVE hunting, SBOM generation, runtime hardening, and container security.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;&lt;em&gt;Black Forest Shadow: A Dark Fantasy Guide to Docker and Kubernetes Security&lt;/em&gt;&lt;/strong&gt; grew out of the Advent of Docker Security series I published in December 2025—24 daily posts set in the Black Forest of 1865, where shadow creatures called CVEs were spreading through villages. After the series ended, I wrote seven more chapters, compiled the whole thing, and turned it into a book.&lt;/p&gt;

&lt;p&gt;Each chapter maps to a real security technique: CVE triage, SBOM generation, OCI 1.1 attestations, vulnerability scanning, container hardening, runtime security with Falco, lateral movement prevention. Gord, Rothütle, Jack, and Evie are also the Docker Commandos from the workshop series. The book is their origin story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to get it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://buy.dockersecurity.io" rel="noopener noreferrer"&gt;DockerSecurity.io&lt;/a&gt; — PDF, ePub, and print&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dockersecurity.io/amz/bfs" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.thalia.de/shop/home/artikeldetails/A1078659350" rel="noopener noreferrer"&gt;Thalia&lt;/a&gt; and &lt;a href="https://www.hugendubel.de/de/taschenbuch/mohammad_ali_a_rabi-black_forest_shadow-52778151-produkt-details.html" rel="noopener noreferrer"&gt;Hugendubel&lt;/a&gt; for DACH print&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎖️ Docker Commandos at Rabobank
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;March 27&lt;/strong&gt;, I delivered &lt;strong&gt;Docker Commandos v1.5&lt;/strong&gt; at &lt;a href="https://www.rabobank.com" rel="noopener noreferrer"&gt;Rabobank&lt;/a&gt; in Utrecht, as part of their Docker Champions program. About 20 people attended.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2x8ty2jducb4oj5s83n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2x8ty2jducb4oj5s83n.jpg" alt="Docker Commandos workshop at Rabobank" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker Commandos is a workshop where 10 fictional commandos, each paired with a Docker security command, guide participants through a mission to defend Asgard from CVE monsters. v1.5 covers the full supply-chain pipeline: from &lt;code&gt;docker init&lt;/code&gt; to cryptographic image signing with Cosign and zero-day runtime defense. Two new commandos join in this version.&lt;/p&gt;

&lt;p&gt;The full workshop materials:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/workshop/rabobank-2026" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2F10-commandos-asgard.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/workshop/rabobank-2026" rel="noopener noreferrer" class="c-link"&gt;
            Docker Commandos v1.5 — Docker Commandos Workshop - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Docker Commandos v1.5 at Rabobank, part of their Docker Champions program. Full supply-chain security pipeline from Docker Init to cryptographic signing and zero-day runtime defense.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  📰 JavaPro: "10 Docker Commandos"
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;March 19&lt;/strong&gt;, &lt;a href="https://javapro.io" rel="noopener noreferrer"&gt;JavaPro&lt;/a&gt; published my article &lt;strong&gt;"10 Docker Commandos: Docker Commands to Hunt the Predator"&lt;/strong&gt;—three days before I ran the workshop at Rabobank, which was good timing.&lt;/p&gt;

&lt;p&gt;The article uses the React2Shell supply chain attack (CVE-2025-55182) as the threat model. Attackers deployed crypto miners within hours of disclosure. The 10 commandos walk through the response: Lockdown → SBOM → Scout → SBOM Attestations → Docker Init → Hardened Images → Exempted CVEs → VEX Attestation → Docker Bake → Zero-Day Defense.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://javapro.io/2026/03/19/10-docker-commandos-docker-commands-to-hunt-the-predator/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2026%2F02%2Fcommandos-v5-comic-e1770835706278-1024x350.png" height="273" class="m-0" width="799"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://javapro.io/2026/03/19/10-docker-commandos-docker-commands-to-hunt-the-predator/" rel="noopener noreferrer" class="c-link"&gt;
            10 Docker Commandos: Docker Commands to Hunt the Predator - JAVAPRO International
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjavapro.io%2Fwp-content%2Fuploads%2F2024%2F07%2Fjavapro-favicon-80x80.jpg" width="80" height="80"&gt;
          javapro.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  📚 Q1 2026 Docker Books
&lt;/h2&gt;

&lt;p&gt;Five Docker books came out in the first quarter of 2026. Three of them by Docker Captains, which I think is a first.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/blog/docker-read-list-2026-q1" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fblog-img%2Fdocker-read-list-2026-q1.png" height="447" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/blog/docker-read-list-2026-q1" rel="noopener noreferrer" class="c-link"&gt;
            The Complete Docker Read List: Q1 2026 Edition - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A curated reading list of the best books on Docker and Kubernetes for the first quarter of 2026, featuring releases from Docker Captains and industry experts.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  📅 Next: JCON Europe, Cologne, April 20
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;April 20&lt;/strong&gt;, I had the honor of doing a workshop at &lt;a href="https://jcon.one" rel="noopener noreferrer"&gt;JCON Europe 2026&lt;/a&gt; in Cologne with &lt;strong&gt;"Java Supply Chain Security with Docker"&lt;/strong&gt;—Docker Commandos adapted for a Java audience. Same pipeline, Java project as the target.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://containersecurity.dev/workshop/jcon-europe-2026" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dockersecurity.io%2Fworkshops%2Fcommandos-in-cologne.png" height="597" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://containersecurity.dev/workshop/jcon-europe-2026" rel="noopener noreferrer" class="c-link"&gt;
            Java Supply Chain Security with Docker — Docker Commandos Workshop - Docker and Kubernetes Security
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Docker Commandos adapted for a Java audience at JCON Europe 2026. Supply chain security, SBOMs, and attestations — using Docker tooling with a Java project as the target.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcontainersecurity.dev%2Ffavicon.ico" width="48" height="48"&gt;
          containersecurity.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;&lt;em&gt;Questions or feedback: &lt;a href="https://dockersecurity.io/contact" rel="noopener noreferrer"&gt;dockersecurity.io/contact&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>security</category>
    </item>
    <item>
      <title>Seven Docker Tips Every Engineer Should Know (from Docker Captains)</title>
      <dc:creator>Mohammad-Ali A'RÂBI</dc:creator>
      <pubDate>Mon, 25 May 2026 07:25:00 +0000</pubDate>
      <link>https://dev.to/docker/seven-docker-tips-every-engineer-should-know-from-docker-captains-3o1h</link>
      <guid>https://dev.to/docker/seven-docker-tips-every-engineer-should-know-from-docker-captains-3o1h</guid>
      <description>&lt;p&gt;Between June and August 2025, Docker shared a short series of practical tips from Docker Captains on Twitter/X. The format was brief, but the advice is worth unpacking. This post is revisiting those seven tips with a little more context and newer examples.&lt;/p&gt;

&lt;p&gt;Here are the seven tips, in the chronological order they were shared!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start New Projects with Docker Init
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/captains/mohammad-ali-arabi/" rel="noopener noreferrer"&gt;Mohammad-Ali A'rabi&lt;/a&gt; is a Docker Captain from Freiburg, Germany, a backend software engineer, Docker community leader, and the author of &lt;a href="https://www.dockersecurity.io/docker-and-kubernetes-security" rel="noopener noreferrer"&gt;&lt;em&gt;Docker and Kubernetes Security&lt;/em&gt;&lt;/a&gt;. His work often sits at the intersection of practical engineering, education, community, and secure-by-default container workflows.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1934618217990754462-547" src="https://platform.twitter.com/embed/Tweet.html?id=1934618217990754462"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1934618217990754462-547');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1934618217990754462&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The tweet points to &lt;code&gt;docker init&lt;/code&gt; as the fastest way to get a clean Docker setup for a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command analyzes your project and generates a set of files that follow Docker's best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.dockerignore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compose.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.Docker.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the following article for a detailed walkthrough of &lt;code&gt;docker init&lt;/code&gt; with a Java project: &lt;a href="https://www.dockersecurity.io/blog/dockerize-java-26-with-docker-init" rel="noopener noreferrer"&gt;Dockerize Java 26 with Docker Init&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Clean Up Docker Disk Usage Carefully
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/contributors/rafael-pazini/" rel="noopener noreferrer"&gt;Rafael Pazini&lt;/a&gt; is a Docker Captain from Sao Paulo, Brazil, and a Senior Software Engineer at Pluto TV. He has more than 10 years of experience building scalable applications, with expertise in distributed systems, microservices, Docker, and Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1937229925515252098-27" src="https://platform.twitter.com/embed/Tweet.html?id=1937229925515252098"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1937229925515252098-27');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1937229925515252098&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;docker system prune&lt;/code&gt; is no stranger to Docker users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--volumes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The terminal will say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - unused build cache

Are you sure you want to continue? [y/N]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BTW, did you know &lt;code&gt;[y/N]&lt;/code&gt; means "default to No if the user just presses Enter"?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-a&lt;/code&gt; flag removes &lt;em&gt;all&lt;/em&gt; unused images, not just dangling ones. The &lt;code&gt;--volumes&lt;/code&gt; flag adds unused volumes to the cleanup list. Check it out, and the warning verifies it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all anonymous volumes not used by at least one container
  - all images without at least one container associated to them
  - all build cache

Are you sure you want to continue? [y/N]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few more handy commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# Force-remove all images&lt;/span&gt;
docker volume &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# Remove all volumes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Satisfaction!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Use Multi-Stage Builds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/captains/karan-verma/" rel="noopener noreferrer"&gt;Karan Verma&lt;/a&gt; is a Docker Captain from Jalandhar, India. He is a software engineer and community leader who has been active in the Docker community in Jalandhar since 2017, with a focus that includes AI and MLOps.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1939768473887916538-62" src="https://platform.twitter.com/embed/Tweet.html?id=1939768473887916538"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1939768473887916538-62');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1939768473887916538&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;It's not only AI images that can get big. It's better to trim images down, AI or not. It's cost-effective, faster to deploy, and more secure by reducing the attack surface. Multi-stage builds are the way to go for that.&lt;/p&gt;

&lt;p&gt;To add to that, &lt;code&gt;docker init&lt;/code&gt; already generates a multi-stage Dockerfile for you.&lt;/p&gt;

&lt;p&gt;Also, make sure the final stage is hardened with a non-root user and limited privileges. For example, use a base image with no package manager, no shell, and no extra tools.&lt;/p&gt;

&lt;p&gt;Another important tip is to generate SBOM attestations during the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--sbom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; my-image:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command doesn't automatically include all stages in the SBOM, so you need to add the following line to each stage in your Dockerfile to ensure they are included:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILDKIT_SBOM_SCAN_CONTEXT=true&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;image&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;stage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Choose Lightweight, Version-Pinned Base Images
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/contributors/sergio-lopes/" rel="noopener noreferrer"&gt;Sergio Lopes&lt;/a&gt; is a Docker Captain from Sao Paulo, Brazil, and a Principal Backend Engineer at Banco Itau Unibanco S.A. Docker highlights his long backend engineering background and expertise in developer productivity, Kubernetes, modern application development, and observability.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1944758785475498198-694" src="https://platform.twitter.com/embed/Tweet.html?id=1944758785475498198"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1944758785475498198-694');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1944758785475498198&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;This tweet is from July 2025, but the advice is evergreen. Use Docker Hardened Images (DHI) for base images, and pin to a specific version. The DHI are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Open-source&lt;/li&gt;
&lt;li&gt;Secure-by-default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the catalog at &lt;a href="https://dhi.io" rel="noopener noreferrer"&gt;dhi.io&lt;/a&gt; and pick the right image for your language and use case. Search for "node", get into the &lt;a href="https://hub.docker.com/hardened-images/catalog/dhi/node" rel="noopener noreferrer"&gt;Node.js image catalog&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0ms7meghy1vt90ky3p7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0ms7meghy1vt90ky3p7.png" alt="DHI Node.js Catalog" width="799" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then go to the "Images" tab to see &lt;a href="https://hub.docker.com/hardened-images/catalog/dhi/node/images" rel="noopener noreferrer"&gt;the full list&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2iifvjnl9thpkwbffw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2iifvjnl9thpkwbffw7.png" alt="DHI Node.js Images" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the list of images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there is a lock, it's not free to use. Just skip it.&lt;/li&gt;
&lt;li&gt;There are Debian and Alpine variants.&lt;/li&gt;
&lt;li&gt;There are "dev" variants with build tools and "prod" variants without them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find a version, and your Dockerfile should start like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# The build stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;dhi.io/node:26.2.0-debian13-dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="c"&gt;# The production stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; dhi.io/node:26.2.0-debian13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dev image has 10 CVEs and the prod image has 0.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Use Docker Scout Quickview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/contributors/khushboo-verma/" rel="noopener noreferrer"&gt;Khushboo Verma&lt;/a&gt; is a Docker Captain and Platform Engineer at Appwrite in Bengaluru, India. She is also a community builder and speaker, with Docker listing her expertise in developer productivity, modern application development, and observability.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1947370272115290448-318" src="https://platform.twitter.com/embed/Tweet.html?id=1947370272115290448"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1947370272115290448-318');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1947370272115290448&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;docker scout quickview&lt;/code&gt; command is a fast way to get a snapshot of your image's security posture. It checks for known CVEs, lists dependencies, and provides metadata about the base image. This is especially useful in CI pipelines to catch vulnerabilities before pushing images to a registry.&lt;/p&gt;

&lt;p&gt;Let's do it on the DHI Node.js image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker scout quickview dhi.io/node:26.2.0-debian13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    i New version 1.21.0 available (installed version is 1.20.3) at https://github.com/docker/scout-cli
    ✓ SBOM obtained from attestation, 20 packages found
    ✓ Provenance obtained from attestation
    ✓ VEX statements obtained from attestation

    i Base image was auto-detected. To get more accurate results, build images with max-mode provenance attestations.
      Review docs.docker.com ↗ for more information.

 Target   │  dhi.io/node:26.2.0-debian13  │    0C     0H     0M     0L
   digest │  f3fb2a06abd6                 │
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, there are no CVEs, and the image has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SBOM attestation with 20 packages&lt;/li&gt;
&lt;li&gt;Provenance attestation&lt;/li&gt;
&lt;li&gt;VEX statements attestation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to learn more about these concepts, check out the Docker Commandos workshop on Docker Labspaces: &lt;a href="https://www.dockersecurity.io/commandos" rel="noopener noreferrer"&gt;Docker Commandos&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Use .dockerignore
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/captains/anjan-kumar-reddy-ayyadapu/" rel="noopener noreferrer"&gt;Anjan Kumar Reddy Ayyadapu&lt;/a&gt; is a Docker Captain and Senior Architect Solution Leader at Cloudera Inc. Docker lists his expertise across AI/ML, CI/CD, Kubernetes, observability, developer productivity, and software secure supply chain work.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1950295464433025395-539" src="https://platform.twitter.com/embed/Tweet.html?id=1950295464433025395"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1950295464433025395-539');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1950295464433025395&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The tweet compares &lt;code&gt;.dockerignore&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;, which is exactly the right mental model. &lt;code&gt;.gitignore&lt;/code&gt; decides what should not enter version control; &lt;code&gt;.dockerignore&lt;/code&gt; decides what should not enter the Docker build context.&lt;/p&gt;

&lt;p&gt;Two points on that!&lt;/p&gt;

&lt;p&gt;When doing a &lt;code&gt;docker build&lt;/code&gt; command, it usually looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-image:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; at the end is not the Dockerfile path; it's the build context path. It means, "send the current directory and all its contents to the Docker daemon for the build".&lt;/p&gt;

&lt;p&gt;Anjan says &lt;em&gt;blacklist&lt;/em&gt; some files with &lt;code&gt;.dockerignore&lt;/code&gt;, I would say &lt;em&gt;whitelist&lt;/em&gt; some files with &lt;code&gt;.dockerignore&lt;/code&gt;. Start with a clean slate, and add only what you need. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .dockerignore
*

!src/
!package.json
!package-lock.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Limit Container Privileges
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Captain intro:&lt;/strong&gt; &lt;a href="https://www.docker.com/captains/mohammad-ali-arabi/" rel="noopener noreferrer"&gt;Mohammad-Ali A'rabi&lt;/a&gt; appears again in Docker's series, this time with a security tip. It's not me promoting myself, it's Docker!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1953561787623788652-733" src="https://platform.twitter.com/embed/Tweet.html?id=1953561787623788652"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1953561787623788652-733');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1953561787623788652&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Just for context: Linux capabilities are granular permissions that can be independently enabled or disabled for processes. Similar to the whitelisting approach of &lt;code&gt;.dockerignore&lt;/code&gt;, you can start with a clean slate by dropping all capabilities and then adding only the ones your application needs. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--cap-drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ALL &lt;span class="nt"&gt;--cap-add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN my-image:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's similar in a Kubernetes pod spec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-pod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-container&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-image:latest&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
          &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NET_ADMIN"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To learn more about Linux capabilities and how to use them in Docker and Kubernetes, check out the book &lt;a href="https://www.dockersecurity.io/docker-and-kubernetes-security" rel="noopener noreferrer"&gt;Docker and Kubernetes Security&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I wish Docker starts sharing more tips from Docker Captains, and I hope this post helps expand on the original tweets with more context and examples. If you have any questions or want to share your own Docker tips, feel free to reach out on &lt;a href="https://www.linkedin.com/in/aerabi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://x.com/MohammadAliEN" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Dockerizing!&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
  </channel>
</rss>
