Skip to content

:octocat: GitHub Action for Copacetic: Directly patch container image vulnerabilities

License

Notifications You must be signed in to change notification settings

project-copacetic/copa-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Copacetic Action

Marketplace

This action patches vulnerable containers using Copa. Copacetic Action is supported with Copa version 0.3.0 and later.

Inputs

Name Type Required Default Description
image String True Image reference to patch
image-report String True Trivy JSON vulnerability report of the image to patch
patched-tag String True Patched image tag
timeout String False 5m Timeout for copa patch
buildkit-version String False latest Buildkit version
copa-version String False latest Copa version
output String False Output filename (available using copa-action with copa v0.6.1 and later)
format String False openvex Output format (available using copa-action with copa v0.6.1 and later)
custom-socket String False Custom Docker socket address (available using copa-action with copa v0.6.1 and later)

Note

Features that are supported with new Copacetic releases will not neccessarily align with what is supported with Copa Action. For example, the output file feature was released in Copa v0.5.0, but is supported with Copa Action when using Copa version v0.6.1 and later.

Outputs

Name Type Description
patched-image String Image reference of the patched image

Ways to connect to Buildkit

Note

Custom Buildkit connection to patch local or private images is only available with Copa-Action versions 0.6.1 and later. For all earlier Copa-Action versions, Buildkit in a container is the default approach, and a version must be supplied as input.

Option 1: Connect to buildx instance (default)

By default, Copa Action creates its own Buildx instance to connect to for patching public and private images.

Option 2: Connect using defaults through a custom socket

To patch local images, copa is limited to using docker's built-in buildkit service, and must use the containerd image store feature. To enable this in your Github workflow, use ghaction-setup-docker's daemon-configuration to set "containerd-snapshotter": true.

Example:

    - name: Set up Docker
        uses: crazy-max/ghaction-setup-docker@v3
        with:
        daemon-config: |
            {
            "debug": true,
            "experimental": true,
                "features": {
                "containerd-snapshotter": true
                }
            }
    - name: Get socket path
        run: |
            url=$(docker context inspect | jq -r .[0].Endpoints.docker.Host)
            socket_path=$(echo "$url" | awk -F// '{print $2}')
            echo "$socket_path"
            echo "SOCKET=$socket_path" >> $GITHUB_ENV

Then, supply the resulting socket path ($SOCKET) as the input custom-socket for the Copa Action to connect to.

Note

Copa Action will load the image to the default docker context, not the "setup-docker-action" context.

Option 3: Buildkit in a container

To connect via buildkit in a container, provide the input buildkit-version. Copa Action will create a buildkit container with that version to connect to.

Note

This approach does not allow for patching of local or private images.

Refer to Copacetic documentation to learn more about connecting Copa to Buildkit.

Example usage

name: Patch vulnerable images
on:
# change these to your preferred event triggers
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
push:
branches:
- main
paths-ignore:
- '**.md'
workflow_dispatch:
jobs:
patch:
runs-on: ubuntu-latest
# used for pushing patched image to GHCR
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
# provide relevant list of images to scan on each run
images:
- "docker.io/library/alpine:3.18.4"
- "docker.io/openpolicyagent/opa:0.46.0"
- "docker.io/library/hello-world:latest"
steps:
# generate trivy report for fixable OS package vulnerabilities
- name: Generate Trivy Report
uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca # 0.16.1
with:
scan-type: "image"
format: "json"
output: "report.json"
ignore-unfixed: true
vuln-type: "os"
image-ref: ${{ matrix.images }}
# check whether there are any OS package vulnerabilities
- name: Check vulnerability count
id: vuln_count
run: |
report_file="report.json"
vuln_count=$(jq 'if .Results then [.Results[] | select(.Class=="os-pkgs" and .Vulnerabilities!=null) | .Vulnerabilities[]] | length else 0 end' "$report_file")
echo "vuln_count=$vuln_count" >> $GITHUB_OUTPUT
# copa action will only run if there are vulnerabilities
- name: Run Copa action
if: steps.vuln_count.outputs.vuln_count != '0'
id: copa
# using main for testing purposes
# use a tag (such as v1 or v1.0.1) at a bare minimum
# recommendation is to pin to a digest for security and stability
# and rely on dependabot for digest/version updates
uses: project-copacetic/copa-action@main
with:
image: ${{ matrix.images }}
image-report: "report.json"
patched-tag: "patched"
timeout: "5m" # optional, default is 5m
output: vex.json # optional
format: "openvex" # optional, default is openvex
# copa-version: "0.6.0" # optional, default is latest
# buildkit-version: "v0.12.4" # optional, default is latest
# custom-socket: "/var/run/buildkit/buildkitd.sock" # optional, used for custom socket address
# see https://github.com/docker/login-action#usage for other registries
- name: Login to GHCR
if: steps.copa.conclusion == 'success'
id: login
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push patched image
if: steps.login.conclusion == 'success'
run: |
# retag if needed
docker tag ${{ steps.copa.outputs.patched-image }} ghcr.io/project-copacetic/copa-action/test/${{ steps.copa.outputs.patched-image }}
docker push ghcr.io/project-copacetic/copa-action/test/${{ steps.copa.outputs.patched-image }}