Scan container images in CI
AlertaVuln scans a built container image for vulnerable OS packages and the application dependencies baked into its layers, tiers every finding RED / YELLOW / GREEN, and lands the results on the project’s Containers page. The natural place to run that is the pipeline that already builds the image.
From a runner that has just built your image, that is a single command:
av image scan "$IMAGE_REF" --project "$ALERTAVULN_PROJECT_ID"The scan reads the image with the runner’s own registry credentials, uploads the normalised findings and a CycloneDX inventory, and leaves the image itself on the runner. This guide wires that command into GitHub Actions and Azure DevOps, signing in with an organisation API key your platform injects from a secret.
How authentication works in CI
Section titled “How authentication works in CI”There is no interactive browser login in a pipeline. Instead the CLI reads an
organisation API key from the ALERTAVULN_API_KEY environment variable and
uses it as the request token for that one invocation. Your CI platform holds the
key as a secret and injects it into the job; the CLI never writes it to disk, so
it stays ephemeral on the runner.
Before you start
Section titled “Before you start”-
Create an organisation API key with ReadWrite scope. In the web app, open Settings and the API Keys panel (org-admin only). Uploading a scan writes to the project, so the key must be ReadWrite, not ReadOnly. The key looks like
av_live_followed by 64 hex characters and is shown once, so copy it immediately. -
Store the key as a secret in your CI platform (next section). Never commit it or print it in logs.
-
Find the project ID you want to scan into. Install the CLI locally and run
av project list, then copy the ID from the first column (it is also on the project’s page in the web app).
Store the API key as a secret
Section titled “Store the API key as a secret”Add a repository (or organisation) secret named ALERTAVULN_API_KEY
under Settings -> Secrets and variables -> Actions. Store the project ID
as a plain variable (it is not sensitive) named ALERTAVULN_PROJECT_ID.
Add a secret pipeline variable named ALERTAVULN_API_KEY (a variable
group backed by Azure Key Vault works well for sharing it across pipelines).
Store the project ID as an ordinary variable named ALERTAVULN_PROJECT_ID.
Add the pipeline
Section titled “Add the pipeline”The job does three things: build the image, install the CLI, and scan the image it just built. Because the scan reads the image locally, it must run after the build, and it uses the runner’s Docker credentials to reach any registry.
name: Scan container imageon: push: branches: [main]
jobs: image-scan: runs-on: ubuntu-latest env: # Injected from the repository/organisation secret; read by the CLI. ALERTAVULN_API_KEY: ${{ secrets.ALERTAVULN_API_KEY }} IMAGE_REF: acme/api:${{ github.sha }} steps: - uses: actions/checkout@v4
- name: Build the image run: docker build -t "$IMAGE_REF" .
- name: Install the AlertaVuln CLI run: | curl -fsSL https://get.alertavuln.com/cli/install.sh | sh echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Scan the image run: av image scan "$IMAGE_REF" --project "${{ vars.ALERTAVULN_PROJECT_ID }}" --fail-on redtrigger: branches: include: [main]
pool: vmImage: ubuntu-latest
variables: IMAGE_REF: acme/api:$(Build.SourceVersion)
steps: - checkout: self
- script: docker build -t "$(IMAGE_REF)" . displayName: Build the image
- script: | curl -fsSL https://get.alertavuln.com/cli/install.sh | sh echo "##vso[task.prependpath]$HOME/.local/bin" displayName: Install the AlertaVuln CLI
- script: av image scan "$(IMAGE_REF)" --project "$(ALERTAVULN_PROJECT_ID)" --fail-on red displayName: Scan the image env: # Secret variables are NOT auto-exposed to the environment - map it here. ALERTAVULN_API_KEY: $(ALERTAVULN_API_KEY)On the next push to main the job builds the image, installs the CLI,
authenticates with the injected key, and scans. --fail-on red makes the build
fail when the worst finding is RED, so a newly
vulnerable image blocks the pipeline. Each run prints a summary and the tiered
finding counts:
$ av image scan acme/api:8f3c1d2 --project "$ALERTAVULN_PROJECT_ID"Image: acme/api:8f3c1d2Digest: sha256:2b1c9f4e7a08...OS: debian 12SEVERITY COUNTRED 2YELLOW 14GREEN 7Uploaded to project. View on the Containers page.The scanner runs locally and is reported by its neutral capability label,
container-scanner. Only the findings and a CycloneDX inventory are uploaded -
never your registry credentials.
See the base-image advice
Section titled “See the base-image advice”Once an image is scanned, the project’s Containers page splits its findings
into base image layers and your layers, and shows up to three safer base
images - a newer patch tag, a slimmer variant, or the next major - each with a
concrete delta such as “-2 RED, -14 YELLOW”. When the project has a connected
repo, the advice also names the Dockerfile FROM line to change. Often the
fastest way to clear a batch of base-layer findings is to take the recommended
FROM change rather than to patch packages one by one.
Keep an image monitored (Enterprise)
Section titled “Keep an image monitored (Enterprise)”A CI scan is a point-in-time check. With continuous monitoring on (an Enterprise feature), AlertaVuln keeps re-checking a scanned image as new CVEs land - a nightly sweep plus an event-driven re-match whenever a fresh CVE names a package in the image - all from the stored inventory, with no image re-pull. New or reopened findings raise alerts through your configured notification channels. Turn it on per image from the Containers page (see continuous monitoring).
Verify it worked
Section titled “Verify it worked”List the project’s findings after a run, from the pipeline or your machine:
$ av image findings --project "$ALERTAVULN_PROJECT_ID" --severity redSEVERITY STATE CVE PACKAGE INSTALLED FIXED LAYERRED Open CVE-2025-1234 openssl 3.0.11 3.0.13 baseRED Open CVE-2025-5678 libxml2 2.9.14 2.9.15 baseThe same findings appear on the project’s Containers page, and any new or reopened RED / YELLOW finding raises an alert through whatever notification channels you have configured.
Keep the key safe
Section titled “Keep the key safe”- Use a dedicated ReadWrite key for CI, separate from any personal login, so you can rotate or revoke it without disrupting anyone else.
- Keep it in your platform’s secret store. Do not echo it, and prefer a Key Vault-backed variable group on Azure DevOps.
- If a key is exposed, revoke it in Settings -> API Keys and issue a new one.
See also
Section titled “See also”av image scanreference - every flag and input mode.- Container image scanning - what container scanning covers.
- Authentication - interactive login for local use.