From odh-ai-helpers
Scans container images or the local host for RPM packages not signed with the Red Hat GPG key, outputting results as CSV. Use for compliance auditing and supply-chain provenance checks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/odh-ai-helpers:non-redhat-rpms <image_url_or_-f_input_file> [tag1 tag2 ...] | -l<image_url_or_-f_input_file> [tag1 tag2 ...] | -lThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Identify non-Red Hat-signed RPM packages in container images or on the local
Identify non-Red Hat-signed RPM packages in container images or on the local machine for compliance and supply-chain auditing.
If the user asks to scan "this machine", "the host", "localhost", or similar,
run the script with -l. No image URL, tags, or network access are needed:
./scripts/find_non_redhat_rpms.sh -l
For container image scans, follow the sections below.
When the user requests a scan of an image without specifying the full URL:
quay.iorhoai, then opendatahubquay.io/rhoai/<image> first. If the image is not found there, try
quay.io/opendatahub/<image>.registry.redhat.io) or repository
(e.g. opendatahub), use those instead of the defaults.The script automatically resolves component names: if a repository is not
found, it tries appending -rhel9 (e.g. odh-dashboard resolves to
odh-dashboard-rhel9). Pass the user's input as-is and let the script
handle the resolution.
For example, if the user says "scan odh-dashboard", run the script against
quay.io/rhoai/odh-dashboard. The script will find that the repo doesn't
exist and automatically try quay.io/rhoai/odh-dashboard-rhel9.
If quay.io/rhoai/ fails entirely, try quay.io/opendatahub/ as the
repository.
The script always displays the compressed image size before pulling. For
images exceeding 1 GB it prints a WARNING: line to stderr.
When the tag is known before running the script, pre-check the size to decide whether to ask the user first:
skopeo inspect --override-arch amd64 "docker://<image>:<tag>" | jq '[.LayersData[].Size] | add'
If the total exceeds 1 GB (1073741824 bytes), stop and ask the user for
confirmation in the chat before proceeding. Only run the script with -y
after the user confirms. Do not repeat the size in your response — the
script already displays it in its output.
When the user does not specify a tag, discover available tags before running the script so you can offer a choice:
skopeo list-tags "docker://<image>" | jq -r '.Tags[]' \
| grep -E '^rhoai-[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?$' | sort -V
If there are multiple release tags (stable and/or early access), present them to the user and let them pick which tag to scan. Show the highest stable tag and the highest EA tag as the recommended options, for example:
Available tags for odh-dashboard-rhel9:
- rhoai-3.4 (stable)
- rhoai-3.5-ea.2 (early access)
Which tag would you like to scan?
If the user does not have a preference, default to the most recent tag
-- typically the highest-version early access tag (e.g. rhoai-3.5-ea.2
over rhoai-3.4), since compliance scans are usually run against the
newest, not-yet-released builds. The script's discover_tags already
selects the highest version, preferring stable over EA only within the
same version. Then run the script with the chosen tag as a positional
argument.
When scanning multiple images, batch tag-discovery and size-check commands
into a single shell call using a loop (with & / wait for
parallelism). This avoids prompting the user to approve a separate custom
command for every image:
for img in img-a img-b img-c; do
(skopeo list-tags "docker://quay.io/rhoai/${img}" 2>/dev/null \
| jq -r '.Tags[]' \
| grep -E '^rhoai-[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?$' | sort -V \
| awk -v name="$img" '{print name": "$0}') &
done
wait
The same approach applies to size pre-checks — one shell call, one approval.
For the actual scan, use the script's built-in parallelism with -q
(quiet mode suppresses podman progress bars) and PARALLEL=N:
PARALLEL=4 ./scripts/find_non_redhat_rpms.sh -q -y -f images.input rhoai-3.5-ea.2
Each image is processed in its own subshell with isolated output files,
so results are clean and not interleaved. Always use -q with
PARALLEL to avoid garbled terminal output from concurrent podman pulls.
Always present scan results as a markdown table, never as plain-text sentences. Include every scanned image as a row, even when the result is "clean". Example:
| Image | Tag | Arch | Non-RH pkgs | Details |
|-------|-----|------|-------------|---------|
| odh-dashboard-rhel9 | rhoai-3.4 | amd64 | 0 | Clean |
| odh-vllm-rhel9 | rhoai-3.5-ea.2 | amd64 | 3 | pkg-a, pkg-b, pkg-c |
The script supports two modes:
rpm -qai inside the container to
extract package signing info, then filters out packages signed with the Red
Hat GPG key.-l): Runs rpm -qai directly on the host machine. No
container runtime or network access is required.In both modes the remaining non-Red Hat packages are emitted as CSV rows to stdout. Progress and diagnostics are printed to stderr, so the CSV output can be redirected or piped cleanly.
Run the script from this skill's directory:
./scripts/find_non_redhat_rpms.sh -h
Scan the local machine:
./scripts/find_non_redhat_rpms.sh -l > results.csv
Quick scan of a single image (amd64, latest tag):
./scripts/find_non_redhat_rpms.sh quay.io/rhoai/odh-vllm-rocm-rhel9 > results.csv
Scan specific release tags:
./scripts/find_non_redhat_rpms.sh quay.io/rhoai/odh-vllm-rocm-rhel9 rhoai-3.4 rhoai-3.5-ea.1 > results.csv
Scan all supported architectures:
ARCHS="amd64 arm64 s390x ppc64le" ./scripts/find_non_redhat_rpms.sh quay.io/rhoai/odh-vllm-rocm-rhel9 > results.csv
Full matrix -- all architectures and multiple tags:
ARCHS="amd64 arm64 s390x ppc64le" ./scripts/find_non_redhat_rpms.sh quay.io/rhoai/odh-vllm-rocm-rhel9 rhoai-3.4 rhoai-3.5-ea.1 > results.csv
Multiple images from a file with custom tags:
./scripts/find_non_redhat_rpms.sh -f images.input rhoai-3.4 rhoai-3.5-ea.1 > results.csv
Append to an existing CSV (suppress header with -H):
./scripts/find_non_redhat_rpms.sh -H quay.io/rhoai/odh-vllm-gaudi-rhel9 >> results.csv
Batch scan from input file with 4 parallel workers (quiet mode):
PARALLEL=4 ./scripts/find_non_redhat_rpms.sh -q -y -f images.input rhoai-3.5-ea.2 > results.csv
Run -h to see all options, environment variable overrides, and defaults.
One image URL per line (without tag). Lines starting with # and blank lines
are ignored.
CSV with header row:
tag,arch,image_name,image_ref,pkg_name,key_id
| Column | Description |
|---|---|
| tag | Release tag used (e.g. rhoai-3.4) |
| arch | CPU architecture (e.g. amd64) |
| image_name | Short image name (last path segment) |
| image_ref | Full image reference with digest |
| pkg_name | RPM package name |
| key_id | GPG key ID that signed the package, or (none) |
REDHAT_KEY matches the RHEL GPG key, not the Fedora signing key. This is
expected. Set REDHAT_KEY to the Fedora key if scanning a Fedora machine
for non-Fedora packages.gpg-pubkey entries with key ID (none) are RPM-internal placeholders,
not real third-party software. They appear in virtually every image.-l flag ignores ARCHS, tags, and all container-related options.
Do not combine -l with image URLs.-y to avoid hanging on a TTY
prompt.-l): rpmpodman, skopeo, jq, network access to the
container registry, and sufficient disk space for pulling images (cleaned
up after each tag)npx claudepluginhub opendatahub-io/skills-registry --plugin odh-ai-helpersScans container images for vulnerabilities using Trivy and Grype, enforces image signing with Cosign and Sigstore, and builds CI/CD pipelines to prevent deploying unscanned or unsigned images.
Scans container images with Trivy and Grype, enforces image signing with Cosign/Sigstore, and builds CI/CD pipelines that block unscanned or unsigned images.
Secures container registry images via Trivy/Grype vulnerability scanning, Cosign/Sigstore signing, access controls, and CI/CD pipelines blocking unscanned/unsigned deploys.