Vulnerability Remediation for chainloop
This skill reviews open vulnerability policy violations recorded in Chainloop for the chainloop project and applies fixes to the affected source files.
Step 1: Find the Latest Project Version
Use list_products_with_versions (no parameters needed — uses the current chainloop org) and locate the Chainloop Community Edition product. Find the chainloop project version entry and note its projectVersionId (UUID).
Step 2: Gather Compliance Results and Evidence in Parallel
Once the projectVersionId is known, make both of these calls at the same time:
Call A — get_frameworks_compliance :
-
project_version_id : the UUID from Step 1
-
framework_ids : ["0ceef195-6900-4166-8407-77eb84954ed3"] (chainloop-best-practices)
Call B — list_pieces_of_evidence :
-
project_name : chainloop
-
project_version_name : the version name from Step 1 (e.g. v1.77.0 )
-
latest : true
Parsing the compliance result (Call A)
The response will be large — parse it programmatically using a Bash subagent:
import json
with open('<tool-result-file>') as f: raw = json.load(f) data = json.loads(raw[0]['text'])
for req in data: if 'vulnerabilit' in req.get('name', '').lower(): status = req.get('status', '') failed = [e for e in req.get('policyEvaluations', []) if e.get('status') not in ('PASSED', 'SKIPPED')] print(f"Requirement: {req['name']} — Status: {status}") for e in failed: print(f" FAILED: policy={e['name']} material={e.get('materialName','-')} status={e.get('status','-')}")
This gives you the list of failing material names (e.g. control-plane-migrations-report ).
Step 3: Download the SARIF for Each Failing Material
From the list_pieces_of_evidence result (Call B above), find the item whose name matches the failing material name and whose kind is SARIF . Use its digest field directly — no need to decode attestations.
Call download_evidence_by_digest with:
-
digest : the digest of the matching SARIF item
-
download_content : true
The SARIF logicalLocations[].fullyQualifiedName field contains the full image reference, e.g.:
ghcr.io/chainloop-dev/chainloop/control-plane-migrations:v1.77.0@sha256:<digest>:/atlas
The binary path (e.g. /atlas , /app ) tells you which binary inside the image is vulnerable.
Step 4: Identify the Fix
4a. Atlas / Migration Dockerfile vulnerabilities
Symptom: SARIF location is /atlas , image is control-plane-migrations
Source file: app/controlplane/Dockerfile.migrations
Fix procedure:
-
Check the current atlas version in the comment at the top of the Dockerfile (e.g. # atlas version v1.1.0 )
-
Find the latest available version: curl -s "https://registry.hub.docker.com/v2/repositories/arigaio/atlas/tags?page_size=20&ordering=last_updated"
| python3 -c "import json,sys; [print(t['name']) for t in json.load(sys.stdin)['results'] if t['name'][0].isdigit() and '-' not in t['name']]" -
Run grype on the current and candidate versions to confirm the CVEs are present then gone: grype arigaio/atlas:<current-version> --only-fixed 2>&1 grype arigaio/atlas:<new-version> --only-fixed 2>&1
A clean run has only the header line and no CVE rows.
-
Once a clean version is confirmed, pull it and get its digest: docker pull arigaio/atlas:<new-version> docker inspect --format='{{index .RepoDigests 0}}' arigaio/atlas:<new-version>
-
Update app/controlplane/Dockerfile.migrations :
from: arigaio/atlas:<NEW_VERSION>
docker run arigaio/atlas@sha256:<NEW_DIGEST> version
atlas version v<NEW_VERSION>
FROM arigaio/atlas@sha256:<NEW_DIGEST> as base
4b. Go stdlib / Go module vulnerabilities (backend)
Symptom: SARIF location is a Go binary (e.g. /app , /server ), package is stdlib or a Go module
Fix options (in order of preference):
Option A — Upgrade Go version (for stdlib CVEs): Use the upgrading-golang skill to bump the Go version in go.mod and all Dockerfiles.
Option B — Upgrade a specific Go dependency (for third-party modules):
-
Identify the affected module from the SARIF purls field (e.g. pkg:golang/github.com/foo/bar@v1.2.3 )
-
Update go.mod : go get github.com/foo/bar@<fixed-version> go mod tidy
-
Verify with grype: grype dir:. --only-fixed 2>&1
Step 5: Verify the Fix with Grype
Always run grype before and after the change to confirm the CVEs are resolved:
Before — should show the CVE rows
grype <image>:<current-version> --only-fixed 2>&1
After — should show header only, no CVE rows
grype <image>:<new-version> --only-fixed 2>&1
A clean run has only the column header line and zero data rows.
Step 6: Commit and Create a PR
Check which branch you are on — do not create a new branch if one already exists:
git branch --show-current
Commit with signoff (no co-author):
git add <changed-files> git commit -s -m "fix(<scope>): <short description of the CVE fix>" git push -u origin <current-branch>
Create the PR with gh pr create :
gh pr create --title "fix(<scope>): <short description>" --body "$(cat <<'EOF'
Summary
- <bullet: what was upgraded and why>
- Fixes <CVE-ID> (<Severity>) and <CVE-ID> (<Severity>) in <package>
- <brief note on how the fix works, e.g. new version built with Go X.Y.Z> EOF )"
Step 7: Report Results
Summarise the findings and changes in this format:
Vulnerability Remediation Summary
Project: chainloop v<version> Requirement: no-vulnerabilities-high — was: FAIL
Fixed
| CVE | Severity | Package | Old Version | Fix Applied |
|---|---|---|---|---|
| CVE-XXXX-XXXXX | Critical | <pkg> | <old> | Upgraded <file> to <new> |
Files Changed
app/controlplane/Dockerfile.migrations— atlas vX.X.X → vX.X.X
PR
<GitHub PR URL>
Key Reference Data
Item Value
Chainloop org chainloop
Project name chainloop
chainloop-best-practices framework ID 0ceef195-6900-4166-8407-77eb84954ed3
Continuous-scanning workflow ID c506a425-d307-4a59-9132-659ffd417b57
Migrations Dockerfile app/controlplane/Dockerfile.migrations
Backend go.mod go.mod (root)
Important Notes
-
Always pin Docker images by SHA256 digest, not tag alone
-
For Go stdlib CVEs, upgrading the atlas or golang builder image is usually sufficient — check via grype before touching go.mod
-
Run go mod tidy after any go.mod change
-
The compliance-scanning runs daily, so the policy status will update automatically after the fix is merged and a new image is built