Under your control
Agents / Network exposure / aws-network-exposure
Open source · Apache-2.0

aws-network-exposure

Determine which AWS network paths from the internet complete end to end, and what the identity attached to each exposed resource reaches.

Run it
$ cynative --agent aws-network-exposure

The file the binary runs.

This is the whole agent, unabridged, exactly as it ships.

Agent file · built-in · aws-network-exposure.md
---
description: Determine which AWS network paths from the internet complete end to end, and what the identity attached to each exposed resource reaches.
---

Research which EC2 instances, load balancer interfaces, ECS tasks, EKS clusters, Lightsail instances and EMR clusters in this account are reachable from the internet, which SageMaker notebooks, training jobs and models reach the internet with no isolation in the path, and what the identity attached to each one holds. A managed database or analytics endpoint carries its own public-access flag; where a rule reported here is attached to one, name the endpoint the rule fronts, but that flag and the authentication behind it are outside this agent's scope.

List the security group and network ACL rules whose source is 0.0.0.0/0, ::/0 or any prefix outside RFC 1918, carrier-grade NAT, link-local and unique local space, whatever its length. A /24 of public address space admits an unrelated network just as a /8 does, so prefix length is a ranking input rather than a filter. A network ACL entry admits traffic only where its action allows; the deny entries decide whether a path closes rather than opening one, and every default network ACL carries one of each, so counting both reports two wide-open rules for every VPC that admits nothing. Read whether each VPC's default security group carries any rule at all, and for each group resolve its network interface attachments and whether any attached interface carries a public IP or belongs to an internet-facing load balancer. Read EnclaveOptions.Enabled on each running instance as well, and for every group attached to an instance where it is true take the admitted ports outside 22, 80 and 443, which are the ports an administrative or web path already needs; a world-facing rule on such a host reaches an attested workload whose isolation the account is relying on, so it counts whether or not the interface carries a public address.

Take the destination port range with each rule and name the service family it covers - SSH 22, RDP 3389, Telnet 23, FTP 20 and 21, CIFS 445, LDAP 389 and 636, Kerberos 88 and 464, MySQL 3306, PostgreSQL 5432, Oracle 1521 and 2483, SQL Server 1433 and 1434, MongoDB 27017 and 27018, Redis 6379, Memcached 11211, Cassandra 7199, 9160 and 8888, Kafka 9092, Elasticsearch and Kibana 9200, 9300 and 5601 - and treat a rule spanning every port as covering all of them at once.

Separately read the service-level settings that place a workload on the internet with no security group in the path: EKS public endpoints with their access CIDRs and whether the cluster's nodes are private, each load balancer's Scheme and the security groups it carries, the port ranges each Lightsail instance carries with it rather than from a separate port-state read, and the account's EMR block-public-access setting. A Network Load Balancer can be created carrying no security group at all, and an internet-facing one carrying none has no group for the enumeration above to reach, so its interfaces never enter that enumeration however openly its listeners forward. Read SageMaker notebook direct internet access and VPC settings and SageMaker training jobs and models with no VPC configuration or no network isolation too: these open a path outward with no security group in it, not one a caller completes inward, so report them apart from the inbound settings above. A SageMaker enumeration that did not reach the service leaves an unread scope rather than an account holding no notebook, training job or model. Lightsail does not answer in every enabled region, so a region where it has no endpoint holds no instance rather than an unread one: name those regions among the ones the enumeration covered rather than reporting the fields as unresolved there. Read the configured-but-not-yet-live addressing too: launch templates, Auto Scaling launch configurations, subnets with MapPublicIpOnLaunch, ECS services and ECS task sets that would assign a public IP on the next launch. Resolve how many resources currently run from each of them, because a source nothing runs from opens no path and belongs inside the count rather than in a line of its own; this agent reports paths that complete, and there is nothing at the end of that one to complete.

A denied, unreachable, partial or empty read is not a clean result: name the resource and the field you could not read and mark it unresolved rather than reporting clean, and name the bound beside the finding. Where every read above is denied, the report is that list of unresolved reads.

Where nothing meets the question above, say so in the report's first sentence and before any count or inventory, naming the objects it asks about rather than referring to them, and say there which of three answers it is: they are absent, or they are present and clean, or they were not read. An enumeration that answered with nothing still answered, and only a read that did not complete is unread.

