<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Devsecops on t0ul</title><link>https://t0ul.com/tags/devsecops/</link><description>Recent content in Devsecops on t0ul</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 14 Oct 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://t0ul.com/tags/devsecops/index.xml" rel="self" type="application/rss+xml"/><item><title>Ship, Securely, Ch. 1: Getting Started</title><link>https://t0ul.com/blog/ship-securely-ch1-getting-started/</link><pubDate>Tue, 02 Sep 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch1-getting-started/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This chapter does two things. First it explains the idea the rest of the book runs on: security built into the pipeline, not bolted on at the end. Then it gets your machine ready to practice it, with Go, Make, an editor, Docker, and a local Kubernetes cluster to deploy into.&lt;/p&gt;
&lt;h2 id="security-in-the-pipeline-not-after-it"&gt;Security in the pipeline, not after it&lt;/h2&gt;
&lt;p&gt;DevOps is a simple idea with a lot of machinery behind it. Development and operations work as one team, and software ships in small, frequent changes that flow through an automated pipeline: build, test, release, repeat. The pipeline is the product. Code only counts once it is running somewhere, so everything that gets it there is scripted, versioned, and repeatable.&lt;/p&gt;</description></item><item><title>Ship, Securely, Ch. 2: DevSecOps in Action</title><link>https://t0ul.com/blog/ship-securely-ch2-devsecops-in-action/</link><pubDate>Tue, 09 Sep 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch2-devsecops-in-action/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Getting tools to run is the easy part. This chapter is about making sense of
their output, and turning it into a decision instead of a backlog.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Now, let&amp;rsquo;s clone the repo and make sure that everything works.&lt;/p&gt;
&lt;h3 id="clone-the-repository"&gt;Clone the repository&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/t0ul/ship-securely-devsecops-starter"&gt;Ship Securely DevSecOps Starter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="why-this-book-is-local-first"&gt;Why this book is local-first&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Zero cloud accounts, zero ongoing cost, predictable setup.&lt;/li&gt;
&lt;li&gt;Everyone’s laptop is the same “platform”: Docker + Minikube + Make.&lt;/li&gt;
&lt;li&gt;Artifacts saved locally → easy “audit packet” and reproducible labs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="what-youll-install-once"&gt;What you’ll install (once)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Git, Docker Desktop (or Docker Engine), Make, Go, &lt;strong&gt;Minikube&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Optional: VS Code (recommended).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="repo-layout-quick-tour"&gt;Repo layout (quick tour)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ship-securely-starter/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ app/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├─ main.go
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├─ go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └─ Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ infra/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├─ docker/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └─ compose.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └─ k8s/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├─ deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├─ service.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └─ kustomization.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ tools/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └─ zap/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └─ README.md # place ZAP context/auth if needed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ artifacts/ # CI reports written here (generated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ .pre-commit-config.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─ Makefile # `make ci`, `make cd`, mk-* targets
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─ README.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="chapter-2-make-ci"&gt;Chapter 2: Make CI&lt;/h2&gt;
&lt;h3 id="first-run-ci-on-your-laptop"&gt;First run (CI on your laptop)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# macOS/Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make ci
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="windows-powershell"&gt;Windows (PowerShell)&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make ci
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="what-you-should-see"&gt;what you should see&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker build -t ship-securely/app:dev app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[+] Building 1.2s (14/14) FINISHED docker:desktop-linux
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load build definition from Dockerfile 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring dockerfile: 645B 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load metadata for docker.io/library/golang:1.22-alpine 0.4s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load metadata for docker.io/library/alpine:3.20 0.4s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load .dockerignore 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring context: 2B 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [build 1/4] FROM docker.io/library/golang:1.22-alpine@sha256:1699c10032ca2582ec89a24a1312d986a3f094aed3d5c1147b19880afe40e052 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [stage-1 1/4] FROM docker.io/library/alpine:3.20@sha256:765942a4039992336de8dd5db680586e1a206607dd06170ff0a37267a9e01958 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load build context 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring context: 2.02kB 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [build 2/4] WORKDIR /src 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [build 3/4] COPY . . 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [build 4/4] RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build - 0.7s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 2/4] RUN adduser -D -u 10001 appuser 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 3/4] WORKDIR /home/appuser 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [stage-1 4/4] COPY --from=build /out/server /usr/local/bin/server 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; exporting to image 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; exporting layers 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; writing image sha256:f72451a65103493a2c99c0b63a3768c21af2fdd1c5679e69b96d8878fc18d3fb 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; naming to docker.io/ship-securely/app:dev 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/t419rs4ety3zd51i77w098cc0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;What&amp;#39;s next:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; View a summary of image vulnerabilities and recommendations → docker scout quickview 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;== Hadolint (Dockerfile) ==
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -i hadolint/hadolint &amp;lt; app/Dockerfile &amp;gt; artifacts/hadolint.txt || true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;== Semgrep (SAST) ==
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -v /Users/t/go/src/ship-securely-starter:/src returntocorp/semgrep semgrep --config p/owasp-top-ten --sarif --output /src/artifacts/semgrep.sarif /src/app || true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Scan Status │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Scanning 3 files tracked by git with 542 Code rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Language Rules Files Origin Rules 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ───────────────────────────── ─────────────────── 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;multilang&amp;gt; 5 3 Community 542 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; go 38 1 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dockerfile 4 1 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌──────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Scan Summary │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;✅ Scan completed successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; • Findings: 1 (1 blocking)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; • Rules run: 47
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; • Targets scanned: 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; • Parsed lines: ~100.0%
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; • No ignore information available
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ran 47 rules on 3 files: 1 finding.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;== Gitleaks (secrets) ==
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -v /Users/t/go/src/ship-securely-starter:/work zricethezav/gitleaks:latest detect -s /work -r artifacts/gitleaks.json --no-banner || true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4:09PM FTL Report path is not writable: artifacts/gitleaks.json error=&amp;#34;open artifacts/gitleaks.json: no such file or directory&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;== Checkov (IaC) ==
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -v /Users/t/go/src/ship-securely-starter:/work bridgecrew/checkov -d /work/infra --output-file-path artifacts/checkov.json || true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _ _
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ___| |__ ___ ___| | _______ __
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / __| &amp;#39;_ \ / _ \/ __| |/ / _ \ \ / /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | (__| | | | __/ (__| &amp;lt; (_) \ V /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \___|_| |_|\___|\___|_|\_\___/ \_/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;By Prisma Cloud | version: 3.2.476 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Update available 3.2.476 -&amp;gt; 3.2.477
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Run pip3 install -U checkov to update 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubernetes scan results:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Passed checks: 83, Failed checks: 7, Skipped checks: 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Check: CKV_K8S_75: &amp;#34;Ensure that the --authorization-mode argument includes Node&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PASSED for resource: Deployment.default.app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File: /k8s/deployment.yaml:1-48
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/ensure-that-the-authorization-mode-argument-includes-node
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Check: CKV_K8S_70: &amp;#34;Ensure that the --token-auth-file argument is not set&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PASSED for resource: Deployment.default.app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File: /k8s/deployment.yaml:1-48
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/ensure-that-the-token-auth-file-parameter-is-not-set
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="chapter-2-make-cd"&gt;Chapter 2: Make CD&lt;/h2&gt;
&lt;h3 id="deploy-locally-cd-to-minikube"&gt;Deploy Locally (CD to Minikube)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make cd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="what-you-should-see-1"&gt;What you should see&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;t@Mac ship-securely-devsecops % make cd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⛵ Minikube (ship) is running
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker build -t ship-securely/app:dev app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[+] Building 0.3s (15/15) FINISHED docker:desktop-linux
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load build definition from Dockerfile 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring dockerfile: 876B 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load metadata for docker.io/library/alpine:3.20 0.3s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load metadata for docker.io/library/golang:1.22-alpine 0.3s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load .dockerignore 0.0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring context: 2B 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [build 1/4] FROM docker.io/library/golang:1.22-alpine@sha256:1699c10032c 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [stage-1 1/5] FROM docker.io/library/alpine:3.20@sha256:765942a403999233 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; [internal] load build context 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; transferring context: 447B 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 2/5] RUN addgroup -g 10001 app &amp;amp;&amp;amp; adduser -D -H -u 10001 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 3/5] WORKDIR /home/appuser 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [build 2/4] WORKDIR /src 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [build 3/4] COPY . . 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [build 4/4] RUN --mount=type=cache,target=/go/pkg/mod --mount 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 4/5] COPY --from=build /out/server /usr/local/bin/server 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; CACHED [stage-1 5/5] RUN chown -R 10001:10001 /home/appuser 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; exporting to image 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; exporting layers 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; writing image sha256:7e699d375101f7b1246378e22a53a70e9d89f63138a7f666 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =&amp;gt; =&amp;gt; naming to docker.io/ship-securely/app:dev 0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/ipq16egtws0nkd6twx07u5xs7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;What&amp;#39;s next:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; View a summary of image vulnerabilities and recommendations → docker scout quickview 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;minikube -p ship image load ship-securely/app:dev
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get ns ship &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || kubectl create ns ship
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;service/app unchanged
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deployment.apps/app unchanged
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl -n ship set image deploy/app app=ship-securely/app:dev
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl -n ship rollout status deploy/app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deployment &amp;#34;app&amp;#34; successfully rolled out
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;== OWASP ZAP (baseline via port-forward) ==
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;( kubectl -n ship port-forward deploy/app 8080:3000 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp; echo $! &amp;gt; .pf.pid )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Port-forward is live
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ZAP target: http://host.docker.internal:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Using the Automation Framework
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Missing Anti-clickjacking Header [10020] x 6 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: X-Content-Type-Options Header Missing [10021] x 7 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Content Security Policy (CSP) Header Not Set [10038] x 7 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Storable and Cacheable Content [10049] x 8 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Permissions Policy Header Not Set [10063] x 7 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Modern Web Application [10109] x 1 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WARN-NEW: Insufficient Site Isolation Against Spectre Vulnerability [90004] x 19 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 7 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 60
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;✅ Deployed app to Minikube (ship) in namespace ship
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="evidence-packet"&gt;Evidence Packet&lt;/h3&gt;
&lt;p&gt;Open ./artifacts/ and skim:&lt;/p&gt;</description></item><item><title>Ship, Securely, Ch. 3: Reviewing Results</title><link>https://t0ul.com/blog/ship-securely-ch3-reviewing-results/</link><pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch3-reviewing-results/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="chapter-3-reviewing-results"&gt;Chapter 3. Reviewing Results&lt;/h2&gt;
&lt;h3 id="sast--static-application-security-testing"&gt;SAST — Static Application Security Testing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;br&gt;
SAST analyzes source code &lt;em&gt;without executing it&lt;/em&gt; to find risky patterns (e.g., unsanitized inputs, unsafe APIs). In this project we use &lt;strong&gt;Semgrep&lt;/strong&gt; (via the &lt;code&gt;sast&lt;/code&gt; target) to scan the Go app and write results to &lt;code&gt;artifacts/semgrep.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why we need it&lt;/strong&gt;&lt;br&gt;
Catches code-level flaws early, while they’re cheap to fix, and shifts security left. Typical hits: injection, XSS, insecure crypto, unsafe deserialization, etc.&lt;/p&gt;</description></item><item><title>Ship, Securely, Ch. 4: Ratcheting and Supply-Chain Hardening</title><link>https://t0ul.com/blog/ship-securely-ch4-supply-chain-hardening/</link><pubDate>Tue, 23 Sep 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch4-supply-chain-hardening/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="chapter-4-trivy-image-workflow"&gt;Chapter 4. Trivy Image Workflow&lt;/h2&gt;
&lt;h3 id="1-build--scan--decide-quarantine-first"&gt;1) Build → Scan → Decide (quarantine first)&lt;/h3&gt;
&lt;p&gt;Tag every fresh build as &lt;strong&gt;quarantine&lt;/strong&gt; until it passes policy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Makefile additions&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-makefile" data-lang="makefile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#79c0ff"&gt;QUAR&lt;/span&gt; &lt;span style="color:#ff7b72;font-weight:bold"&gt;:=&lt;/span&gt; &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;IMAGE_REPO&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;:quarantine-&lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;SHA&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#79c0ff"&gt;GOOD&lt;/span&gt; &lt;span style="color:#ff7b72;font-weight:bold"&gt;:=&lt;/span&gt; &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;IMAGE_REPO&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;:good-&lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;TAG&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d2a8ff;font-weight:bold"&gt;build&lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	docker build -t &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;IMAGE&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt; app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	docker tag &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;IMAGE&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt; &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;QUAR&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt; &lt;span style="color:#8b949e;font-style:italic"&gt;# mark as quarantine by default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d2a8ff;font-weight:bold"&gt;sca&lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	@echo &lt;span style="color:#a5d6ff"&gt;&amp;#34;== Trivy (image scan) ==&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	docker run --rm -v &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;PWD&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;:/workspace &lt;span style="color:#79c0ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#79c0ff"&gt;&lt;/span&gt;	 -v &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;PWD&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt;/.trivy-db:/root/.cache/trivy &lt;span style="color:#79c0ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#79c0ff"&gt;&lt;/span&gt;	 aquasec/trivy:latest image --ignore-unfixed &lt;span style="color:#79c0ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#79c0ff"&gt;&lt;/span&gt;	 --format json -o /workspace/artifacts/trivy-image.json &lt;span style="color:#ff7b72"&gt;$(&lt;/span&gt;QUAR&lt;span style="color:#ff7b72"&gt;)&lt;/span&gt; &lt;span style="color:#ff7b72;font-weight:bold"&gt;||&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;We scan &lt;code&gt;$(QUAR)&lt;/code&gt; specifically so it never accidentally ships before review.&lt;/p&gt;</description></item><item><title>Ship, Securely, Ch. 5: Kubernetes Runtime Security</title><link>https://t0ul.com/blog/ship-securely-ch5-kubernetes-runtime-security/</link><pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch5-kubernetes-runtime-security/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="chapter-5-kubernetes-configuration-testing"&gt;Chapter 5. Kubernetes Configuration Testing&lt;/h2&gt;
&lt;h3 id="why-this-step"&gt;Why this step&lt;/h3&gt;
&lt;p&gt;Catching issues in &lt;code&gt;infra/k8s/*.yaml&lt;/code&gt; &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;kubectl apply&lt;/code&gt; is cheap and fast. These tools complement each other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kube-linter&lt;/strong&gt;: opinionated rules → SARIF (great for PR review).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-score&lt;/strong&gt;: human-readable “why” explanations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checkov&lt;/strong&gt;: policy-as-code across K8s/Terraform/etc. (already in CI).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="run-it"&gt;Run it&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# from repo root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make k8s-audit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;What you’ll see&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Ship, Securely, Ch. 6: Conclusion</title><link>https://t0ul.com/blog/ship-securely-ch6-conclusion/</link><pubDate>Tue, 07 Oct 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-ch6-conclusion/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="chapter-6-conclusion-and-next-steps"&gt;Chapter 6. Conclusion and Next Steps&lt;/h2&gt;
&lt;p&gt;You just built a &lt;strong&gt;local-first DevSecOps stack&lt;/strong&gt; that runs anywhere a laptop does. It ships a working app on day one, grows in small, testable waves, produces &lt;strong&gt;evidence&lt;/strong&gt; for every step, and hardens both your &lt;strong&gt;supply chain&lt;/strong&gt; and &lt;strong&gt;runtime&lt;/strong&gt; without cloud spend.&lt;/p&gt;
&lt;p&gt;This chapter helps you (1) summarize what you’ve built, (2) &lt;strong&gt;ratchet&lt;/strong&gt; quality safely, (3) map your &lt;code&gt;make&lt;/code&gt; targets to a hosted CI, and (4) roll it out with sane ownership, SLAs, and audit-ready artifacts. Finally, you’ll get a compact “what’s next” backlog.&lt;/p&gt;</description></item><item><title>Ship, Securely: Appendix</title><link>https://t0ul.com/blog/ship-securely-appendix/</link><pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/ship-securely-appendix/</guid><description>&lt;p&gt;&lt;em&gt;Part of &lt;a href="https://t0ul.com/blog/ship-securely-ch1-getting-started/"&gt;Ship, Securely&lt;/a&gt;, a hands-on DevSecOps book.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="appendix-image-signing--offline-digest-vs-registry-signatures"&gt;Appendix: Image Signing — Offline Digest vs Registry Signatures&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Two ways to prove “what we built is what we run”:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A) Offline (no registry): sign the image &lt;em&gt;digest&lt;/em&gt; as a blob&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What it proves:&lt;/strong&gt; You signed the SHA256 digest of the &lt;em&gt;promoted&lt;/em&gt; image (GOOD).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Where the signature lives:&lt;/strong&gt; In your repo as &lt;code&gt;artifacts/image-digest.bundle&lt;/code&gt; (not attached to the image).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Air-gapped demos, workshops without a registry, or when you only need an &lt;strong&gt;evidence pack&lt;/strong&gt; (auditors/customers).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limitations:&lt;/strong&gt; Admission controllers (Kyverno) can’t verify this at deploy time because the signature isn’t stored alongside the image.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;B) Registry signatures (recommended for class): sign the image &lt;em&gt;reference&lt;/em&gt; in a registry&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>