Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions .github/actions/trivy-scan-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: 'Trivy Vulnerability Scanner'
description: |
Run [Trivy](https://trivy.dev) vulnerability scanner on container images or filesystems.
Features
- Supports both container image and filesystem scanning
- Configurable Trivy version
- Customizable scan parameters (scanners, timeout, exit codes)
- Generates markdown reports
- Automatically adds reports to GitHub job summary
Requirements
- Podman must be installed and running (for image scans)
- The Trivy report template must exist at the specified path
- For image scans, the image must be available in the local Podman storage
inputs:
# https://trivy.dev/docs/latest/guide/target/container_image/#vulnerabilities
scan-type:
description: 'Type of scan to perform: "image" or "fs" (filesystem)'
required: true
scan-target:
description: 'Target to scan (image name or filesystem path)'
required: true
trivy-version:
description: 'Version of Trivy to use'
required: false
default: '0.68.2'
podman-socket:
description: 'Path to Podman socket (required for image scans)'
required: false
default: '/var/run/podman/podman.sock'
workspace-path:
description: 'Workspace path for filesystem scans'
required: false
default: ${{ github.workspace }}
report-template:
description: 'Path to Trivy report template'
required: false
default: 'ci/trivy-markdown.tpl'
scanners:
description: 'Comma-separated list of scanners to use'
required: false
default: 'vuln'
ignore-unfixed:
description: 'Ignore unfixed vulnerabilities'
required: false
default: 'true'
timeout:
description: 'Scan timeout'
required: false
default: '30m'
exit-code:
description: 'Exit code when vulnerabilities are found'
required: false
default: '0'

outputs:
report-file:
description: 'Path to the generated report file'
value: ${{ steps.scan.outputs.report-file }}

runs:
using: 'composite'
steps:
- name: Setup report directory
id: setup
shell: bash
run: |
REPORT_FOLDER=${{ inputs.workspace-path }}/trivy-report
REPORT_FILE=trivy-report.md
REPORT_TEMPLATE=$(basename ${{ inputs.report-template }})
mkdir -p $REPORT_FOLDER
cp ${{ inputs.report-template }} $REPORT_FOLDER/
echo "report-folder=$REPORT_FOLDER" >> $GITHUB_OUTPUT
echo "report-file=$REPORT_FILE" >> $GITHUB_OUTPUT
echo "report-template=$REPORT_TEMPLATE" >> $GITHUB_OUTPUT
- name: Run Trivy vulnerability scanner
id: scan
shell: bash
run: |
REPORT_FOLDER=${{ steps.setup.outputs.report-folder }}
REPORT_FILE=${{ steps.setup.outputs.report-file }}
REPORT_TEMPLATE=${{ steps.setup.outputs.report-template }}
SCAN_TARGET=${{ inputs.scan-target }}
SCAN_TYPE=${{ inputs.scan-type }}
echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"
# Configure scan arguments based on type
if [[ "$SCAN_TYPE" == "image" ]]; then
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
PODMAN_ARGS="-v ${{ inputs.podman-socket }}:/var/run/podman/podman.sock"
elif [[ "$SCAN_TYPE" == "fs" ]]; then
WORKSPACE_FOLDER="/workspace"
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
PODMAN_ARGS="-v ${{ inputs.workspace-path }}:$WORKSPACE_FOLDER"
else
echo "Error: Invalid scan type '$SCAN_TYPE'. Must be 'image' or 'fs'"
exit 1
fi
# Run Trivy scan in container
podman run --rm \
$PODMAN_ARGS \
-v ${REPORT_FOLDER}:/report \
docker.io/aquasec/trivy:${{ inputs.trivy-version }} \
$SCAN_TYPE \
$SCAN_ARGS \
--scanners ${{ inputs.scanners }} \
${{ inputs.ignore-unfixed == 'true' && '--ignore-unfixed' || '' }} \
--exit-code ${{ inputs.exit-code }} \
--timeout ${{ inputs.timeout }} \
--format template --template "@/report/$REPORT_TEMPLATE" \
-o /report/$REPORT_FILE \
$SCAN_TARGET
echo "report-file=$REPORT_FOLDER/$REPORT_FILE" >> $GITHUB_OUTPUT
- name: Add report to job summary
shell: bash
run: |
REPORT_FILE=${{ steps.scan.outputs.report-file }}
if [[ -f "$REPORT_FILE" ]]; then
cat $REPORT_FILE >> $GITHUB_STEP_SUMMARY
else
echo "Warning: Report file not found at $REPORT_FILE"
fi
44 changes: 8 additions & 36 deletions .github/workflows/build-notebooks-TEMPLATE.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ jobs:
IMAGE_REGISTRY: "ghcr.io/${{ github.repository }}/workbench-images"
# GitHub image registry used for storing $(CONTAINER_ENGINE)'s cache
CACHE: "ghcr.io/${{ github.repository }}/workbench-images/build-cache"
TRIVY_VERSION: 0.64.1
# https://github.com/aquasecurity/trivy
TRIVY_VERSION: 0.68.2
# Targets (and their folder) that should be scanned using FS instead of IMAGE scan due to resource constraints
TRIVY_SCAN_FS_JSON: '{}'
# Makefile variables
Expand Down Expand Up @@ -362,41 +363,12 @@ jobs:

- name: Run Trivy vulnerability scanner
if: ${{ steps.resolve-target.outputs.target }}
run: |
REPORT_FOLDER=${{ github.workspace }}/report
REPORT_FILE=trivy-report.md
REPORT_TEMPLATE=trivy-markdown.tpl

mkdir -p $REPORT_FOLDER
cp ci/$REPORT_TEMPLATE $REPORT_FOLDER

SCAN_TARGET=${{ steps.resolve-target.outputs.target }}
SCAN_TYPE=${{ steps.resolve-target.outputs.type }}
echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"

if [[ "$SCAN_TYPE" == "image" ]]; then
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
PODMAN_ARGS="-v ${PODMAN_SOCK}:/var/run/podman/podman.sock"
elif [[ "$SCAN_TYPE" == "fs" ]]; then
WORKSPACE_FOLDER="/workspace"
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
PODMAN_ARGS="-v ${{ github.workspace }}:$WORKSPACE_FOLDER"
fi

# have trivy access podman socket,
# https://github.com/aquasecurity/trivy/issues/580#issuecomment-666423279
podman run --rm \
$PODMAN_ARGS \
-v ${REPORT_FOLDER}:/report \
docker.io/aquasec/trivy:$TRIVY_VERSION \
$SCAN_TYPE \
$SCAN_ARGS \
--scanners vuln --ignore-unfixed \
--exit-code 0 --timeout 30m \
--format template --template "@/report/$REPORT_TEMPLATE" -o /report/$REPORT_FILE \
$SCAN_TARGET

cat $REPORT_FOLDER/$REPORT_FILE >> $GITHUB_STEP_SUMMARY
uses: ./.github/actions/trivy-scan-action
with:
scan-type: ${{ steps.resolve-target.outputs.type }}
scan-target: ${{ steps.resolve-target.outputs.target }}
trivy-version: ${{ env.TRIVY_VERSION }}
podman-socket: /var/run/podman/podman.sock

# endregion

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

# https://github.com/astral-sh/setup-uv
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "latest"
activate-environment: false
Expand All @@ -32,7 +32,7 @@ jobs:
- run: find . -name pyproject.toml -execdir uv lock \;

- name: Trivy scan
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # 0.32.0
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
with:
scan-type: 'fs'
format: 'sarif'
Expand Down
68 changes: 68 additions & 0 deletions .github/workflows/test-trivy-scan-action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
name: Test Trivy Scan Action
"on":
workflow_dispatch:
pull_request:
paths:
- '.github/actions/trivy-scan-action/**'
- '.github/workflows/test-trivy-scan-action.yaml'
- 'ci/trivy-markdown.tpl'
push:
paths:
- '.github/actions/trivy-scan-action/**'
- '.github/workflows/test-trivy-scan-action.yaml'
- 'ci/trivy-markdown.tpl'

jobs:
test-scan-type-image:
name: Test Image Scan
runs-on: ubuntu-24.04
env:
TEST_IMAGE: docker.io/library/alpine:latest
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Install and configure Podman
run: |
sudo apt-get update
sudo apt-get install -y podman
# Start podman socket for rootful podman
sudo systemctl enable --now podman.socket
sudo systemctl status podman.socket
# Verify socket is accessible
ls -la /var/run/podman/podman.sock || true
- name: Pull test image
run: |
sudo podman pull ${{ env.TEST_IMAGE }}
sudo podman images
- name: Test Trivy scan on container image
uses: ./.github/actions/trivy-scan-action
with:
scan-type: image
scan-target: ${{ env.TEST_IMAGE }}
podman-socket: /var/run/podman/podman.sock

test-scan-type-fs:
name: Test Multiple Targets
runs-on: ubuntu-24.04
strategy:
matrix:
target:
- jupyter/minimal/ubi9-python-3.12
- jupyter/datascience/ubi9-python-3.12
- codeserver/ubi9-python-3.12
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Test Trivy scan on ${{ matrix.target }}
uses: ./.github/actions/trivy-scan-action
with:
scan-type: fs
scan-target: ${{ github.workspace }}
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
repos:
# https://docs.astral.sh/uv/guides/integration/pre-commit/
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.9.13
rev: 0.9.18
hooks:
- id: uv-lock
# https://github.com/astral-sh/ruff-pre-commit
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.6
rev: v0.14.10
hooks:
- id: ruff
types_or: [python, pyi]
Expand Down
40 changes: 20 additions & 20 deletions manifests/base/commit-latest.env
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
odh-pipeline-runtime-datascience-cpu-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-minimal-cpu-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-pytorch-cuda-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-pytorch-llmcompressor-cuda-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-pytorch-rocm-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-tensorflow-cuda-py312-ubi9-commit-n=d164e58
odh-pipeline-runtime-tensorflow-rocm-py312-ubi9-commit-n=d164e58
odh-workbench-codeserver-datascience-cpu-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-datascience-cpu-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-minimal-cpu-py312-ubi9-commit-n=d164e58
odh-workbench-jupyter-minimal-cuda-py312-ubi9-commit-n=d164e58
odh-workbench-jupyter-minimal-rocm-py312-ubi9-commit-n=df7f474
odh-workbench-jupyter-pytorch-cuda-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-pytorch-llmcompressor-cuda-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-pytorch-rocm-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-tensorflow-cuda-py312-ubi9-commit-n=89f9356
odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-commit-n=df7f474
odh-workbench-jupyter-trustyai-cpu-py312-ubi9-commit-n=d164e58
odh-workbench-rstudio-minimal-cpu-py312-c9s-commit-n=388c84c
odh-workbench-rstudio-minimal-cuda-py312-c9s-commit-n=388c84c
odh-pipeline-runtime-datascience-cpu-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-minimal-cpu-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-pytorch-cuda-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-pytorch-llmcompressor-cuda-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-pytorch-rocm-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-tensorflow-cuda-py312-ubi9-commit-n=ac7d523
odh-pipeline-runtime-tensorflow-rocm-py312-ubi9-commit-n=ac7d523
odh-workbench-codeserver-datascience-cpu-py312-ubi9-commit-n=ac7d523
odh-workbench-jupyter-datascience-cpu-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-minimal-cpu-py312-ubi9-commit-n=ac7d523
odh-workbench-jupyter-minimal-cuda-py312-ubi9-commit-n=ac7d523
odh-workbench-jupyter-minimal-rocm-py312-ubi9-commit-n=ac7d523
odh-workbench-jupyter-pytorch-cuda-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-pytorch-llmcompressor-cuda-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-pytorch-rocm-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-tensorflow-cuda-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-commit-n=79b82c0
odh-workbench-jupyter-trustyai-cpu-py312-ubi9-commit-n=79b82c0
odh-workbench-rstudio-minimal-cpu-py312-c9s-commit-n=ac7d523
odh-workbench-rstudio-minimal-cuda-py312-c9s-commit-n=ac7d523
Loading