Guide · AWS Inspector · EC2 Scanning
AWS Inspector EC2 Scanning — SSM Agent, Package Vulnerabilities, Network Reachability, and CIS
AWS Inspector EC2 scanning has one hard prerequisite that stops most teams cold: every instance must be a Systems Manager managed instance with SSM Agent running and connected — without it, Inspector marks the instance INACTIVE and performs no scan. When that prerequisite is met, Inspector performs three types of checks: package vulnerability scanning (CVEs in OS and language packages), network reachability analysis (which ports are reachable from the internet based on VPC topology), and CIS Benchmark hardening checks. All three are continuous — Inspector re-runs the package and network checks whenever a new CVE is published in the NVD, when a patch is applied, or when VPC configuration changes; you do not schedule scans manually.
TL;DR
Install SSM Agent and attach an IAM instance profile with AmazonSSMManagedInstanceCore. Verify connectivity with aws ssm describe-instance-information. Once the instance appears as a managed instance, Inspector automatically scans it — no further configuration needed. For the overview of all Inspector resource types see the Inspector overview. For ECR and Lambda scanning see the ECR guide and Lambda guide. For managing findings see the findings guide.
SSM Agent prerequisites
Inspector communicates with EC2 instances through the SSM Agent — there is no Inspector agent to install separately. Amazon Linux 2, Amazon Linux 2023, Ubuntu Server 18.04+, Windows Server 2016+, and RHEL 7+ all ship with SSM Agent pre-installed but not necessarily configured with the right IAM permissions.
# Step 1: verify SSM Agent is running on the instance
sudo systemctl status amazon-ssm-agent
# Step 2: verify the IAM instance profile has SSM permissions
aws iam get-instance-profile \
--instance-profile-name YourInstanceProfile \
--query 'InstanceProfile.Roles[0].AssumedRolePolicyList'
# The profile's role must include AmazonSSMManagedInstanceCore (AWS managed policy)
# ARN: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# Step 3: check the instance is registered as a managed instance
aws ssm describe-instance-information \
--filters "Key=InstanceIds,Values=i-0abc1234567890def" \
--query 'InstanceInformationList[0].{Id:InstanceId,Ping:PingStatus,Agent:AgentVersion}'
The critical field is PingStatus. A value of Online means SSM Agent is connected and Inspector can scan the instance. ConnectionLost means the agent cannot reach the SSM endpoint — this usually happens when the instance is in a private subnet without a NAT gateway or a VPC interface endpoint for SSM.
# For private subnets without NAT: create VPC interface endpoints for SSM
# Required endpoints: com.amazonaws.REGION.ssm, com.amazonaws.REGION.ec2messages, com.amazonaws.REGION.ssmmessages
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc1234 \
--service-name com.amazonaws.us-east-1.ssm \
--vpc-endpoint-type Interface \
--subnet-ids subnet-0abc1234 \
--security-group-ids sg-0abc1234 \
--private-dns-enabled
Package vulnerability scanning
Inspector scans all packages installed via the OS package manager (yum, apt, zypper, dnf) and language runtime package managers (pip for Python, npm for Node.js, gem for Ruby, and Maven/Gradle for Java). The scan reads the package database on disk — it does not execute code or make network requests from the instance.
Inspector uses the NVD, vendor security advisories (RHSA, DSA, USN), and threat intelligence feeds to match installed package versions against known CVEs. The matching is exact-version: a package at version 1.2.3 is only flagged if there is a CVE that affects exactly 1.2.3 — advisory "affected versions: <= 1.2.3" is correctly handled.
# View package vulnerability findings for a specific instance
aws inspector2 list-findings \
--filter-criteria '{
"resourceId": [{"comparison":"EQUALS","value":"i-0abc1234567890def"}],
"findingType": [{"comparison":"EQUALS","value":"PACKAGE_VULNERABILITY"}],
"severity": [{"comparison":"EQUALS","value":"CRITICAL"},{"comparison":"EQUALS","value":"HIGH"}]
}' \
--sort-criteria '{"field":"INSPECTOR_SCORE","sortOrder":"DESC"}' \
--query 'findings[].{Score:inspectorScore,Severity:severity,CVE:packageVulnerabilityDetails.vulnerabilityId,Package:packageVulnerabilityDetails.vulnerablePackages[0].name,Fix:packageVulnerabilityDetails.vulnerablePackages[0].fixedInVersion}' \
--output table
The fixedInVersion field tells you which package version resolves the CVE. If fixedInVersion is absent, no upstream fix is available yet — you must suppress the finding or accept the risk until a patch is released.
Network reachability analysis
Inspector's network reachability check analyzes VPC topology — security groups, NACLs, route tables, and internet gateway attachments — to determine which ports on an instance are reachable from the internet or from other VPCs. This is static analysis, not active port scanning; Inspector does not send packets to your instances.
A NETWORK_REACHABILITY finding reports a specific port and protocol (e.g., TCP/22, TCP/3000) along with the reason it is reachable: the security group rule, the NACL allow, and the route via IGW or VPC peering. This is useful for catching security group rules that were opened for debugging and never closed.
# View network reachability findings
aws inspector2 list-findings \
--filter-criteria '{
"findingType": [{"comparison":"EQUALS","value":"NETWORK_REACHABILITY"}],
"resourceId": [{"comparison":"EQUALS","value":"i-0abc1234567890def"}]
}' \
--query 'findings[].{Port:networkReachabilityDetails.openPortRange,Protocol:networkReachabilityDetails.protocol,Via:networkReachabilityDetails.networkPath.steps[-1].componentType}' \
--output table
Common MCP server patterns that trigger network reachability findings:
- Port 22 (SSH) open to 0.0.0.0/0 — should be locked to a bastion security group or removed entirely in favor of SSM Session Manager (which also fixes SSM connectivity)
- MCP server port (3000, 8080, etc.) open to 0.0.0.0/0 — intended for public MCP access but Inspector flags it; use a suppress rule if intentional and document the business justification
- Debug port (9229 for Node.js) reachable — almost always an oversight; close immediately
Network reachability findings update within minutes when VPC configuration changes — if you close a security group rule, the finding moves to CLOSED status automatically without any manual action.
CIS Benchmark scanning
Inspector supports CIS Benchmark Level 1 and Level 2 checks for the following operating systems: Amazon Linux 2, Amazon Linux 2023, Ubuntu 18.04/20.04/22.04, Red Hat Enterprise Linux 7/8/9, and Windows Server 2019/2022. CIS scanning checks OS hardening configuration: password complexity policy, SSH configuration (PermitRootLogin, PasswordAuthentication), filesystem permissions, auditd rules, sysctl parameters, and service hardening.
# CIS findings use finding type "SOFTWARE_CONFIGURATION" in the API
# (reported as "CIS" in console but SOFTWARE_CONFIGURATION in filter criteria)
aws inspector2 list-findings \
--filter-criteria '{
"findingType": [{"comparison":"EQUALS","value":"SOFTWARE_CONFIGURATION"}]
}' \
--query 'findings[].{Title:title,Severity:severity,Resource:resources[0].id,Rule:codeVulnerabilityDetails}' \
--output table | head -30
CIS Level 1 checks are generally safe to enforce on MCP server instances — they cover basic hardening without breaking typical server workloads. Level 2 includes more restrictive controls (e.g., disabling USB storage, strict auditd rules) that may require testing before enforcement in production.
CIS scan frequency is weekly for configuration checks (unlike package vulnerability scans which trigger on patch events). If you remediate a CIS finding, the finding remains ACTIVE until the next weekly scan cycle confirms the fix — you cannot force an immediate re-scan for CIS findings.
Rescan triggers
Inspector EC2 scanning is event-driven, not scheduled. Rescans happen automatically when:
| Trigger | Finding types rescanned | Typical latency |
|---|---|---|
| New CVE published in NVD or vendor advisory | PACKAGE_VULNERABILITY | Minutes to a few hours after CVE publication |
| Package installed or removed (detected via SSM inventory change) | PACKAGE_VULNERABILITY | Within 1 hour of SSM inventory update |
| Security group, NACL, or route table modified | NETWORK_REACHABILITY | Within minutes of VPC configuration change |
| Inspector initially enabled in account | All types | Initial deep scan, 30–60 min for large fleets |
| Weekly CIS cycle | SOFTWARE_CONFIGURATION (CIS) | Fixed weekly cadence |
There is no API to manually trigger an on-demand rescan for EC2. If you need to verify a patch applied, the fastest path is to update a package (which triggers an SSM inventory change) and wait for the subsequent rescan.
Suppressing false positives
Not every finding requires remediation — some packages have vulnerabilities that are not exploitable given your specific deployment (e.g., a CVE in a networking library for a feature your MCP server does not use). Use Inspector suppression rules to keep your dashboard actionable:
# Create a suppression rule for a specific CVE on a specific resource tag
aws inspector2 create-filter \
--name "suppress-CVE-2024-XXXXX-dev-tier" \
--description "CVE-2024-XXXXX in libssl not exploitable in MCP server data path — tracked in JIRA-1234" \
--filter-criteria '{
"vulnerabilityId": [{"comparison":"EQUALS","value":"CVE-2024-XXXXX"}],
"resourceTags": [{"comparison":"EQUALS","key":"Environment","value":"development"}]
}' \
--action SUPPRESS \
--reason "Compensating control: MCP server does not expose TLS termination; handled by ALB"
Suppression rules apply to existing and future findings — once created, all matching findings move to SUPPRESSED status immediately. The --reason field is logged to CloudTrail and visible in the Security Hub finding record, creating an audit trail. Always include a ticket reference and a technical reason in --description.
Failure modes reference
| Failure | Symptom | Fix |
|---|---|---|
| Instance INACTIVE in coverage | ListCoverage shows statusCode INACTIVE with reason NO_SSM | Install SSM Agent + attach AmazonSSMManagedInstanceCore policy; for private subnets create SSM VPC interface endpoints |
| Instance online in SSM but INACTIVE in Inspector | describe-instance-information shows Online but Inspector coverage shows INACTIVE | Inspector uses SSM inventory; run aws ssm start-associations-once to force inventory collection; up to 1 hour for Inspector to pick it up |
| Language packages not scanned | Only OS packages appear in findings; no npm/pip packages | SSM Agent must have access to the package lock files; Python venvs and Node node_modules in home directories may not be visible — install packages system-wide or use a standard path |
| Network reachability not updating after SG change | Finding still ACTIVE after closing security group rule | Network reachability updates within minutes; if stale after 15 min, check that the correct SG was modified on the instance's primary network interface |
| CIS check fails but config is correct | CIS finding ACTIVE after applying the recommended fix | CIS scans run weekly; the finding will close at the next weekly cycle; no on-demand trigger available |