Improving container security in your CI/CD pipeline

Improving container security in your CI/CD pipeline

At PyCon AU 2026 , the presentation Your Python container is 90% stuff you didn’t ask for by Scott Norris at Chainguard really exposed the impact of being lazy in container management for security purposes. With the average number of newly published CVEs at 233 per day and climbing in 2026 Source , and with that number not including the shadow CVEs still in flight, even the live demo showed higher numbers than the slides produced earlier in the day.

The CVE velocity problem

Scott’s demonstration of CVE impact using common containers such as python:3.12 and python:3.12-slim quickly highlighted the urgent need for organizations to perform basic checking and constant reporting in their CI/CD build pipeline. Engineers and infrastructure teams should become well versed in the ability to perform security scanning as a routine part of shipping software, not as an annual audit exercise.

I use a distro Python container myself, so to see that the default python:3.12 contained roughly 1,920 known CVEs (of which not all are actionable in the real world) made me stop and assess my own built containers. I was surprised at the findings.

Scott Norris PyCon AU — minimal container CVE reduction Scott Norris PyCon AU — minimal container CVE reduction Scott Norris PyCon AU — python:3.12-slim container CVE comparison

Every extra package enlarges the potential attack surface for a malicious actor. In many cases it is not necessary to find a new vulnerability by probing systems; simply executing known exploits against packages with known vulnerabilities is like a free prize for your business to potentially suffer the impact of a data breach, data loss, or cyber hijacking.

Minimal images by construction

The primary strategy Scott offered as the means to end much of the security paperwork required for government compliance is based on containers being distroless. This minimization however doesn’t come without complexity. You effectively need two versions of your containers: a full distroless production image, and a debugging variant, because you have removed the shell, package installation capabilities, and build dependencies.

For more on the distroless origins, see the Google image family at gcr.io/distroless . Chainguard applies the same philosophy to language runtimes; a minimal Python image such as cgr.dev/chainguard-private/python:3.12 is the direction of travel when you want to ship the application, not the operating system.

As Scott closed: “Ship the app. Not the whole OS.”

Australian compliance context

The presentation also pointed me to several Australian resources used for cybersecurity, including the Australian Government Signals Directorate and the Protective Security Policy Framework (PSPF) . Avoiding the paperwork burden of frameworks such as ISM and IRAP starts with not shipping unnecessary attack surface in the first place. Ship minimal images by construction, validated continuously in CI/CD.

Building a scanner for CI/CD

Taking the example from the presentation, I built my own scanner with some additional tooling (skopeo, crane) as I saw several other use cases with container sources (docker, docker-archive, oci-archive) which I will discuss in a future post.

Here is output from scanning a few images I work with regularly:

$ ./scan docker:mysql:8.4
[09:22:50] INFO  syft: generating SBOM for docker:mysql:8.4
[09:23:01] INFO  syft: docker:mysql:8.4: packages=140  types=[go-module:4, python:19, rpm:117]  size=756MB
[09:23:01] INFO  grype: scanning docker-mysql-8.4.sbom.json
[09:23:03] INFO  grype severity: Critical=1 High=45 Medium=71 Low=9 Negligible=0 Unknown=0 Total=126
[09:23:03] INFO  trivy: scanning docker:mysql:8.4 (image)
[09:23:07] INFO  trivy severity: CRITICAL=1 HIGH=60 MEDIUM=114 LOW=9 UNKNOWN=1 Total=185
[09:23:07] INFO  done

$ ./scan docker:container-registry.oracle.com/mysql/community-server:9.7
[09:21:36] INFO  syft: generating SBOM for docker:container-registry.oracle.com/mysql/community-server:9.7
[09:21:53] INFO  syft: docker:container-registry.oracle.com/mysql/community-server:9.7: packages=140  types=[npm:8, python:20, rpm:112]  size=860.3MB
[09:21:53] INFO  grype: scanning docker-container-registry.oracle.com-mysql-community-server-9.7.sbom.json
[09:21:56] INFO  grype severity: Critical=0 High=17 Medium=40 Low=7 Negligible=0 Unknown=0 Total=64
[09:21:56] INFO  trivy: scanning docker:container-registry.oracle.com/mysql/community-server:9.7 (image)
[09:22:06] INFO  trivy severity: CRITICAL=0 HIGH=36 MEDIUM=72 LOW=7 UNKNOWN=0 Total=115
[09:22:06] INFO  done

$ ./scan docker:villagesql/villagesql-server:latest
[09:19:38] INFO  syft: generating SBOM for docker:villagesql/villagesql-server:latest
[09:19:56] INFO  syft: docker:villagesql/villagesql-server:latest: packages=184  types=[deb:182, go-module:2]  size=1054.4MB
[09:19:56] INFO  grype: scanning docker-villagesql-villagesql-server-latest.sbom.json
[09:20:03] INFO  grype severity: Critical=3 High=30 Medium=456 Low=180 Negligible=11 Unknown=0 Total=680
[09:20:03] INFO  trivy: scanning docker:villagesql/villagesql-server:latest (image)
[09:20:10] INFO  trivy severity: CRITICAL=25 HIGH=392 MEDIUM=3806 LOW=500 UNKNOWN=0 Total=4723
[09:20:10] INFO  done
Tagged with: Security DevOps Python

Related Posts

My take on PyCon Australia 2026

PyCon AU 2026 held in Brisbane this week was a five day event for the Python community. With specialized tracks and dedicated tutorial and engineering days there was a wide variety of content available.

Read more

MITRE ATLAS - A 2025 Review

The MITRE ATLAS Matrix provides a working knowledge base of adversary tactics, techniques, and real-world case studies specifically for Artificial Intelligence (AI) and Machine Learning (ML) systems. It adapts the established MITRE ATT&CK adversary tactics and techniques matrix which is the standard reference for traditional IT cybersecurity.

Read more

Foundational Frameworks for GenAI Security Analysis

Three frameworks form the analytical foundation of this series’ threat analysis, selected for their complementary coverage of the GenAI security landscape and their broad adoption across enterprise security practices. The MITRE Adversarial Threat Landscape for AI Systems (MITRE ATLAS) maps tactics and techniques specific to AI systems.

Read more