Skip to content
Merged
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
90 changes: 90 additions & 0 deletions .github/workflows/scan.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: Scan

on:
workflow_dispatch:
schedule:
# A CVE disclosed after an image is published only surfaces on a re-scan,
# so sweep every published image daily.
- cron: "17 6 * * *"

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

permissions:
contents: read

jobs:
prepare:
runs-on: ubuntu-latest
outputs:
scan: ${{ steps.matrix.outputs.scan }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Generate matrix
id: matrix
run: |
set -euo pipefail

scan="[]"
for metadata in images/*/metadata.yaml; do
image="$(basename "$(dirname "${metadata}")")"
version="$(yq '.version' "${metadata}")"
while read -r platform; do
case "${platform}" in
linux/amd64) runner="ubuntu-latest" ;;
linux/arm64) runner="ubuntu-24.04-arm" ;;
*) echo "unsupported platform: ${platform}" >&2; exit 1 ;;
esac
scan="$(jq -c \
--arg image "${image}" --arg version "${version}" \
--arg slug "${platform//\//-}" --arg runner "${runner}" \
'. + [{image: $image, version: $version, slug: $slug, runner: $runner}]' \
<<<"${scan}")"
done < <(yq '.platforms[]' "${metadata}")
done

echo "scan=${scan}" >>"${GITHUB_OUTPUT}"

scan:
name: scan (${{ matrix.image }}, ${{ matrix.slug }})
needs: prepare
if: ${{ needs.prepare.outputs.scan != '[]' }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: read
security-events: write
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.scan) }}
steps:
- name: Login to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Trivy resolves the manifest list to the runner's own architecture, so
# each platform is scanned by the native runner that built it.
- name: Scan published image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}:${{ matrix.version }}
scanners: vuln
severity: HIGH,CRITICAL
limit-severities-for-sarif: true
format: sarif
output: trivy.sarif
hide-progress: true

- name: Upload SARIF
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
with:
sarif_file: trivy.sarif
category: trivy-${{ matrix.image }}-${{ matrix.slug }}
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ container build -t <name>:local -f images/<name>/Dockerfile images/<name>
```

CI (`.github/workflows/build.yaml`) builds changed images on native amd64/arm64 runners, merges digests into a manifest list, and attaches SBOM + provenance attestations. Third-party actions are pinned to commit SHAs — keep it that way when editing workflows.

`.github/workflows/scan.yaml` re-scans every published image daily with Trivy and reports HIGH/CRITICAL CVEs to GitHub code scanning. It reports and does not gate: most findings are in vendored upstream artefacts this repo cannot patch. It reads the `version` from each `metadata.yaml`, so that field must always name a tag that is actually published.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ when this repo rebuilds the same upstream version; the rolling `X.Y`, `X`, and
- No docker CLI, except CI-runner images that build against an injected dind sidecar
- Base images pinned by digest, tool versions pinned and updated by Renovate
- SBOM and SLSA provenance attestations attached to every image
- Every published image re-scanned daily for HIGH/CRITICAL CVEs, reported to GitHub code scanning

### claude-code

Expand Down Expand Up @@ -97,6 +98,10 @@ CI builds and tags whatever version the metadata declares — bump it in the sam

Trigger a manual build of any (or every) image via *Actions → Build → Run workflow*.

`.github/workflows/scan.yaml` runs daily and scans every published image, one job per image per platform on its native runner, uploading Trivy results to GitHub code scanning. A CVE disclosed after an image ships only surfaces on a re-scan, so this — not the build — is what catches them.

The scan reports rather than gates. Almost everything it finds lives in vendored upstream artefacts (Go binaries, the runner's .NET runtime, npm's own bundled dependencies) where a patched upstream module exists but this repo only consumes a release build, so it cannot act on the fix until upstream rebuilds. Gating merges on that would block PRs on work the repo cannot do. Treat the alerts as a queue: the ones worth acting on are the OS packages a base-image bump fixes, and language deps this repo installs directly.

## Local development

Build with [Apple container](https://github.com/apple/container) (or any BuildKit-compatible builder):
Expand Down
7 changes: 6 additions & 1 deletion images/infisical-mcp/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ FROM node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432

# renovate: datasource=npm depName=@infisical/mcp
ARG INFISICAL_MCP_VERSION=0.0.23
# The node base image ships an older bundled npm whose own vendored deps carry
# known CVEs; upgrading npm itself is the only way to move them.
# renovate: datasource=npm depName=npm
ARG NPM_VERSION=12.0.1

RUN npm install -g "@infisical/mcp@${INFISICAL_MCP_VERSION}" \
RUN npm install -g "npm@${NPM_VERSION}" \
&& npm install -g "@infisical/mcp@${INFISICAL_MCP_VERSION}" \
&& npm cache clean --force \
&& node --check /usr/local/lib/node_modules/@infisical/mcp/dist/index.js

Expand Down
8 changes: 6 additions & 2 deletions images/infisical-mcp/metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
name: infisical-mcp
description: Infisical MCP server (secrets management over MCP)
# renovate: datasource=npm depName=@infisical/mcp
version: 0.0.23
# <upstream mcp version>-<revision>. Bump the revision whenever this image's
# contents change without INFISICAL_MCP_VERSION moving. Renovate tracks upstream
# on INFISICAL_MCP_VERSION in the Dockerfile — deliberately not annotated here,
# since a -N suffix is a semver pre-release and would be "upgraded" straight
# back to the bare release.
version: 0.0.23-1
platforms:
- linux/amd64
- linux/arm64
Expand Down
9 changes: 8 additions & 1 deletion images/sandbox-agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ FROM ubuntu:24.04@sha256:4fbb8e6a8395de5a7550b33509421a2bafbc0aab6c06ba2cef9ebff

# renovate: datasource=node-version depName=node
ARG NODE_VERSION=24.18.0
# Node ships an older bundled npm whose own vendored deps carry known CVEs;
# upgrading npm itself is the only way to move them.
# renovate: datasource=npm depName=npm
ARG NPM_VERSION=12.0.1
# renovate: datasource=github-releases depName=cli/cli
ARG GH_VERSION=2.96.0
# renovate: datasource=github-releases depName=astral-sh/uv
Expand Down Expand Up @@ -36,7 +40,10 @@ RUN apt-get update \
RUN NODE_ARCH="$(case "${TARGETARCH}" in amd64) echo x64 ;; *) echo "${TARGETARCH}" ;; esac)" \
&& curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" \
| tar -xJ -C /usr/local --strip-components=1 --no-same-owner \
&& node --version
&& npm install -g "npm@${NPM_VERSION}" \
&& npm cache clean --force \
&& node --version \
&& npm --version

RUN curl -fsSL "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz" \
| tar -xz -C /usr/local/bin --strip-components=2 --no-same-owner "gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh" \
Expand Down
2 changes: 1 addition & 1 deletion images/sandbox-agent/metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: sandbox-agent
description: Rootless base image for sandboxed coding agents
version: 1.0.0
version: 1.0.1
platforms:
- linux/amd64
- linux/arm64
Expand Down