Self-hosted service
anaynayak/aws-security-viz avatar
anaynayak/aws-security-viz

aws-security-viz turns security group rules into a reachability graph

Visualize your aws security groups.

723 stars110 forksRubyMIT

At a glance

What is it?
aws-security-viz reads EC2 security group configuration from the AWS API or from a JSON file and draws which groups can reach which, with a self-contained HTML viewer, a Mermaid and DOT output, and a CI mode that fails on risky public ingress. It is a Ruby tool, and the interesting part is the risk rule, not the drawing.
Who is it for?
aws-security-viz is worth adopting if you want an answer to a question that raw security group JSON does not answer, namely which group can actually reach which, and you want that answer reviewable as a single HTML file or as a CI exit code.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The question a security group dump cannot answer

Every AWS account accumulates security groups, and reading them one rule at a time does not scale. The rules are one-directional, so the answer to can this group reach that one is not in any single group's description. It is a property of the relationship between groups, which is why the tool exists in this form. The README states the purpose in one line: see which AWS security groups can reach which, and which are open to the internet. The input is either the EC2 security group configuration read from the AWS API, or the JSON written by the AWS command line tool, and the output is a graph. The audience is whoever owns the security posture of an account, which in practice means a platform engineer reviewing a change, a reviewer checking a pull request that touches infrastructure code, or a security team doing a periodic sweep. The project is MIT licensed, written in Ruby, and released as a gem named aws_security_viz, with a published container image as an alternative to a local install. The repository also carries a Dockerfile, a gemspec, an Rakefile, a spec directory, and a docs site built with mkdocs, so the intent is a real project rather than a script.

Reachability edges come from the group rules themselves

The mechanism is straightforward to reason about even though the README does not spell out the algorithm in code. Security groups reference each other, and each referenced group brings its own ingress rules with it, so a group can be reachable through a chain of references. That transitive structure is what the graph shows, and it is why a flat listing of rules misleads. The README describes the output in terms of the question a reader asks: the self-contained HTML viewer shows the dev VPC and its groups, the public peers 0.0.0.0/0 and ::/0, and a thick red edge from 0.0.0.0/0 to the dev-bastion group. The graph is not decorative. It turns a set of rules into a picture where a single edge can represent a path from the open internet to something that should not be reachable, and the viewer lets you ask the can X reach Y question against the drawn model. The scope is set by the region argument, so you can work on one region, several regions, or all regions in a single graph. That last mode is the one that catches things, and also the one that produces the largest picture, since the same public CIDR block now appears once per region with a different set of neighbours.

The HTML viewer is offline, and that is the point

The default output format is a self-contained HTML viewer, and the listed features are worth reading closely, because they describe a tool built for sharing a finding rather than for staring at a local render. It is offline, so there is no server, no account and no upload of your infrastructure data to anyone. It has collapsed VPCs, so a large account can be explored rather than read at a glance. It offers can X reach Y queries, several layouts, and light and dark themes. The documentation links to a viewer tour that walks through the outputs page, and the top of the README carries a screenshot of the same scene in a dark colour scheme variant. The rest of the format list is for other consumers: JSON, Mermaid, DOT, and any image format Graphviz supports. Mermaid matters if you want the result inside a pull request comment or a wiki page, since it is text rather than a picture. DOT and the image formats need Graphviz installed, which is the only reason Graphviz appears in the requirements at all, since the default HTML output does not use it. A second, smaller set of outputs exists so the tool can be used as a check rather than a picture, and that is where the risk rule comes in.

Risky public ingress becomes an exit code, not a colour

The mechanism that separates this from a diagrammer is the risk rule. Risky public ingress, meaning 0.0.0.0/0 or ::/0 on a sensitive port, is drawn as a dashed crimson edge, and the --fail-on-risk flag turns that into exit status 2 for CI. The default HTML output shows you the same condition as an edge, and the flag makes it a build failure. That is the whole design idea: a picture gets reviewed once, an exit code gets enforced on every change. The set of sensitive ports is configuration rather than hardcoded policy, and the documentation lists a section on configuration, opts.yml and exit codes as well as a separate section on filtering and risk checks including CI, so the port list, the filters and the exit behaviour are all treated as things you set rather than things you accept. The dependency list in the repository confirms there is a configuration file involved. The trade-off is the same one every such check has: the rule is a blunt instrument, and a port that is genuinely public on purpose still fails the build until you either exclude it or turn the check off for that scope.

Installing the gem, or pulling the image with Graphviz already in it

The local route is a gem install, and the requirements are Ruby 3.3 or newer with Graphviz needed only for image formats such as png and svg.

bash
gem install aws_security_viz

The container route is for when you do not want to set up Ruby or Graphviz locally, and the published image has both built in.

