Verity automatically scans Helm chart dependencies for container image vulnerabilities, patches them using Copa, and publishes wrapper charts that make it easy to consume patched images while maintaining full chart customization.
# Install prometheus with security-patched images
helm install my-prometheus \
oci://quay.io/verity/charts/prometheus \
--version 25.8.0-0
# With custom values (patched images automatically included)
helm install my-prometheus \
oci://quay.io/verity/charts/prometheus \
-f my-values.yaml# Scan charts for images
./verity -chart Chart.yaml -output charts
# Scan and patch with Copa
./verity -chart Chart.yaml -output charts \
-patch \
-registry quay.io/your-org \
-buildkit-addr docker-container://buildkitdChart.yaml Dependencies
↓
Scan for Images (verity)
↓
Vulnerability Scan (Trivy)
↓
Patch Images (Copa)
↓
Wrapper Charts Created
↓
Published to Quay.io
For each chart dependency, verity creates a wrapper chart:
charts/
prometheus/
Chart.yaml # Depends on original prometheus chart
values.yaml # Patched images (namespaced)
.helmignore
reports/ # Trivy vulnerability reports (JSON)
Example values.yaml:
prometheus:
server:
image:
registry: quay.io/verity
repository: prometheus
tag: v2.48.0-patched
alertmanager:
image:
registry: quay.io/verity
repository: alertmanager
tag: v0.26.0-patchedWrapper chart versions mirror the upstream chart version with a patch level suffix:
Format: {upstream-version}-{patch-level}
Examples:
prometheus 25.8.0 → prometheus 25.8.0-0 (initial patch)
→ prometheus 25.8.0-1 (new CVEs found)
→ prometheus 25.8.0-2 (more patches)
prometheus 25.9.0 → prometheus 25.9.0-0 (chart update, reset)
When versions change:
- Chart Update (Renovate): Base version changes, patch level resets to
-0 - New CVEs (Scheduled Scan): Patch level auto-increments (queries registry for existing versions)
- Manual Patch: Patch level auto-increments (if registry is specified)
This keeps the relationship to upstream charts clear while tracking security updates independently.
Verity is fully automated with GitHub Actions:
- Scans for new vulnerabilities
- Creates PR if patches available
- Runs daily at 2 AM UTC
- Renovate bumps chart version
- Workflow auto-patches images
- Commits to same PR
- Ready to merge!
- Wrapper charts published to OCI registry
- Patched images verified
- Chart index generated
See WORKFLOWS.md for details.
✅ Security patches without forking upstream ✅ Update chart versions independently ✅ Automated vulnerability monitoring ✅ Publish to your own registry
✅ Drop-in replacements for original charts ✅ All customization options preserved ✅ Transparent security patching ✅ Zero-trust supply chain (verify patches yourself)
- Verity (Go) - Chart scanner and wrapper generator
- Trivy - Vulnerability scanner
- Copa - Microsoft's container patching tool
- BuildKit - Image building
- Helm - Chart dependency management
┌──────────────┐
│ Renovate │ Updates Chart.yaml
└──────┬───────┘
↓
┌──────────────────┐
│ patch-on-pr.yaml │ Auto-patches
└──────┬───────────┘
↓
┌────────────────┐
│ Merge to main │
└──────┬─────────┘
↓
┌─────────────┐
│ publish.yaml│ Pushes to Quay.io
└─────────────┘
Plus scheduled scans for continuous monitoring.
Edit Chart.yaml:
dependencies:
- name: prometheus
version: "25.8.0"
repository: oci://ghcr.io/prometheus-community/charts
- name: grafana
version: "7.0.0"
repository: https://grafana.github.io/helm-chartsRenovate and workflows handle the rest.
Registry:
Set via -registry flag (e.g. quay.io/your-org).
Scan Schedule:
Edit .github/workflows/scheduled-scan.yaml:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTCRenovate:
See .github/renovate.json for dependency update config.
- Go 1.24+
- Docker
- Helm 3
- BuildKit (for patching)
go build -o verity .docker run --rm -v $(pwd):/workspace \
quay.io/verity:latest \
-chart /workspace/Chart.yaml -output /workspace/chartsverity [options]
Options:
-chart string
Path to Chart.yaml (default "Chart.yaml")
-output string
Output directory for charts (default "charts")
-patch
Enable patching with Trivy + Copa
-registry string
Target registry for patched images (e.g. quay.io/org)
-buildkit-addr string
BuildKit address (e.g. docker-container://buildkitd)
-report-dir string
Directory for Trivy JSON reports
Examples:
# Scan only
./verity -chart Chart.yaml -output ./charts
# Scan and patch
./verity -chart Chart.yaml -output ./charts \
-patch \
-registry quay.io/myorg \
-buildkit-addr docker-container://buildkitd
# With custom report directory
./verity -chart Chart.yaml -output ./charts \
-patch \
-registry quay.io/myorg \
-buildkit-addr docker-container://buildkitd \
-report-dir ./reportsgo test ./...# Check YAML syntax
for f in .github/workflows/*.yaml; do
yq eval '.' "$f" > /dev/null && echo "✅ $f" || echo "❌ $f"
done# Start BuildKit
docker run -d --privileged --name buildkitd \
moby/buildkit:v0.19.0
# Run verity with patching
./verity -chart Chart.yaml -output /tmp/test-charts \
-patch \
-registry quay.io/test \
-buildkit-addr docker-container://buildkitd
# Cleanup
docker stop buildkitd && docker rm buildkitd- WORKFLOWS.md - Complete workflow automation guide
- WRAPPER_CHARTS.md - How wrapper charts work
- .github/RENOVATE.md - Renovate integration
Every patch run includes:
- Trivy JSON reports (attached to workflow runs)
- CVE details and CVSS scores
- Fixable vs unfixable vulnerabilities
Patched images are:
- Built from official upstream images
- Scanned with Trivy (open source)
- Patched with Copa (Microsoft, open source)
- Pushed to your registry with
-patchedsuffix - Never modify upstream images
Verify patches yourself:
# Pull patched image
docker pull quay.io/verity/prometheus:v2.48.0-patched
# Compare to original
docker pull quay.io/prometheus/prometheus:v2.48.0
docker diff <original-id> <patched-id>Q: What types of vulnerabilities can Copa patch? A: Copa patches OS-level packages (apt, yum, apk). It cannot patch application vulnerabilities in compiled binaries.
Q: Will this patch ALL vulnerabilities? A: No. Only vulnerabilities with available package updates. Some images may have unfixable CVEs.
Q: Can I use my existing Chart values? A: Yes! Wrapper charts support all original chart values. Just namespace them under the chart name (or use them as-is, Helm handles it).
Q: What if I don't want to auto-merge security updates?
A: Edit .github/renovate.json and set automerge: false for vulnerability alerts.
Q: How do I add more charts?
A: Just add them to Chart.yaml dependencies. Workflows automatically handle any number of charts.
Q: Can I run this without GitHub Actions? A: Yes! Verity is a standalone CLI tool. Run it manually or integrate with any CI system.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Open a pull request
- Copa - Microsoft's container patching tool
- Trivy - Vulnerability scanner
- Helm - Kubernetes package manager
- Renovate - Dependency automation