Amazon Inspector is AWS's managed vulnerability scanner. It finds EC2 instances, container images in Amazon ECR and Lambda functions in an account, works out what software each one contains, and compares that inventory against vulnerability advisories. Each match becomes a finding with a severity, an environment-adjusted score and, when one exists, the version that fixes it. It also reports EC2 network exposure. It does not watch for intrusions, which is GuardDuty's job, and it does not patch anything.

The hard part is not turning it on. It is getting full coverage, then turning thousands of findings into a short list that someone will fix. This article explains how each scan type collects inventory, what a finding contains, how to enable Inspector across an organization, how to route and suppress findings, how to scan images in CI before they reach a registry, a worked triage example, failure modes and a checklist. Details were checked against the Amazon Inspector user guide and CLI reference on 2026-10-04.

How every scan works

Every scan type follows the same three steps. Inspector collects a software inventory for a resource: packages and versions, from operating system package databases and language manifests. It matches that inventory against its vulnerability data and produces package-vulnerability findings. For EC2 it separately analyses network paths to report reachability findings. Scanning is continuous, not scheduled. Inspector rescans when a resource changes, for example a new instance, a new package or a new image push, and when a newly published CVE matches inventory it already holds.

That last trigger is the important one. A container image that was clean on Monday can have a critical finding on Thursday without anyone touching it, because the advisory arrived on Thursday. Findings close automatically when Inspector sees the fix, such as the package upgraded or the image no longer in scope. Your process therefore has to cope with findings that open and close on their own.

Amazon Inspector: collect inventory, match it against advisories, emit findingsEC2 via SSM agentagent-basedEC2 via EBS snapshotagentlessECR imagesenhanced scanningLambda functionsstandard + codeAmazon Inspectorper account, per Regioninventory + reachabilitymatched to CVE dataFindingsscore, status, fixEventBridgeSecurity HubCSPMSuppressionrulesSBOM exportto S3Rescans are event-driven: new instance, new package, new image push, or a new CVE that matches existing inventory.A delegated administrator account aggregates findings for every member account in the organization.
How Inspector collects inventory from four resource types, matches it against vulnerability data and hands findings to EventBridge, Security Hub CSPM, suppression rules and SBOM export.

EC2: agent-based, agentless and hybrid

EC2 has two ways to collect inventory. Agent-based scanning uses AWS Systems Manager. The instance must be an SSM managed instance in the same account, which means the SSM Agent is running and has an instance profile with permissions such as the AmazonSSMManagedInstanceCore policy. Inspector creates SSM associations in your account with names ending -do-not-delete, such as InspectorInventoryCollection-do-not-delete. If they are deleted, it recreates them at the next interval. Agent-based scans rescan on launch, on software install and on new CVEs. On Linux they add deep inspection of language packages in default and configured paths. AWS now also offers an Enhanced EC2 Scanning upgrade based on a VM Scanner, and recommends it for more consistent results across operating systems.

Agentless scanning creates EBS snapshots of an instance's volumes, tags them InspectorScan, reads them through EBS direct APIs and deletes them afterwards. It covers instances that are not SSM managed, or whose inventory is stale, provided they are EBS-backed with ext3, ext4 or xfs file systems, have fewer than 8 attached volumes, and total 1,200 GB or less. Agentless scans run every 24 hours, so a CVE published at 09:00 may not appear for an unmanaged instance until the next daily pass. Agentless scans look at all paths for language packages, agent-based scans only at configured ones. The same instance can therefore show different findings depending on which method scanned it.

Hybrid mode uses agent-based scanning where SSM is available and agentless scanning elsewhere. The user guide is inconsistent about which mode a newly activated account starts in, so read the EC2 scanning settings page rather than assuming. Separately, network reachability analysis runs every 12 hours. To exclude an instance, tag it with the InspectorEc2Exclusion key. The key is case-insensitive and excluded instances are not charged.

Container images in ECR

Activating ECR scanning switches the private registry from ECR's basic scanning to enhanced scanning, which Inspector performs and bills. Enhanced scanning covers operating system and language packages. Each repository is set to scan on push only or to scan continuously. With on-push, an image is scanned once and never re-evaluated against new CVEs. With continuous, it is rescanned when a matching CVE is published. Inspector scans only images whose ECR status is ACTIVE. When an image is archived its findings are closed, then deleted three days later.

Continuous monitoring is bounded in time. For accounts created on or after May 16, 2025, the documented default keeps monitoring an image while it was pushed within 14 days, last used within 14 days, or is inside the configured re-scan duration. Older accounts defaulted to 90 days since push or pull. An image deployed six months ago that still runs in production can drop out of monitoring unless the last-in-use signal keeps it in. Inspector maps images to running ECS tasks and EKS pods, including on Fargate, and exposes ecrImageInUseCount and ecrImageLastInUseAt as filters. That mapping is the most useful prioritisation signal for containers: a critical CVE in an image nobody runs can wait. One gap to know: the Docker manifest-list media type is not supported, so multi-architecture images need checking.

Lambda functions and code