bash
docker pull ghcr.io/anaynayak/aws-security-viz:<version>

The image is built in two stages on an Alpine base, with the build stage installing build tools and the final stage adding Graphviz and the DejaVu fonts, then dropping to a non-root user with a work directory the user owns. The entrypoint is the gem itself.

dockerfile
RUN apk add --no-cache graphviz font-dejavu \
 && addgroup -S viz && adduser -S -G viz -h /home/viz viz \
 && mkdir /work && chown viz:viz /work

That last detail matters if you run the container against files on your machine, since the container writes to a work directory owned by an unprivileged user. The repository also ships a pyproject.toml, but it is for the documentation site only, and the comment in that file says so explicitly: the gem itself is built from the gemspec. The same project therefore uses two toolchains, Ruby for the tool and a Python environment for the docs and the headless browser specs.

Exporting once, or querying AWS directly

The example in the README is two commands, and the first is the ordinary AWS CLI call, redirected to a file.

bash
aws ec2 describe-security-groups > security_groups.json
aws_security_viz -o security_groups.json -f viz.html

The second command points the tool at that file with -o and asks for the HTML output with -f, and opening viz.html in a browser gives you the viewer. If you would rather not export anything, the README says to use --profile and --region in place of -o, for example --profile <profile_name> --region us-west-1, and the tool then talks to the API itself. Those credentials are the part to think about before you run it, and the documentation has a dedicated page on credentials and IAM, so the intended audience is expected to read it. The practical difference between the two modes is auditability. The export produces an artefact you can attach to a review, diff between runs, and check into a repository if your policy allows it, while the direct mode is convenient and leaves no intermediate file. The direct mode also means the tool needs read permissions on EC2 security group state, and in a multi-account setup you would run it once per account, since the tool reads the accounts your credentials can see.

What this does not do

Several limits are worth stating plainly. It is a snapshot tool. Whether the data comes from the API at run time or from a JSON file you exported, the graph describes the account as it was at that moment, and there is no watch mode, no refresh and no schedule, so a graph left in a wiki goes stale silently. It also does not consider anything outside security groups. The rules it reasons about are EC2 ingress and egress between groups, and the README does not describe network ACLs, route tables, VPC peering, transit gateways, IAM policies, or whether a resource is even attached to a group, so a group that looks unreachable in the picture may still be reachable through a path the tool does not model. A false sense of coverage is the risk here, and the picture's clarity works against you, because a clean graph invites the reading that nothing else is open. The alternative approaches differ on that axis. The AWS CLI on its own gives you the raw JSON, which is authoritative and complete but requires you to do the transitive reasoning yourself. A managed security posture tool, or a cloud configuration scanner, evaluates rules against a policy baseline and can report on things the graph does not show, at the cost of a service, an account and a bill. The middle option, an internal script that resolves group references and prints reachable pairs as text, gives you the same transitive reasoning without a rendering layer, and is easier to review in a pull request than an image. What aws-security-viz adds is the picture and the exit code, and what it cannot add is coverage of the things it does not model.

Editorial conclusion

aws-security-viz is worth adopting if you want an answer to a question that raw security group JSON does not answer, namely which group can actually reach which, and you want that answer reviewable as a single HTML file or as a CI exit code. It is the wrong tool if you need a live view of a changing account, since the model is built from a snapshot taken either from the API at run time or from a JSON file you export yourself, and it is the wrong tool if you are not willing to think about which ports count as sensitive, because the risk rule is a configuration concern the documentation treats as configurable. Before you wire it into a pipeline, run it once against one region with a JSON export, read the dashed crimson edges to check that the flagged ports match your policy, and then enable --fail-on-risk only once the noise is acceptable.

Frequently asked questions

How do I install aws-security-viz?

Install the gem with gem install aws_security_viz, which needs Ruby 3.3 or newer, or pull the published image with docker pull ghcr.io/anaynayak/aws-security-viz:<version>, which has Ruby and Graphviz built in. Graphviz is only needed locally for image formats such as png and svg.

How does aws-security-viz fail a CI job on open security groups?

Risky public ingress, meaning 0.0.0.0/0 or ::/0 on a sensitive port, is drawn as a dashed crimson edge, and the --fail-on-risk flag turns that into exit status 2. The documentation covers the port configuration in opts.yml and the filtering and risk check pages.

Can aws-security-viz read security groups without calling the AWS API?

Yes. It reads the JSON written by aws ec2 describe-security-groups, as in the README example where the file security_groups.json is passed with -o. To query AWS directly instead, use --profile and --region in place of -o.

Official sources

  1. anaynayak/aws-security-viz on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/anaynayak-aws-security-viz.svg)](https://hysenlabs.com/projects/anaynayak-aws-security-viz)

Was this useful?