Insight
Reachability Is a Traversal Problem, Not a Lookup Problem
Most security tools answer "can A reach B?" by matching against stored rules. That is the wrong abstraction. The answer lives in the graph, and it requires walking the structure to find out.
The most common question in network security is also the most poorly answered.
“Can A reach B?”
Every SIEM, every firewall UI, every CSPM, and every asset inventory tool will attempt to answer it. Very few succeed, not because the underlying data is absent, but because the computational model is incorrect.
Most tools treat reachability as a lookup problem. Locate A, locate B, check whether a rule permits the traffic. If a rule allows it, the answer is yes.
That logic fails in almost every real environment.
Why lookups break down
A firewall rule is not a statement of reachability. It is a statement about one device’s policy for one traffic direction at the moment the query was issued.
To determine whether A can actually reach B, the following conditions must all hold simultaneously:
- the topology path between A and B exists
- every policy device along that path permits the traffic
- the routing table delivers packets in the direction the policy expects
- any tunnel or stateful session required to carry that traffic is established
If any one of these conditions is violated, the answer changes. They do not update in synchrony.
A lookup against a firewall ruleset can only evaluate the second condition. The remaining three require walking the network from A, through every intermediate hop, to B, and evaluating each layer in sequence.
That is, by definition, a traversal problem.
The graph is the right model
We adopted Neo4j early in the design process. Not because graph databases are fashionable, but because a network’s underlying data structure is a graph, and the question we are trying to answer is a path query.
A subnet connects to a route table. That route table has entries pointing to a NAT gateway or a transit hub. That transit hub has peerings to other networks. Each hop has a security group or firewall policy governing what traffic may pass. VPN connections introduce tunnels that conditionally splice two otherwise-disconnected segments.
No relational schema captures this structure naturally. Every JOIN becomes an approximation of a hop. Recursive queries grow unwieldy as path depth increases. And the path itself, which is the object of interest, remains implicit rather than first-class.
In a graph database, the path is a first-class object. The query becomes: does a path exist from node A to node B such that every edge in that path is traversable given this traffic specification? The database was built to answer exactly that question.
The normalization problem is the hard part
Multi-vendor environments make traversal substantially more difficult than it might initially appear.
An AWS Security Group and an Azure Network Security Group both filter traffic. However, they model rules differently, attach at different levels of the topology hierarchy, and express port ranges in different formats. A UniFi firewall policy uses nested source and destination zone objects referencing legacy Mongo-style identifiers.
If each vendor’s data is stored in its native representation, cross-vendor traversal becomes impossible. A path from an on-premises workload through a site-to-site VPN into an Azure VNet requires walking from a UniFi node type to an Azure node type, across a VpnConnection edge, and evaluating both sides’ policies under a consistent model.
To make this tractable, all ingested data is normalized into a shared vocabulary before it enters the graph. Every security boundary becomes a SecurityGroup or Firewall node. Every network segment becomes a Subnet. Every tunnel becomes a VpnConnection. Every route becomes a Route with a ROUTES_TO edge.
That shared vocabulary is what makes cross-vendor path analysis possible. Without it, every query would need to dispatch on the vendor origin of each node and handle each representation separately. At that point, traversal has been reduced to a chain of vendor-specific lookups.
What this unlocks
Once reachability is modeled as a traversal problem on a normalized graph, a class of questions that was previously impractical becomes answerable:
- Which paths from the internet can reach this database, and what permits each hop?
- If this firewall policy is modified, which workloads gain or lose reachability?
- What is the shortest path from this compromised endpoint to the most sensitive assets?
- Which networks are reachable from this subnet, and what is the evidence for each claim?
These are not exotic queries. Security teams ask them routinely. The reason most tools cannot answer them well is not a data collection problem. It is a data model problem.
Getting the model right at the outset means the hard questions become progressively easier, rather than requiring bespoke logic for each new case.
The architectural bet
This architectural choice was made with full awareness that it introduces upfront complexity. Maintaining a normalized vocabulary across vendors requires ongoing discipline. Every new resource type must be mapped before it can enter the graph. The normalization layer represents engineering investment that does not ship user-facing features directly.
The alternative, however, is worse. Starting from raw vendor data allows faster initial development, until the point at which a user needs to reason about a path that crosses a vendor boundary, at which point the model cannot support the query without a structural rewrite.
The traversal model is the correct foundation. The normalization layer is what makes it defensible over time.
That is what we are building on.