Lambda standard scanning scans functions and layers for vulnerable dependencies when they are deployed or updated, and rescans when new CVEs arrive. Lambda code scanning is an optional extra layer that analyses the function code itself and produces code-vulnerability findings. Enabling it also enables standard scanning. A separate Code Security feature scans first-party code, third-party dependencies and infrastructure as code in connected source repositories, using the Amazon Q Developer scanning engine. Treat that as a source-repository tool rather than a runtime one.

Reading a finding

Findings arrive in three types: PACKAGE_VULNERABILITY, NETWORK_REACHABILITY and CODE_VULNERABILITY. Each has a status of ACTIVE, SUPPRESSED or CLOSED. The fields that drive triage are visible in the EventBridge event Inspector emits, abridged here from the documented example:

{
  "source": "aws.inspector2",
  "detail-type": "Inspector2 Finding",
  "resources": ["i-0c2a343f1948d5205"],
  "detail": {
    "type": "PACKAGE_VULNERABILITY",
    "severity": "MEDIUM",
    "status": "ACTIVE",
    "exploitAvailable": "YES",
    "fixAvailable": "YES",
    "findingArn": "arn:aws:inspector2:us-east-1:111122223333:finding/FINDING_ID",
    "packageVulnerabilityDetails": {
      "vulnerabilityId": "CVE-2022-3303",
      "cvss": [{"baseScore": 4.7, "source": "NVD", "version": "3.1"}],
      "vulnerablePackages": [{
        "name": "linux-image-aws",
        "version": "5.15.0.1026.30~20.04.16",
        "fixedInVersion": "0:5.15.0.1027.31~20.04.16",
        "remediation": "apt update && apt install --only-upgrade linux-image-aws"
      }]
    }
  }
}

The Inspector score starts from the NVD CVSS base score and adjusts it for your environment. The documentation's example lowers the score of a network-exploitable CVE on an instance that has no open network path to the internet. Use that score, together with exploitAvailable and fixAvailable, rather than raw CVSS. A finding that has a public exploit, an available fix and a reachable resource is a ticket today. A finding with no fix is a watch item.

Enabling it across an organization

Inspector is regional and per account. In an AWS Organization, designate a delegated administrator account, normally your security tooling account. It can activate scanning for members, auto-enable new accounts, view aggregated findings and set the EC2 scan mode for everyone. Do this in every Region you use, because a Region where Inspector is off is a Region with no findings, which looks identical to a clean one.

# From the delegated administrator account, per Region:
aws inspector2 enable \
  --account-ids 111122223333 444455556666 \
  --resource-types EC2 ECR LAMBDA LAMBDA_CODE

# Check coverage: what is scanned, and why the rest is not
aws inspector2 list-coverage --region eu-west-1

The valid --resource-types values are EC2, ECR, LAMBDA, LAMBDA_CODE and CODE_REPOSITORY. Coverage, not findings count, is the first metric to watch. Instances that show as unmanaged or with stale inventory are the ones silently falling back to daily agentless scans, or not being scanned at all.

Routing and suppressing findings

Inspector publishes every new finding and every state change to EventBridge on the default bus, per Region and on a best-effort basis. A delegated administrator receives member accounts' events too, with awsAccountId identifying the source. Match all statuses so closures reach your handler too:

{
  "source": ["aws.inspector2"],
  "detail-type": ["Inspector2 Finding"],
  "detail": {
    "severity": ["HIGH", "CRITICAL"],
    "status": ["ACTIVE", "SUPPRESSED", "CLOSED"]
  }
}

Point it at a Lambda function that keys tickets on findingArn, because every state change of a finding arrives as a new event. Create tickets only for active findings with a fix, and let later events update or close them:

def handler(event, context):
    d = event["detail"]
    arn = d["findingArn"]
    ticket = tickets.find_by_external_id(arn)          # your tracker's API
    if d["status"] == "CLOSED":
        if ticket: tickets.resolve(ticket, "Inspector observed the fix")
        return
    if d["status"] == "SUPPRESSED":
        if ticket: tickets.resolve(ticket, "Risk accepted by suppression rule")
        return
    summary = f'{d["title"]} on {event["resources"][0]} (account {d["awsAccountId"]})'
    if ticket:
        tickets.update(ticket, summary=summary, severity=d["severity"])
    elif d.get("fixAvailable") == "YES":
        tickets.create(external_id=arn, summary=summary, severity=d["severity"],
                       owner=owner_from_tags(d["resources"][0]))

Suppress what you have decided to accept with a suppression rule: a filter with action SUPPRESS. Suppressed findings stay queryable, but leave the default view and stop counting. Scope rules narrowly and record the reason, or they quietly become a way to hide work:

aws inspector2 create-filter \
  --name "accept-CVE-2023-12345-batch-images" \
  --action SUPPRESS \
  --reason "No network listener in batch images; revisit 2027-01-31" \
  --filter-criteria '{
    "vulnerabilityId": [{"comparison": "EQUALS", "value": "CVE-2023-12345"}],
    "ecrImageRepositoryName": [{"comparison": "EQUALS", "value": "batch-jobs"}]
  }'

