Skip to main content

Image Vulnerability Scanning Using Amazon Ecr Image

More Info:

Scan images being deployed to Amazon EKS for vulnerabilities.

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CIS EKS
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. Inventory images used in the cluster (any machine with kubectl access)

    kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' \
    | tr ' ' '\n' | sort -u

    Save the list and identify which images are stored in Amazon ECR (*.dkr.ecr.*.amazonaws.com/*) vs. other registries.

  2. Verify ECR repositories have scan-on-push enabled (AWS CLI, any machine with AWS CLI and permissions)
    For each ECR image ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/REPO_NAME:TAG, run:

    aws ecr describe-repositories --repository-names REPO_NAME --region REGION \
    --query 'repositories[0].imageScanningConfiguration'

    If scanOnPush is false or missing, enable it:

    aws ecr put-image-scanning-configuration \
    --repository-name REPO_NAME \
    --image-scanning-configuration scanOnPush=true \
    --region REGION
  3. Ensure new repositories are created with scan-on-push (AWS CLI / IaC policy, any machine)
    For any new ECR repository you plan to use with EKS, create it with scanning enabled:

    aws ecr create-repository \
    --repository-name REPO_NAME \
    --image-scanning-configuration scanOnPush=true \
    --region REGION

    Update Terraform/CloudFormation/CD pipelines so repository creation always sets scanOnPush=true.

  4. Manually scan existing images lacking a recent scan (AWS Console or CLI)
    Console (per remediation): navigate to the repository → select the image → Scan.
    CLI alternative (per image digest):

    aws ecr start-image-scan \
    --repository-name REPO_NAME \
    --image-id imageTag=TAG \
    --region REGION

    Then retrieve findings:

    aws ecr describe-image-scan-findings \
    --repository-name REPO_NAME \
    --image-id imageTag=TAG \
    --region REGION
  5. Decide on policy for non‑ECR images (manual review)

    • Identify images from Docker Hub, other vendors, or private registries from step 1.
    • Choose and configure a third‑party scanner (e.g., integrated into your CI/CD) to scan those registries before push or deploy.
    • Ensure your deployment process rejects images with unscanned or high‑severity vulnerabilities according to your risk tolerance.
  6. Verify compliance for all in‑use images

    • For every ECR‑hosted image currently used in the cluster, confirm scanOnPush=true on its repository and that a scan has run (via describe-image-scan-findings).
    • For every non‑ECR image, document which scanner and pipeline stage covers it and ensure a current report exists.
Using kubectl

kubectl cannot configure image vulnerability scanning for Amazon ECR repositories or third‑party scanners; this must be set in the AWS account via the AWS console, CLI, or your IaC. Refer to the Manual Steps section for how to enable ECR scan-on-push and/or integrate a third-party image scanning solution.

Automation
#!/usr/bin/env bash
# Purpose: Report which container images used in the cluster are NOT stored in
# ECR repositories that have scanOnPush enabled.
# Runs on: Any machine with kubectl, aws CLI, and creds for the target cluster/account.

set -euo pipefail

# ---------- CONFIGURATION ----------
AWS_REGION="us-east-1" # set to the primary region where your ECR repos live
# ----------------------------------

echo "Discovering all images running in the cluster..."
ALL_IMAGES_RAW=$(
kubectl get pods --all-namespaces -o json |
jq -r '.items[]
| .spec.containers[]?.image,
.spec.initContainers[]?.image' |
sort -u
)

if [[ -z "${ALL_IMAGES_RAW}" ]]; then
echo "No images found in the cluster."
exit 0
fi

echo
echo "Unique images in cluster:"
printf '%s\n' "${ALL_IMAGES_RAW}"

echo
echo "Filtering for AWS ECR images..."
ECR_IMAGES=$(printf '%s\n' "${ALL_IMAGES_RAW}" | grep -E '\.ecr\.[^.]+\.amazonaws\.com/' || true)

NON_ECR_IMAGES=$(comm -23 <(printf '%s\n' "${ALL_IMAGES_RAW}" | sort) <(printf '%s\n' "${ECR_IMAGES}" | sort || true))

echo
echo "Non‑ECR images (require separate vulnerability‑scanning solution):"
if [[ -n "${NON_ECR_IMAGES}" ]]; then
printf '%s\n' "${NON_ECR_IMAGES}"
else
echo "None detected."
fi

if [[ -z "${ECR_IMAGES}" ]]; then
echo
echo "No ECR images detected. Ensure your non‑ECR registries have image vulnerability scanning enabled."
exit 0
fi

echo
echo "Checking scanOnPush setting for ECR repositories referenced by the cluster..."

# Normalize image names to extract registry, repository, and then repo-name for ECR
# ECR image formats (examples):
# 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:tag
# 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-namespace/my-repo@sha256:...
#
# We only care about the repository path relative to the ECR registry endpoint.

ECR_REPOS=$(
printf '%s\n' "${ECR_IMAGES}" |
sed -E 's|@sha256:.*$||' |
sed -E 's|:([^/:]+)$||' | \
awk -F'/' '
{
# drop the first field (the registry host)
$1=""; sub(/^ /, "", $0);
print $0
}' |
sort -u
)

if [[ -z "${ECR_REPOS}" ]]; then
echo "No ECR repositories could be parsed from image names."
exit 1
fi

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
if [[ -z "${ACCOUNT_ID}" ]]; then
echo "Unable to determine AWS account ID from current credentials."
exit 1
fi

echo
echo "AWS Account: ${ACCOUNT_ID}"
echo "AWS Region : ${AWS_REGION}"
echo
echo "ECR repositories referenced by cluster images:"
printf '%s\n' "${ECR_REPOS}"

echo
echo "Querying scanOnPush configuration for each referenced ECR repository..."
echo

# Header
printf "%-50s %-8s %-s\n" "ECR_REPOSITORY" "SCAN_ON_PUSH" "NOTES"

while IFS= read -r repo; do
# Some images may reference repos that don't exist in this account/region (e.g. cross-account)
if ! OUT=$(aws ecr describe-repositories \
--region "${AWS_REGION}" \
--repository-names "${repo}" 2>/dev/null); then
printf "%-50s %-8s %-s\n" "${repo}" "UNKNOWN" "Repository not found in ${ACCOUNT_ID}/${AWS_REGION} (cross-account? different region?)"
continue
fi

SCAN_ON_PUSH=$(echo "${OUT}" | jq -r '.repositories[0].imageScanningConfiguration.scanOnPush // "false"')
if [[ "${SCAN_ON_PUSH}" == "true" ]]; then
printf "%-50s %-8s %-s\n" "${repo}" "true" ""
else
printf "%-50s %-8s %-s\n" "${repo}" "false" "IMAGE SCANNING NOT ENABLED (scanOnPush=false)"
fi
done <<< "${ECR_REPOS}"

echo
echo "INTERPRETATION:"
echo " - Any row with SCAN_ON_PUSH = false indicates an ECR repository that does NOT automatically"
echo " scan images on push. This is a potential finding for CIS EKS 5.1.1."
echo " - Rows with SCAN_ON_PUSH = UNKNOWN mean the repository is not found in the current account/region."
echo " Review whether those images are:"
echo " * hosted in another AWS account or region, and"
echo " * covered by an alternate vulnerability-scanning solution."
echo " - Non‑ECR images listed earlier must be independently verified to be scanned by a third‑party provider."

What output indicates a problem

  • Under “Non‑ECR images”, any listed image requires confirmation that a third‑party vulnerability scanner is in place.
  • In the final table:
    • SCAN_ON_PUSH = false → ECR repo is not configured for automatic image scanning (non‑compliant unless compensated by another approved scanner).
    • SCAN_ON_PUSH = UNKNOWN → the script couldn’t find that repo in the current account/region; you must manually verify where it lives and whether scanning is enabled there.

Additional Reading: