Home
05
WRITING
REV · March 20, 2026

Your Cloud Is a Graph. Your Security Tools Don't Know That.

  • #cloud
  • #security
  • #open-source
  • #graph-database
  • #aws
  • #iam
  • #attack-paths
AUTHOR
Srinivas Gowda
Srinivas Gowda
LENGTH
4 min
WORDS
1,032
SUBJECTS
7
Your Cloud Is a Graph. Your Security Tools Don't Know That.

Inventory is a list. Compromise is a path.

Ask a cloud engineer to describe their AWS account and you get an inventory grouped by service and region. Ask someone who breaks into cloud environments for a living and you get a route.

A load balancer fronts an instance. The instance carries a role. The role can assume a second role in another account. That role can read a bucket nobody has opened since 2021. Every fact is boring alone. Strung together they are the incident.


Why rule engines miss it

Posture management tools evaluate one resource at a time, which means they assign severity one resource at a time. Four findings from an ordinary week:

FindingSeverity
Security group allows 0.0.0.0/0 on 443Low, it is a web server
Instance profile has a broad role attachedMedium
Role trusts a role in another accountLow, that is how we deploy
Bucket is private, readable by that roleInformational

Nothing above medium. Ticket closed. Now connect them:

The chain is the finding. No single check was wrong and no single check could have caught it, because the vulnerability does not live in a resource. It lives between them. A list cannot express a path, so this is a data model problem, not a tuning problem.


Cartography

Cartography pulls your infrastructure into a Neo4j graph database: resources become nodes, relationships become first-class edges, and you ask questions in Cypher.

Built at Lyft, open sourced in 2019, accepted into the CNCF at Sandbox maturity in August 2024. It ships 50+ integrations, which matters more than it sounds:

Real attack paths do not respect product boundaries. They start at an identity provider, pass through a code host, and end at a database. One graph holding all three can express that in a single query. Three consoles cannot.

The sync is a batch job using credentials you already have. Writes use MERGE, so re-running converges instead of duplicating, and a cleanup pass deletes anything not touched by the current run. Without that second part the graph slowly fills with resources that no longer exist, which is worse than having no graph at all.


Three queries worth running first

Which internet-facing instances carry a role?

MATCH (:IpRange {id: '0.0.0.0/0'})-[:MEMBER_OF_IP_RULE]->(:IpPermissionInbound)
      -[:MEMBER_OF_EC2_SECURITY_GROUP]->(sg:EC2SecurityGroup)
      <-[:MEMBER_OF_EC2_SECURITY_GROUP]-(i:EC2Instance)
MATCH (i)-[:STS_ASSUMEROLE_ALLOW]->(r:AWSRole)
RETURN i.instanceid, i.publicdnsname, r.arn

What is the blast radius of one compromised role?

MATCH path = (:AWSRole {arn: $compromised})
             -[:STS_ASSUMEROLE_ALLOW*1..4]->(reached:AWSRole)
RETURN reached.arn, length(path) AS hops ORDER BY hops

That *1..4 is the entire argument for a graph database. It means follow this edge up to four times and show me where it lands. Against a relational inventory it is four self-joins and a query nobody will maintain.

Which people can reach production, and through which group?

MATCH (u:OktaUser)-[:MEMBER_OF_OKTA_GROUP]->(g:OktaGroup)
      -[:ALLOWED_BY]->(r:AWSRole)-[:POLICY]->(p:AWSPolicy)
WHERE p.name CONTAINS 'Admin'
RETURN u.email, g.name, r.arn

This one starts at a person and ends at an AWS policy. Without a graph it is two exports and a spreadsheet, which is why nobody runs it more than once a year.


Tracing a real breach

Capital One, 2019. Every hop is individually defensible.

A rule engine sees a bad WAF rule, an instance with a role, and a private bucket. Three findings, none critical. A graph sees four hops from the public internet to customer data, and can be asked for every other path shaped like it:

MATCH p = (:IpRange {id: '0.0.0.0/0'})-[*1..6]->(b:S3Bucket)
WHERE b.anonymous_access = false
RETURN p LIMIT 25

Cartography would not have prevented the breach. It makes "what else looks like this" a query instead of a quarter-long audit.


Getting started

git clone https://github.com/cartography-cncf/cartography.git
cd cartography
docker compose up

Open Neo4j on localhost:7474 and start with the smallest useful question:

MATCH (a:AWSAccount)-[:RESOURCE]->(i:EC2Instance)
RETURN a.name, count(i) AS instances

Give it read-only credentials. It is a mapping tool and has no reason to write anything. The documentation covers per-provider setup and the permissions each integration needs.

Its drift-detection mode diffs the graph between runs. People discover it last and rely on it most, because a snapshot answers "is this safe now" while a diff answers "what changed since it was", which is the question you actually have at 2am.


Where it does not help

It is a snapshot, not a stream. Between syncs the graph is stale. A role created and used within the hour may never appear. It complements CloudTrail rather than replacing it.

Reachability is not exploitability. A path means permissions allow it. It says nothing about SCPs, permission boundaries, trust policy conditions, or network controls a step removed. Expect to triage findings that turn out to be blocked elsewhere.

Someone has to own the queries. You get a graph, not a verdict. With nobody asking it questions you have installed a thorough inventory system and gained nothing.

Neo4j is now yours to run. Size it, back it up, keep it off the internet. Breaching yourself with your own attack-path mapper would be a poor way to prove the thesis.


The shift

Security is moving from "is this resource configured correctly" to "what can be reached from here". Every major vendor has shipped some form of attack path analysis recently, and underneath they are all building a graph. Cartography is that idea without the license.

Start with the smallest question you cannot currently answer. Mine was which internet-facing services could reach the customer database and by what route. It took ten minutes once the graph existed, and had been unanswerable for a year before that.

Tweet this article

Stay up to date

Get emails from me about web development, tech, and early access to new projects.


Srinivas Gowda

Srinivas Gowda

I craft cloud canvases where art meets architecture, blending creativity with technical expertise to design innovative digital masterpieces.

ALL RIGHTS RESERVED © SRINIVAS GOWDA 2026
DRAWN BY SRINIVAS GOWDA · SOLANCER.COM