Adding Scaleway to Cartography without rewriting vulnerability management

How shared graph concepts let a new cloud provider reuse the existing path from a running container to a CVE, fix, source repository, and owner.

I recently added Scaleway support to Cartography. The part I was most curious about was vulnerability management. Cartography already knows how to connect a CVE to a running container, its image, its source repository, and sometimes its owner. Would we have to teach it the same chain again for Scaleway, handling all of its specific data types?

It turned out that all we had to do was model the Scaleway resources correctly. Once the module said that a resource was a container, that it ran a particular image, and that the image came from a particular repository, the existing vulnerability queries could use it.

This is a small example of why we added an ontology to Cartography. It is also a useful way to explain what the ontology does, because “we added an ontology” is otherwise a fairly abstract claim.

Five questions a vulnerability finding should answer

Vulnerability management has been a Cartography use case for a long time. Lyft wrote about using Cartography for vulnerability management in 2020, and we covered container vulnerability management again in a 2023 BSidesSF talk.

A scanner gives you a CVE and a package. To do something with the finding, you usually need a few more facts:

  • Is the affected image running, or is it only sitting in a registry?
  • Which repository produced the image?
  • Does the scanner know a fixed package version?
  • Who owns the relevant code?

The answers cross several data sources. Runtime data comes from the cloud provider or Kubernetes API, often both. Package and fix data comes from the scanner. Image provenance often comes from OCI metadata, and ownership may come from CODEOWNERS. Cartography's job is to put those facts in one graph.

Before the ontology work, queries often followed provider-specific node types. An AWS query might start at an ECSTask, while another cloud would need a different starting point and a different set of relationships. Adding a provider could therefore mean adding another version of the analysis.

The Cartography ontology does not replace those provider-specific nodes. It adds shared concepts to them. A ScalewayServerlessContainer can still contain the fields returned by Scaleway's API while also participating in the more general Container concept. Queries that only care that something is a container can use the shared label.

Scaleway and AWS map to the same graph concepts

The Scaleway integration imports serverless containers, registries, and images. There are two relationships that matter most for this example.

The first is the relationship between a running container and its image. Scaleway configures a container with an image tag, but tags can move. The registry module resolves the tag to a digest and creates RESOLVED_IMAGE, so a query can work with the image that is actually running.

The second is PACKAGED_FROM. The registry module reads OCI metadata and, when the build has recorded its source, connects the image to a code repository.

After those edges exist, the vulnerability path uses data that was already in the graph. Trivy connects CVEs to affected images and packages. It records a fixed package version when one is available. GitHub ingestion can connect a repository to its CODEOWNERS rules and owners.

None of this means Scaleway has a special vulnerability management feature. The Scaleway module describes its resources and how they connect to an image. The vulnerability query works with the shared Container, Image, Package, and CodeRepository concepts.

Following CVE-2024-3094 from a running container to its owner

The diagram below came from the original Cartography draft. It is a schematic of the relationships involved, not customer data or a dump of one tested graph.

A schematic vulnerability path from CVE-2024-3094 to a Scaleway workload, source repository, and CODEOWNER

The useful shape is the path through it. Starting from a CVE, the graph can lead to an affected image and package. A running container resolves to the same image, which tells us the image is in use. When Trivy has remediation data, the package can also point to a fixed version with SHOULD_UPDATE_TO.

In the other direction, PACKAGED_FROM connects the image to the repository that built it. If the repository is on GitHub and Cartography has ingested CODEOWNERS, the matching rule can point to an owner. That last part is conditional. A graph cannot derive ownership data that was never provided.

The query

Here is a simplified version of the Cypher. There is no reference to a Scaleway node type in it:

MATCH (c:CVE {cve_id: $cve_id})
MATCH (c)-[:AFFECTS]->(img:Image)
MATCH (ctr:Container)-[:RESOLVED_IMAGE]->(img)
WHERE toLower(ctr._ont_state) = 'running'
OPTIONAL MATCH (c)-[:AFFECTS]->(pkg:Package)
OPTIONAL MATCH (pkg)-[:SHOULD_UPDATE_TO]->(fix:TrivyFix)-[:APPLIES_TO]->(c)
OPTIONAL MATCH (img)-[:PACKAGED_FROM]->(repo:CodeRepository)
OPTIONAL MATCH (repo)-[:HAS_CODEOWNER_RULE]->(rule)-[:CODEOWNER]->(owner)
RETURN c, img, ctr, pkg, fix, repo, rule, owner

The query will also work for another provider whose running resources participate in the Container concept and resolve to an Image. Provider-specific details still matter during ingestion; they do not have to leak into every analysis that uses the data afterward.

The lesson: coverage should be cheap to extend

Scaleway support is useful, but the interesting part is what did not change. We did not add a Scaleway vulnerability pipeline or write another set of correlation queries. We taught Cartography how Scaleway resources map onto concepts the rest of the graph already understands, and the existing analysis kept working.

That is a useful constraint to keep. If every new provider needs its own logic for joining findings to workloads, images, repositories, and owners, provider coverage and security analysis are coupled. The system gets larger and more fragile with every integration. When the concepts are genuinely shared, model them once and keep the provider-specific work at the ingestion boundary. The cross-cloud permission work arrived at the same idea: the reasoning lives above the provider, so new providers can inherit it.

Two practical things follow.

You can use this approach in Cartography today. Connect your clouds, ingest Trivy results and source-control data, and run the query above. For workloads connected to the shared container and image model, it can show where a vulnerable image is running, where its code came from, whether a fix exists, and, when ownership data is present, who owns it. When the graph cannot answer one of those questions, the missing edge tells you which integration is incomplete.

If you want the result without maintaining all of that plumbing yourself, this is what SubImage’s vulnerability management is built to do. It connects scanner findings to what is actually running, the source repository, the available fix, and the team that owns it. Instead of rebuilding that context for every CVE, your security team can start with the vulnerabilities that affect deployed systems and the people who can fix them.

And if Cartography does not support your provider yet, adding it does not mean rewriting the vulnerability analysis. A provider module ingests its resources and attaches them to the shared concepts where they fit. A genuinely different runtime model may require extending the ontology, but that is different from copying the whole analysis stack. The developer guide walks through building a module, and missing providers are some of the most useful contributions to pick up.

Come add your cloud!