chainloop-dev

vulnerability-remediation

Reviews vulnerability policy violations for the chainloop project recorded in Chainloop and performs fixes in Dockerfiles or go.mod. Use when asked to fix vulnerabilities, review CVEs, or remediate security issues in chainloop.

chainloop-dev 551 53 Updated 3mo ago
GitHub

Install

npx skillscat add chainloop-dev/chainloop/vulnerability-remediation

Install via the SkillsCat registry.

SKILL.md

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 Aget_frameworks_compliance:

  • project_version_id: the UUID from Step 1
  • framework_ids: ["0ceef195-6900-4166-8407-77eb84954ed3"] (chainloop-best-practices)

Call Blist_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:

  1. Check the current atlas version in the comment at the top of the Dockerfile (e.g. # atlas version v1.1.0)
  2. 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']]"
  3. 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.
  4. 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>
  5. 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):

  1. Identify the affected module from the SARIF purls field (e.g. pkg:golang/github.com/foo/bar@v1.2.3)
  2. Update go.mod:
    go get github.com/foo/bar@<fixed-version>
    go mod tidy
  3. 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

  1. Check which branch you are on — do not create a new branch if one already exists:

    git branch --show-current
  2. 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>
  3. 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