Image Scan #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Image Scan | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - litellm_internal_staging | |
| - litellm_oss_branch | |
| - "litellm_**" | |
| paths: | |
| - docker/Dockerfile.non_root | |
| - tests/proxy_migration_tests/test_offline_image_migration.py | |
| - uv.lock | |
| - ui/litellm-dashboard/package-lock.json | |
| - .github/workflows/image-scan.yml | |
| schedule: | |
| - cron: "41 6 * * *" | |
| workflow_dispatch: | |
| permissions: {} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| image-scan: | |
| name: image-scan | |
| runs-on: ubuntu-latest | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 | |
| with: | |
| persist-credentials: false | |
| - name: Download Grype v0.114.0 | |
| run: | | |
| curl -fsSL --retry 3 -o "$RUNNER_TEMP/grype.tar.gz" \ | |
| https://github.com/anchore/grype/releases/download/v0.114.0/grype_0.114.0_linux_amd64.tar.gz | |
| echo "edda0968d8827daab01d32b3cd7de192ae0915005e7bbfcfef9e68e79bc43343 $RUNNER_TEMP/grype.tar.gz" | sha256sum -c - | |
| tar xzf "$RUNNER_TEMP/grype.tar.gz" -C "$RUNNER_TEMP" grype | |
| chmod +x "$RUNNER_TEMP/grype" | |
| # Dockerfile.non_root is the rootless variant we ship. The other | |
| # Dockerfiles share the same wolfi base and apk set, so OS-layer coverage | |
| # is the same; matrix-scan if those variants ever diverge. | |
| - name: Build runtime image | |
| run: docker build -f docker/Dockerfile.non_root -t litellm-image-scan:${{ github.sha }} . | |
| # The prisma bake must migrate a fresh DB with no egress as an arbitrary | |
| # non-root uid (OpenShift restricted-v2 / air-gapped / readOnlyRootFilesystem). | |
| # `docker run` as the default uid with network hides a broken bake because | |
| # the migration entrypoint exits 0 even when it applied nothing; asserting | |
| # the schema was created is what catches it. | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: "3.12" | |
| - name: Verify offline migration as a non-root uid | |
| env: | |
| LITELLM_IMAGE: litellm-image-scan:${{ github.sha }} | |
| run: | | |
| python -m pip install "pytest==9.0.3" | |
| python -m pytest tests/proxy_migration_tests/test_offline_image_migration.py -v | |
| # Scans the whole shipped artifact: OS/apk plus every language package | |
| # baked into the image, including ones no lockfile declares (e.g. prisma's | |
| # vendored node engine) that osv-scan cannot see. osv-scan stays the fast | |
| # source-level gate; this is the customer's-eye-view backstop. Credential- | |
| # free OSS, run as a pinned, checksum-verified binary; no GitHub Action | |
| # dependency and no vendor SaaS callout. | |
| - name: Scan image for fixable HIGH/CRITICAL CVEs | |
| env: | |
| GRYPE_MATCH_PYTHON_USING_CPES: "true" | |
| run: | | |
| "$RUNNER_TEMP/grype" litellm-image-scan:${{ github.sha }} \ | |
| --only-fixed \ | |
| --fail-on high \ | |
| --output table |