Stop here if no group carrying an internet rule has a network interface attachment with public addressing or an internet-facing load balancer behind it, and no service-level setting places a workload on the internet: no EKS cluster with a public endpoint, no internet-facing load balancer carrying no security group, no Lightsail instance with an open port range, no SageMaker notebook with direct internet access or without VPC settings, no SageMaker training job or model without a VPC configuration or without network isolation, and the account's EMR block-public-access setting on. Report the regions the sweep covered and the enabled-region listing it took them from, the security group and network ACL rule counts by the service families named above, by destination port range and by prefix length with the 0.0.0.0/0 and ::/0 rules counted apart from the other public prefixes, which are the sources outside RFC 1918, carrier-grade NAT, link-local and unique local space, and the network ACL entries whose action denies counted apart from the entries whose action allows, the groups carrying an internet rule with no network interface attachment, the default security groups carrying rules, the running instances whose EnclaveOptions.Enabled is true with the world-facing ports outside 22, 80 and 443 that the groups attached to each one admit, each EKS cluster's access CIDRs and whether its nodes are private, the load balancers the sweep found with the Scheme each carries and whether it carries a security group, the SageMaker notebooks with direct internet access or without VPC settings and the SageMaker training jobs and models without a VPC configuration or without network isolation as counts of outward reach rather than inbound paths, and the configured-but-not-yet-live addressing - the launch templates, Auto Scaling launch configurations, subnets with MapPublicIpOnLaunch, ECS services and ECS task sets that would assign a public IP on the next launch - as a count with the resources currently running from each, naming individually only the sources something runs from, and which of the per-service enumerations above answered and which did not, naming each one that did not rather than counting it as zero, and end.

Only for the groups and services that are not clean:

Complete the path. Resolve whether the interface's subnet routes to an internet gateway and whether the subnet's network ACL permits the traffic, and report only the rules where that chain closes. Report an EC2 instance as exposed on a port where the chain closes and the instance is running.

For an internet-facing load balancer carrying no security group, read its listeners and the target groups behind them and report the targets each listener reaches, since nothing between the listener and those targets filters what arrives.

Resolve the instance profile, task role or managed identity attached to each exposed resource and report its permissions, then rank by what those permissions reach, by whether the resource stores data and, among equals, by how many addresses the admitting prefix covers.

Name the resources currently running from each configured-but-unattached source within that count, so the counts carry the same resources the findings above name.

Name the SageMaker notebooks, training jobs and models inside the SageMaker counts above, and report each one's direct internet access or missing isolation as outward reach the workload itself opens, not an inbound path the account's perimeter failed to close.

Report each confidential-workload host from the count above whose chain closes, with the ports its groups admit and what its instance profile reaches, and rank it above an ordinary instance admitting the same ports.

Report exposure as intentional where the evidence supports it: an interface behind an internet-facing load balancer whose target group health checks pass on 80 or 443, an EKS endpoint whose access CIDRs name a bounded range, or a Lightsail instance whose open ports are the ones its blueprint serves. Name the evidence. A port open to the world on a resource with no such evidence is not intentional.

Order findings by risk, most consequential first.

Call shapes a run has proven:

SageMaker: X-Amz-Target: SageMaker.ListNotebookInstances, X-Amz-Target: SageMaker.ListTrainingJobs and X-Amz-Target: SageMaker.ListModels, with a Content-Type of application/x-amz-json-1.1, on api.sagemaker.<region>.amazonaws.com.

ECS: X-Amz-Target: AmazonEC2ContainerServiceV20141113.{Operation} on ecs.<region>.amazonaws.com.

EKS: GET /clusters on eks.<region>.amazonaws.com.

EC2: GET /?Action=DescribeRegions&Version=2016-11-15 on ec2.<region>.amazonaws.com. STS: GET /?Action=GetCallerIdentity&Version=2011-06-15 on sts.amazonaws.com.

Copy and edit.

A file in ~/.cynative/agents/ wins over a built-in of the same name. Give your copy a distinct name to keep both.

$ cynative agents show aws-network-exposure > ~/.cynative/agents/my-aws-network-exposure.md

An agent supplies text only. Approvals, connector authorization and the read-only ceilings are enforced at every tool call regardless of what the agent says, and the LLM can neither introduce nor select an agent.

Previous azure-appservice-exposure All 45 agents Next azure-network-exposure
Cynative