Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rad.security/llms.txt

Use this file to discover all available pages before exploring further.

The rad-security/image-scan-action action wraps rad-image-scanner for use in GitHub workflows. It scans an image (or a pre-built Syft SBOM), optionally enriches the report with currently-deployed inventory from RAD Security, and can fail the workflow on a severity threshold, a regression vs deployed instances, or an end-of-life base distro.

Minimal example — plain vulnerability scan

name: image-scan
on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: rad-security/image-scan-action@v1
        with:
          image: ghcr.io/${{ github.repository }}:${{ github.sha }}
          fail_on_severity: high
Without RAD credentials this is a transparent Grype scan: the workflow fails if Grype finds a high or critical vulnerability.

RAD-enriched example — gate on regression vs deployed images

name: image-scan
on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: rad-security/image-scan-action@v1
        with:
          image: ghcr.io/${{ github.repository }}:${{ github.sha }}
          format: sarif
          rad_account_ids: acct_1,acct_2
          rad_fail_on_regression: critical
          rad_fail_on_eol: "true"
        env:
          RAD_ACCESS_KEY_ID: ${{ secrets.RAD_ACCESS_KEY_ID }}
          RAD_SECRET_KEY: ${{ secrets.RAD_SECRET_KEY }}

      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: ${{ steps.scan.outputs.sarif }}
RAD_ACCESS_KEY_ID and RAD_SECRET_KEY are passed via the workflow’s env: block, not as inputs:. GitHub Actions inputs are visible in workflow logs; secrets in env: are masked.

Inputs

InputDefaultDescription
imageImage to scan (e.g. registry.example.com/foo/bar:v1). Required unless sbom is set.
sbomPath to a Syft JSON SBOM to scan instead of an image.
formattableOutput format passed to Grype: table, json, sarif, or cyclonedx.
fail_on_severityFail the workflow if any Grype finding at this severity or higher exists. Values: negligible, low, medium, high, critical.
ignore_cvesMultiline list of CVE IDs to ignore, one per line.
rad_account_idsComma-separated RAD account IDs to query. Required for RAD enrichment. Without this the action runs as plain Grype.
rad_fail_on_regressionFail the workflow if the scan adds vulnerabilities at this severity or higher vs any deployed instance. Values: critical, high, medium, low, any.
rad_fail_on_eolSet to "true" to fail the workflow if the scanned image is built on an end-of-life distro.
rad_api_urlhttps://api.rad.securityOverride the RAD API base URL.
rad_reportrad-report.jsonPath where the RAD enrichment JSON report is written.
rad_annotate_sarif"true"When format=sarif, inject the RAD report under runs[].properties.rad.

Outputs

OutputWhen setDescription
sarifformat: sarifPath to the SARIF report.
rad_reportRAD credentials configuredPath to the RAD enrichment JSON report.

Required secrets

For RAD-enriched scans, add the credential pair to your repository (or organisation) secrets:
SecretDescription
RAD_ACCESS_KEY_IDAccess key ID from RAD Security. See Managing API keys.
RAD_SECRET_KEYSecret matching the access key.

Common recipes

Upload SARIF to Code Scanning

- id: scan
  uses: rad-security/image-scan-action@v1
  with:
    image: ghcr.io/${{ github.repository }}:${{ github.sha }}
    format: sarif

- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: ${{ steps.scan.outputs.sarif }}
The Code Scanning UI then shows each finding as an alert tied to the image layer.

Ignore noisy CVEs

- uses: rad-security/image-scan-action@v1
  with:
    image: ghcr.io/${{ github.repository }}:${{ github.sha }}
    fail_on_severity: high
    ignore_cves: |
      CVE-2024-12345
      CVE-2024-67890

Scan a pre-built SBOM instead of an image

Useful when you already build a Syft SBOM earlier in the pipeline and want to avoid re-pulling the image.
- uses: anchore/sbom-action@v0
  with:
    image: ghcr.io/${{ github.repository }}:${{ github.sha }}
    format: syft-json
    output-file: image.sbom.json

- uses: rad-security/image-scan-action@v1
  with:
    sbom: image.sbom.json
    fail_on_severity: high

Matrix across multiple images

strategy:
  matrix:
    image:
      - ghcr.io/${{ github.repository }}/api:${{ github.sha }}
      - ghcr.io/${{ github.repository }}/worker:${{ github.sha }}
steps:
  - uses: rad-security/image-scan-action@v1
    with:
      image: ${{ matrix.image }}
      rad_account_ids: ${{ vars.RAD_ACCOUNT_IDS }}
      rad_fail_on_regression: critical
    env:
      RAD_ACCESS_KEY_ID: ${{ secrets.RAD_ACCESS_KEY_ID }}
      RAD_SECRET_KEY: ${{ secrets.RAD_SECRET_KEY }}

How the action behaves on failure

SituationOutcome
Grype finds a vulnerability ≥ fail_on_severityWorkflow fails.
RAD scan adds vulnerabilities ≥ rad_fail_on_regression vs deployedWorkflow fails.
rad_fail_on_eol: "true" and base distro is EOLWorkflow fails.
RAD credentials set but auth or API unreachableWorkflow fails. No silent fallback to pure-Grype.
Neither image nor sbom providedWorkflow fails with input error.

Next steps

Use the CLI locally

Run the same scanner outside CI to reproduce findings or iterate on a fix.

Manage API keys

Generate the RAD_ACCESS_KEY_ID / RAD_SECRET_KEY pair used by the action.