$npx -y skills add opendatahub-io/ai-helpers --skill cve-fix-applyUse this skill to apply a CVE fix to a repository. Reads .cve-fix/examples.md for repo-specific guidance (branch naming, co-upgrades, files that change together). Supports Go version bumps, module updates, npm overrides, Python deps, and base image updates. Writes result to autof
| 1 | # Skill: CVE Fix Apply |
| 2 | |
| 3 | Apply the minimal set of changes to remediate a specific CVE in a cloned |
| 4 | repository. Uses repo-specific guidance from `.cve-fix/examples.md` when |
| 5 | available to match the project's conventions. |
| 6 | |
| 7 | ## Step 1: Load repo-specific fix guidance |
| 8 | |
| 9 | Read `.cve-fix/examples.md` if it exists. This file contains patterns learned |
| 10 | from previously merged CVE PRs in this repo: |
| 11 | |
| 12 | ```bash |
| 13 | cd "${REPO_DIR}" |
| 14 | if [ -d ".cve-fix" ]; then |
| 15 | for FILE in .cve-fix/*; do |
| 16 | cat "$FILE" |
| 17 | done |
| 18 | fi |
| 19 | ``` |
| 20 | |
| 21 | Extract and apply: |
| 22 | - **Branch naming convention** (e.g., `fix/cve-2024-xxxxx-package`) |
| 23 | - **Files that change together** (e.g., go.mod + Dockerfile + Dockerfile.konflux) |
| 24 | - **Co-upgrade patterns** (e.g., when bumping starlette, also update fastapi) |
| 25 | - **Don'ts** from previously rejected PRs |
| 26 | |
| 27 | ## Step 2: Create feature branch |
| 28 | |
| 29 | Find a branch name that doesn't conflict with existing local or remote branches: |
| 30 | |
| 31 | ```bash |
| 32 | ATTEMPT=1 |
| 33 | while true; do |
| 34 | FIX_BRANCH="fix/${CVE_ID,,}-${PACKAGE//\//-}-${TARGET_BRANCH//\//-}-attempt-${ATTEMPT}" |
| 35 | if ! git rev-parse --verify "refs/heads/${FIX_BRANCH}" >/dev/null 2>&1 && \ |
| 36 | ! git ls-remote --exit-code origin "${FIX_BRANCH}" >/dev/null 2>&1; then |
| 37 | break |
| 38 | fi |
| 39 | ATTEMPT=$((ATTEMPT + 1)) |
| 40 | if [ $ATTEMPT -gt 10 ]; then |
| 41 | echo "ERROR: Could not find free branch name after 10 attempts" >&2 |
| 42 | exit 1 |
| 43 | fi |
| 44 | done |
| 45 | git checkout -b "$FIX_BRANCH" |
| 46 | ``` |
| 47 | |
| 48 | ## Step 3: Analyze breaking changes |
| 49 | |
| 50 | Before applying fixes, check dependency compatibility: |
| 51 | - Research whether the fix version is compatible with current dependencies |
| 52 | - Identify required co-upgrades (e.g., bumping starlette requires fastapi update) |
| 53 | - Check for breaking API changes in the new version |
| 54 | - Review changelogs and migration guides when available |
| 55 | - Determine the minimal set of changes needed |
| 56 | |
| 57 | Document findings — they go into the PR body and commit message. |
| 58 | |
| 59 | ## Step 4: Apply fix (language-specific) |
| 60 | |
| 61 | **Go standard library CVEs:** |
| 62 | |
| 63 | ```bash |
| 64 | sed -i "s/^go ${OLD_GO_VERSION}/go ${FIXED_GO_VERSION}/" go.mod |
| 65 | |
| 66 | # Update toolchain directive if present (Go 1.21+) |
| 67 | if grep -q '^toolchain ' go.mod; then |
| 68 | sed -i "s/^toolchain go.*/toolchain go${FIXED_GO_VERSION}/" go.mod |
| 69 | fi |
| 70 | |
| 71 | for DF in Dockerfile Dockerfile.konflux; do |
| 72 | [ -f "$DF" ] && sed -i \ |
| 73 | "s/ARG GOLANG_VERSION=${OLD_GO_VERSION}/ARG GOLANG_VERSION=${FIXED_GO_VERSION}/" "$DF" |
| 74 | done |
| 75 | ``` |
| 76 | |
| 77 | **Go module dependencies:** |
| 78 | |
| 79 | ```bash |
| 80 | go get "${PACKAGE}@${FIXED_VERSION}" |
| 81 | go mod tidy |
| 82 | ``` |
| 83 | |
| 84 | **Node.js — determine fix strategy:** |
| 85 | |
| 86 | First, discover the fixed version: |
| 87 | |
| 88 | ```bash |
| 89 | npm view "${PACKAGE}" versions --json |
| 90 | ``` |
| 91 | |
| 92 | Then determine if the package is a direct or transitive dependency: |
| 93 | |
| 94 | ```bash |
| 95 | IS_DIRECT=$(jq -e --arg pkg "$PACKAGE" \ |
| 96 | '.dependencies[$pkg] // .devDependencies[$pkg]' package.json 2>/dev/null) |
| 97 | ``` |
| 98 | |
| 99 | For direct dependencies — use `npm install`: |
| 100 | |
| 101 | ```bash |
| 102 | npm install "${PACKAGE}@${FIXED_VERSION}" |
| 103 | ``` |
| 104 | |
| 105 | For transitive dependencies — use npm overrides (npm 8.3+): |
| 106 | |
| 107 | ```bash |
| 108 | jq --arg pkg "$PACKAGE" --arg ver ">=${FIXED_VERSION}" \ |
| 109 | '.overrides[$pkg] = $ver' package.json > package.json.tmp |
| 110 | mv package.json.tmp package.json |
| 111 | npm install |
| 112 | ``` |
| 113 | |
| 114 | Check for monorepo structure — if no `package.json` in root, check common |
| 115 | subdirectories (`frontend/`, `client/`, `app/`, `web/`). |
| 116 | |
| 117 | Do NOT blindly add a transitive dependency as a direct dependency. |
| 118 | |
| 119 | **Python:** |
| 120 | |
| 121 | Update the package version in whichever manifest file declares it: |
| 122 | |
| 123 | ```bash |
| 124 | # Check all Python manifest formats |
| 125 | for MANIFEST in requirements*.txt; do |
| 126 | [ -f "$MANIFEST" ] && sed -i "s/${PACKAGE}==.*/${PACKAGE}>=${FIXED_VERSION}/" "$MANIFEST" |
| 127 | done |
| 128 | |
| 129 | # Also check pyproject.toml and setup.py |
| 130 | if [ -f "pyproject.toml" ] && grep -Fq -- "${PACKAGE}" pyproject.toml; then |
| 131 | sed -i "s/${PACKAGE}==.*/${PACKAGE}>=${FIXED_VERSION}/" pyproject.toml |
| 132 | fi |
| 133 | if [ -f "setup.py" ] && grep -Fq -- "${PACKAGE}" setup.py; then |
| 134 | sed -i "s/${PACKAGE}==.*/${PACKAGE}>=${FIXED_VERSION}/" setup.py |
| 135 | fi |
| 136 | ``` |
| 137 | |
| 138 | For projects using `pip-compile`, update `requirements.in` and re-compile: |
| 139 | |
| 140 | ```bash |
| 141 | if [ -f "requirements.in" ]; then |
| 142 | sed -i "s/${PACKAGE}==.*/${PACKAGE}>=${FIXED_VERSION}/" requirements.in |
| 143 | pip-compile requirements.in |
| 144 | fi |
| 145 | ``` |
| 146 | |
| 147 | **Base image update:** |
| 148 | |
| 149 | ```bash |
| 150 | DOCKERFILE=$(ls Dockerfile.konflux Dockerfile.konflux.* Dockerfile 2>/dev/null | head -1) |
| 151 | LATEST_TAG=$(skopeo list-tags "docker://${IMAGE_REF}" 2>/dev/null | \ |
| 152 | jq -r '.Tags[]' | sort -V | tail -1) |
| 153 | if [ -n "$LATEST_TAG" ]; then |
| 154 | sed -i "s|${BASE_IMAGE}|${IMAGE_REF}:${LATEST_TAG}|g" "$DOCKERFILE" |
| 155 | fi |
| 156 | ``` |
| 157 | |
| 158 | ## Step 5: Discover and run tests |
| 159 | |
| 160 | Discover test commands by checking repo documentation and configuration in |
| 161 | this order: |
| 162 | |
| 163 | ```ba |