Scanning before the registry

Registry scanning tells you about a vulnerable image after it has been pushed. To fail a build earlier, use the Amazon Inspector SBOM Generator (inspector-sbomgen) in the pipeline. It builds a CycloneDX SBOM for an image, directory, archive or Go and Rust binary, and with --scan-sbom sends it to the Inspector Scan API for vulnerability results. Plugins exist for Jenkins, TeamCity and GitHub Actions. The Scan API rejects SBOMs with more than 5,000 packages with an HTTP 400.

./inspector-sbomgen container --image "$IMAGE:$GIT_SHA" \
    --scan-sbom --scan-sbom-output-format inspector \
    --outfile /tmp/inspector_scan.json
# then fail the job if the report contains CRITICAL findings with a fix available

For an inventory of what is already deployed, aws inspector2 create-sbom-export writes SBOMs for scanned resources to S3 in CYCLONEDX_1_4 or SPDX_2_3 format, encrypted with a KMS key you supply. That is the answer when someone asks which services ship a given library.

Worked example: from 9,000 findings to a work list

Take an illustrative organization: 400 EC2 instances, of which 310 are SSM managed, 70 are unmanaged but EBS-backed and eligible, and 20 are ineligible. It also has 1,800 ECR images and 150 Lambda functions. In the first week Inspector reports about 9,000 active findings. The numbers are made up but the shape is typical, and the triage is the same at any size:

  1. Coverage first. The 20 ineligible instances, perhaps with volumes over 1,200 GB, have no findings at all. Bring them under SSM management.
  2. Drop what is not running. Filter container findings to ecrImageInUseCount greater than zero. Old images with no running tasks often account for most container findings.
  3. Fix available and exploit available. Filter the rest to HIGH or CRITICAL with fixAvailable = YES and exploitAvailable = YES. That leaves a short list measured in dozens.
  4. Group by remediation, not by CVE. One base image rebuild or one AMI refresh closes hundreds of findings at once. Assign work per owner, using resource tags.
  5. Measure closure. Track time from first observed to closed per severity. Because Inspector closes findings automatically when it sees the fix, the metric needs no manual updates.

Failure modes

  • Silent coverage gaps. Instances without SSM and ineligible for agentless scanning, Regions where Inspector is off, and images outside the monitoring window all produce zero findings. Watch coverage, not the findings count.
  • On-push only. Repositories set to scan on push are never re-evaluated against new CVEs. Use continuous scanning for anything that runs.
  • Deleted SSM associations. Someone cleans up resources ending -do-not-delete. Inspector recreates them, but agent-based scans pause until it does.
  • Duplicate tickets. Every state change is a new event. Key on findingArn.
  • Suppression creep. Broad rules with no reason or review date hide real risk. Require a reason and expire them.
  • Different results from different methods. Agentless and agent-based scans see different language-package paths, so a finding can appear when an instance switches method.

Trade-offs

ChoiceGainsCosts
Agent-based EC2Rescans on change, deep inspection, network-independentNeeds SSM managed instances and permissions
Agentless EC2No agent; covers unmanaged instancesDaily cadence; volume and file-system limits
Continuous ECRNew CVEs reach old imagesBilled by Inspector; bounded monitoring window
CI scan with sbomgenBlocks bad images before pushOnly sees the build, not runtime drift

Inspector findings flow into AWS Security Hub, alongside threat detections from GuardDuty. Routing is covered in EventBridge, organization-wide guardrails in Organizations and SCPs, and SBOM formats in SBOMs and supply chain security.

What to do next

  1. Pick a delegated administrator account and enable Inspector for every member account in every Region you use, with auto-enable for new accounts.
  2. Open the EC2 scanning settings and confirm the scan mode. Prefer hybrid, and plan the Enhanced EC2 Scanning upgrade.
  3. Run list-coverage and fix every instance that is unmanaged, has stale inventory or is ineligible. Put SSM on by default with Default Host Management Configuration or instance profiles.
  4. Set running repositories to continuous scanning and check the re-scan duration against how long your images actually stay deployed.
  5. Create one EventBridge rule for HIGH and CRITICAL findings in every status, feeding a handler that keys on findingArn, opens tickets for fixable active findings and resolves them on close.
  6. Write a suppression policy: narrow criteria, a recorded reason and a review date.
  7. Add inspector-sbomgen with --scan-sbom to the image build and fail on CRITICAL findings that have a fix.
  8. Report time-to-close per severity monthly, and treat coverage as a metric alongside it.
Key takeaway: Amazon Inspector continuously matches the software inventory of EC2 instances, ECR images and Lambda functions against vulnerability data, and rescans when either the resource or the advisories change. Its value depends on coverage and triage. Enable it org-wide in every Region, keep instances SSM managed with agentless as the fallback, scan running repositories continuously, prioritise by in-use images, available fixes, known exploits and the Inspector score, dedupe routed findings on findingArn, suppress narrowly with reasons, and scan images with sbomgen before they reach the registry.