Back to Checks
aws

ECR registry has automated image scanning enabled for all repositories

ecr_registry_scan_images_on_push_enabled
Service: ecrSeverity: medium
OfficialBuilt-inVerified
Categories:container-security
Resource Type:Other

Amazon ECR registries with repositories are evaluated for automated image scanning at the registry level -- scan on push or continuous scanning -- with scan rules that cover all repositories (no restrictive filters), for either basic or enhanced scanning. A registry whose rules specify only MANUAL scanning does not scan pushed images.

Risk

Without automated registry scanning, vulnerable images are pushed and deployed without timely detection, enabling exploitation of known CVEs (RCE, privilege escalation), supply chain compromise, and lateral movement - threatening workload integrity and data confidentiality. Repository filters narrow the same risk to whichever repositories they exclude.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks ecr_registry_scan_images_on_push_enabled

Recommendation

Enable registry-wide scan on push and ensure rules apply to all repositories (no filters). Prefer enhanced scanning for broader coverage, and pair with continuous scans when available. Integrate findings into CI/CD gates and alerts to enforce defense in depth and block promotion of risky images.

Remediation

CLI

aws ecr put-registry-scanning-configuration --rules 'scanFrequency=SCAN_ON_PUSH,repositoryFilters=[{filter=string,filterType=WILDCARD}]'

Terraform

resource "aws_ecr_registry_scanning_configuration" "<example_resource_name>" {
  scan_type = "ENHANCED"

  rule {
    scan_frequency = "SCAN_ON_PUSH"  # Ensures scan on push
    repository_filter {
      filter      = "*"               # Applies to all repositories
      filter_type = "WILDCARD"
    }
  }
}

Other

1Open the AWS Management Console and go to Amazon ECR
2In the left menu, click Account settings (or Settings), then find Registry scanning
3Click Edit
4Set Scanning type to Enhanced scanning
5Enable Scan on push
6Under Repository filters, set Filter type to WILDCARD and Filter to *
7Click Save

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ecr.ecr_client import ecr_client

# The two frequencies that scan an image without anyone asking. MANUAL is the third value
# GetRegistryScanningConfiguration can return, and it is the default a BASIC registry gets when
# scan on push is not specified, so it is the state this check exists to catch.
AUTOMATED_SCAN_FREQUENCIES = {"SCAN_ON_PUSH", "CONTINUOUS_SCAN"}


class ecr_registry_scan_images_on_push_enabled(Check):
    def execute(self) -> list[Check_Report_AWS]:
        """Execute the check against every ECR registry that holds repositories.

        Returns:
            A list of reports, one per in-use registry, PASS when its rules cover all
            repositories with a frequency in AUTOMATED_SCAN_FREQUENCIES.
        """
        findings = []
        for registry in ecr_client.registries.values():
            # We want to check the registry if it is in use, hence there are repositories
            if len(registry.repositories) != 0:
                report = Check_Report_AWS(metadata=self.metadata(), resource=registry)
                report.status = "FAIL"
                report.status_extended = f"ECR registry {registry.id} has {registry.scan_type} scanning without automated scanning enabled."
                if registry.rules:
                    # Read the frequency rather than inferring it from the presence of a rule. A rule
                    # always carries one -- scanFrequency is required on the shape -- and a MANUAL
                    # rule is a registry where nothing is scanned until someone runs a scan by hand.
                    frequencies = {
                        rule.scan_frequency
                        for rule in registry.rules
                        if rule.scan_frequency in AUTOMATED_SCAN_FREQUENCIES
                    }
                    if frequencies:
                        report.status = "PASS"
                        report.status_extended = f"ECR registry {registry.id} has {registry.scan_type} scanning with {self._describe(frequencies)} for all repositories."
                        filters = True
                        for rule in registry.rules:
                            if not rule.scan_filters or "'*'" in str(rule.scan_filters):
                                filters = False
                        if filters:
                            report.status = "FAIL"
                            report.status_extended = f"ECR registry {registry.id} has {registry.scan_type} scanning with {self._describe(frequencies)} but with repository filters."
                    else:
                        report.status_extended = f"ECR registry {registry.id} has {registry.scan_type} scanning set to manual only, so images are not scanned when they are pushed."

                findings.append(report)

        return findings

    @staticmethod
    def _describe(frequencies: set) -> str:
        """Name automated scan frequencies in a fixed order.

        Args:
            frequencies: The registry's configured frequencies, already narrowed to
                AUTOMATED_SCAN_FREQUENCIES.

        Returns:
            The frequencies in a fixed order, so the message does not vary between runs for
            the same registry.
        """
        wording = {
            "SCAN_ON_PUSH": "scan on push",
            "CONTINUOUS_SCAN": "continuous scanning",
        }
        return " and ".join(
            wording[f] for f in ("SCAN_ON_PUSH", "CONTINUOUS_SCAN") if f in frequencies
        )