> ## 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.

# Scanning Images with rad-image-scanner (CLI)

> Scan container images locally with rad-image-scanner — a Grype wrapper that enriches reports with how the image is currently deployed in your fleet.

`rad-image-scanner` is a container image vulnerability scanner. Without RAD credentials it behaves identically to [Grype](https://github.com/anchore/grype). With RAD credentials, it queries the RAD Security inventory for every configured account, compares severity counts against the image as it is *currently deployed* in your fleet, and writes an enrichment report with vulnerability count deltas, regression detection, and distro EOL warnings.

Source: [github.com/rad-security/image-scanner](https://github.com/rad-security/image-scanner). For CI usage see [Scanning Images in CI with the GitHub Action](/rad-security/platform/tutorials/image-scan-github-action).

## Installation

<Tabs>
  <Tab title="Homebrew">
    ```sh theme={null}
    brew install rad-security/tap/rad-image-scanner
    ```
  </Tab>

  <Tab title="Linux (curl + tar)">
    ```sh theme={null}
    VERSION=$(curl -fsSL https://api.github.com/repos/rad-security/image-scanner/releases/latest | grep -oE '"tag_name": "v[^"]+"' | cut -d'"' -f4 | sed 's/^v//')
    ARCH=$(uname -m); case "$ARCH" in x86_64) ARCH=amd64;; aarch64|arm64) ARCH=arm64;; esac
    curl -fsSL "https://github.com/rad-security/image-scanner/releases/download/v${VERSION}/rad-image-scanner_${VERSION}_linux_${ARCH}.tar.gz" \
      | sudo tar -xz -C /usr/local/bin rad-image-scanner
    rad-image-scanner --version
    ```

    For macOS, swap `linux` for `darwin` in the URL.
  </Tab>

  <Tab title="Docker">
    ```sh theme={null}
    docker run --rm public.ecr.aws/n8h5y2v5/rad-security/rad-image-scanner:latest <image>
    ```
  </Tab>

  <Tab title="From source">
    ```sh theme={null}
    go install github.com/rad-security/image-scanner@latest
    ```
  </Tab>
</Tabs>

## Pure passthrough mode (no RAD env)

If `RAD_ACCESS_KEY_ID` and `RAD_SECRET_KEY` are unset, `rad-image-scanner` is a transparent wrapper around `grype`. Every argument is forwarded, output is unchanged, exit code is `grype`'s.

```sh theme={null}
rad-image-scanner alpine:3.23 -o sarif --file alpine.sarif
```

## RAD-enriched mode

Set the credentials below and the scanner additionally queries the RAD Security inventory for every configured account, compares severity counts, and writes an enrichment report.

| Variable            | Required | Description                                       |
| ------------------- | -------- | ------------------------------------------------- |
| `RAD_ACCESS_KEY_ID` | yes      | Access key ID from RAD Security.                  |
| `RAD_SECRET_KEY`    | yes      | Secret matching the access key.                   |
| `RAD_ACCOUNT_IDS`   | yes      | Comma-separated list of RAD account IDs to query. |
| `RAD_API_URL`       | no       | Defaults to `https://api.rad.security`.           |

```sh theme={null}
export RAD_ACCESS_KEY_ID=...
export RAD_SECRET_KEY=...
export RAD_ACCOUNT_IDS=acct_1,acct_2

rad-image-scanner nginx:stable-alpine3.23 \
    -o sarif --file svc.sarif \
    --rad-annotate-sarif \
    --rad-fail-on-regression=critical \
    --rad-fail-on-eol
```

The terminal summary shows where the image runs today (clusters, namespaces, workloads) and a verdict (`improvement`, `same`, or `regression`) per deployed instance. The full structured report is written to a per-run JSON file (`rad-report-<image>-<YYYYMMDD-HHMMSS>.json` by default).

## RAD-specific flags

| Flag                                                        | Description                                                                                                                                       |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--rad-report PATH`                                         | Write the standalone RAD enrichment JSON. Defaults to `rad-report-<image>-<YYYYMMDD-HHMMSS>.json` so successive scans never overwrite each other. |
| `--rad-annotate-sarif`                                      | When Grype emits SARIF, inject the RAD report under `runs[].properties.rad`.                                                                      |
| `--rad-fail-on-regression critical\|high\|medium\|low\|any` | Exit non-zero if the new scan adds vulnerabilities at this severity or higher vs *any* deployed instance.                                         |
| `--rad-fail-on-eol`                                         | Exit non-zero if the scanned image is built on an end-of-life distro (detected by Grype).                                                         |
| `--rad-account-ids id1,id2`                                 | Override `RAD_ACCOUNT_IDS`.                                                                                                                       |
| `--rad-api-url URL`                                         | Override the RAD API base URL.                                                                                                                    |
| `--rad-image-name NAME`                                     | Force the image *name* used for RAD lookup (useful when parsing is ambiguous).                                                                    |
| `--rad-image-repo REPO/`                                    | Force the image *repo* used for RAD lookup.                                                                                                       |
| `--rad-grype-version VER`                                   | Pin a different Grype version at runtime.                                                                                                         |
| `--rad-grype-help`                                          | Print Grype's full, unmodified help and exit.                                                                                                     |
| `--rad-skip`                                                | Disable RAD enrichment even if env is set.                                                                                                        |

All flags not recognised as `--rad-*` are passed through to Grype unchanged.

## How matching works

For each scan target the scanner extracts `name` and `repo` from the image reference (e.g. `registry/foo/bar/baz:v1` → `repo=registry/foo/bar/`, `name=baz`) and queries:

```
GET /accounts/{id}/data/scanned_images
    ?filters_query=name:"<name>" AND repo:"<repo>"
```

across every configured account in parallel. All returned deployments are merged; each one becomes a row in the enrichment report. For every deployed image the scanner then queries the container inventory to aggregate running containers into a **placement** block (container count, clusters, namespaces, workloads).

## Behaviour when RAD is unreachable

If `RAD_ACCESS_KEY_ID` and `RAD_SECRET_KEY` are set but authentication fails or the inventory API is unreachable, the scanner exits non-zero. There is no silent fallback to pure-Grype mode — misconfigured CI should surface a loud failure rather than quietly drop the enrichment guarantee.

## Grype binary management

`rad-image-scanner` does not embed Grype. At runtime it:

1. Honours `$RAD_GRYPE_PATH` if set.
2. Looks for `grype` in `$PATH` and uses it if the version matches the pinned one.
3. Looks in `$XDG_CACHE_HOME/rad-image-scanner/grype-v<version>/grype`.
4. Downloads the official Grype release tarball from GitHub, verifies the SHA256 against the published checksum file, extracts the binary into the cache, and uses it.

`--rad-grype-version` overrides the pinned version.

## Next steps

<CardGroup cols={2}>
  <Card title="Run the scanner in CI" href="/rad-security/platform/tutorials/image-scan-github-action">
    Use the `rad-security/image-scan-action` GitHub Action to gate pull requests on regression and EOL.
  </Card>

  <Card title="Manage API keys" href="/rad-security/platform/tutorials/managing-api-keys">
    Generate the `RAD_ACCESS_KEY_ID` / `RAD_SECRET_KEY` pair used by the scanner.
  </Card>
</CardGroup>
