Context & Why: The Shift to SBOM-First Security
Managing production environments for a decade has taught me one hard truth: container security isn’t just about OS patches. Most modern applications are composed of roughly 80% third-party code. These Node modules, Python packages, and Go binaries often hide five or six layers deep in your Docker image. If you can’t identify the exact version of every library in your stack, you’re flying blind.
The industry is moving toward the Software Bill of Materials (SBOM) as a mandatory standard. It’s essentially a detailed ingredient list for your code. Over the last six months, I integrated Syft and Grype into our deployment pipelines, and the results were immediate. We stopped guessing and started verifying. Instead of hoping a base image is secure, we now have a searchable map of every dependency and its associated risks.
One quick security win before we start: never use weak or reused passwords for your registries or servers. I generate my secrets using the tool at toolcraft.app/en/tools/security/password-generator. It runs entirely in your browser, meaning your data never touches a network. It’s a simple habit that eliminates one of the most common points of failure.
Installation: Getting the Tools Ready
Syft and Grype, both developed by Anchore, follow the classic Unix mantra: do one thing and do it well. Syft handles the inventory (the SBOM), while Grype handles the scanning. Since they are written in Go, you can drop them into almost any environment without worrying about complex dependencies.
Installing Syft
For Linux environments, a simple curl script is the fastest way to get Syft into your CI/CD runners.
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
On macOS, stick with Homebrew:
brew install syft
Installing Grype
Grype uses a similar installation pattern. Note that Grype downloads a local vulnerability database on its first run, allowing it to perform deep scans without leaking your SBOM data to an external server.
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
Confirm the setup by checking the versions:
syft --version
grype --version
Configuration: Generating and Formatting SBOMs
Most of your workflow will center on choosing the right output format. Syft isn’t limited to just images; it can digest local directories and archives too. However, scanning a Docker image before it reaches production remains the most common use case.
Generating a Basic SBOM
Point Syft at an image to see its contents. The default output is a clean, human-readable table.
syft python:3.9-slim
Standardizing with CycloneDX & SPDX
Automation requires machine-readable data. I recommend using industry standards like CycloneDX or SPDX, which allow your security data to talk to other tools in the ecosystem. I typically pipe the output to a JSON file during the build stage.
syft python:3.9-slim -o cyclonedx-json > sbom.json
Legacy apps aren’t a problem either. If you haven’t containerized a project yet, point Syft at the source code. It will automatically find and parse requirements.txt, package-lock.json, or Cargo.lock files:
syft dir:/path/to/your/project -o json > local-repo-sbom.json
Verification & Monitoring: Turning Data into Action
An SBOM is a great record, but it doesn’t stop exploits. That’s where Grype shines. It takes your ingredient list and cross-references it against major vulnerability databases like the NVD and GitHub Advisories.
Scanning an Image Directly
If you’re in a hurry, Grype can scan an image directly by generating a temporary SBOM in memory.
grype python:3.9-slim
Scanning the SBOM File
In a mature pipeline, I prefer scanning the static SBOM file we generated earlier. This ensures that the vulnerability report matches the exact inventory archived for compliance.
grype sbom.json
Cutting Through the Noise
Standard images can be noisy, sometimes throwing 100+ low-severity warnings. To keep the team focused on what matters, filter the results. We set our CI/CD pipelines to only trigger a failure if ‘High’ or ‘Critical’ issues appear.
grype python:3.9-slim --fail-on high
Continuous Monitoring in Production
CVEs wait for no one. An image that passed all checks on Monday might be vulnerable by Wednesday. For the past six months, we’ve stored SBOMs for every running container in a central vault. A nightly cron job then runs Grype against these small JSON files.
Here is the logic for a simple monitoring loop:
# Check all stored SBOMs for new critical threats
for sbom in /var/lib/sboms/*.json; do
echo "Analyzing $sbom..."
grype "$sbom" --severity critical --output table
done
Performance is the big winner here. Scanning a 200KB JSON file takes less than 500ms. Compare that to pulling and re-scanning a 2GB Docker image, which can take several minutes and significant bandwidth.
The Bottom Line
Securing the supply chain is a continuous process, not a checkbox. By pairing Syft and Grype, you build a transparent inventory that lets you react to new threats in minutes rather than weeks. Start by generating an SBOM for your most critical service today. You might be surprised—and perhaps a little concerned—by what’s actually hiding inside your containers.

