Attack paths
The Toxic Combinations page, catalogue chains and computed paths, the score, the detail panel, how to break a chain, and the Sapper's proposals.
The attack path module links findings and graph relationships that, taken one by one, stay medium, but that put end to end lead from the Internet to data, an administrative identity, a key or a cluster. The "Toxic Combinations" page presents the result. The principle is described in Attack paths; this page describes the module as it is.
Two sources of paths
| Source | What it is | Rule keys |
|---|---|---|
| Catalogue chains | Known combinations, written one by one as graph patterns: an exposed resource carrying such a finding and reaching such data. Each chain is a rule of the "Policies" page, "Toxic Combination" tab, with its severity, category and "Status" switch | TOX-… |
| Computed paths | Paths nobody wrote: Ctadel reduces the graph to what an attacker uses (where they get in, what they exploit, which identity they obtain, what it reaches) and walks it, multiplying probabilities. A path is filed by what it reaches | PATH-DATA (sensitive data), PATH-ADMIN (administrative identity), PATH-KEY (key or secret store), PATH-CLUSTER (Kubernetes cluster), PATH-STORE (data store with no classification) |
For computed paths, the probability of each step is fixed once and for all by Ctadel so that every path is scored the same way: for instance 0.9 for a public IP behind a security group open to the world, 0.5 behind a closed one, 0.7 behind a public load balancer, 1.0 for a public bucket; 0.9 for a secret verified active, 0.5 for an unverified secret, 0.1 for an inactive one; 0.9 for an identity obtained through IMDSv1, 0.6 through IMDSv2; 0.6 for a container escape. An exposed host with no known CVE keeps an exploit probability of 0.05: it runs an application. A path has at most 4 steps; Ctadel keeps the 5 most probable paths per entry point and 500 in all. A search that reaches these limits returns what it found without closing the paths it could not revisit.
Score and severity
- Catalogue chain: a base of 80 for
CRITICAL, 60 forHIGH, 40 forMEDIUM, 20 forLOW; plus 5 per link (at most 15) and 2 per resource (at most 10); capped at 100. Ctadel then adjusts this score with what it knows about the final resource: +15 when it is reachable from the Internet, +15 when it carries an exploitable CVE, +10 when it holds something valuable, and -15 for a host or data store that is neither reachable nor exploitable. The result stays between 1 and 100. - Computed path: the product of the probabilities, multiplied by the target's impact, gives a score between 0 and 1. Severity follows:
CRITICALfrom 0.5,HIGHfrom 0.2,MEDIUMfrom 0.05,LOWbelow. The displayed score is 20 + 80 × the square root of the score: a certain path to sensitive data is worth 100, a one-in-twenty path is worth 38.
The Toxic Combinations page
The "Toxic Combinations" page (entry of the same name in the menu) lists the detected chains, highest score first, with the columns "Risk", "Severity", "Title", "Category" and "Resources" (the number of resources on the path). Filters are "Severity" and "Category" ("Exposure", "Lateral Movement", "Privilege Escalation", "Data Access"); a "Search toxic combinations..." field and an "Export CSV" button complete the list. The page loads the 100 highest-scoring chains.
A click opens the detail panel, with four tabs:
| Tab | Content |
|---|---|
| "Overview" | The chain's description, the affected resources (each opens its panel), the rule's references, and the "Risk score" with its breakdown: severity, "Path & resource bonuses", number of hops and resources affected |
| "Attack path" | The "Attack path visualization": the nodes of the path in order, with their type. Clicking a node opens a card with its type, name, identifier and the number of "open findings" it carries; "View more" opens the resource's panel. For a computed path, each node carries its role (entry, pivot, target) and the reason for each step |
| "Remediation" | The rule's remediation steps, and the Mason (see Assistants) |
| "History" | The finding's status changes |

Breaking a chain
A chain exists only as long as all its links exist. Each link is a fact of the graph: an open finding on a resource, an exposure, an access right, a secret, a CVE. Fixing a single link is enough: at the next evaluation, the chain no longer matches and the finding is resolved, with an entry in its history. Findings are closed only when the evaluation was complete; an interrupted evaluation leaves the chains it did not revisit open.
To choose the link, the "Attack path" tab shows the number of open findings on each node, and the Mason proposes a "Link to cut" under "Remediation": it prefers the link managed by code and the one with the fewest dependants, and says why. The finding of a fixed resource can be re-evaluated without waiting for the next inventory with "Verify the fix".
Disabled rules
Some catalogue chains ship disabled by default. In "Policies", "Toxic Combination" tab, they appear with the "Inactive" status; enabling them by hand produces nothing.
The Sapper's proposals
The Sapper is the agent that searches the graph for paths that are neither in the catalogue nor among the computed paths: chains of medium weaknesses that add up, or a CVE whose meaning matters (an SSRF next to IMDSv1). It only reads. Its "Sapper" block sits at the top of the "Toxic Combinations" page.
- "Search now" starts a search; only one runs at a time. Ctadel first surveys the graph ("Reading the graph…"): the number of nodes, the targets worth reaching, and those no known path reaches. Without a graph or without a target, the search stops there and says so.
- The model walks back from the targets towards what is exposed, checks each chain against the graph (a step that does not exist ends the chain), discards what a rule or an open path already covers, then files at most 5 proposals per search. A proposal that names types or relationships the graph does not have is refused.
- The report appears: "N nodes read, N targets, N reached by no known path; N walked back, N filed", and when relevant "The search stopped on its budget: there may be more to find."
- Each proposal shows its title, severity, "confidence N%", the number of current matches, the "Verified path", the "Evidence" (the facts read, link by link) and the "Generalised rule (Cypher)".
- "Accept as a rule" creates a custom toxic rule of the instance (key
SAPPER-…), evaluated at once on the first resource of the path and then at each scan. "Reject" archives the proposal. Nothing enters the catalogue without this action.
The Sapper is available only to users whose role covers every project, because it reads the whole graph. It also runs at a regular interval when the instance operator has set one; by default, this schedule is off.
Limits
- Computed paths only know the entry points, exploits and steps Ctadel can weigh: public IP and security groups, load balancer, Kubernetes service, cluster endpoint, public function, public bucket and database; network-vector CVEs; instance identity, service account, found secret, effective access right, container escape. What is not in that list is not a step.
- Probabilities are judgements fixed by Ctadel, not measurements. They serve to rank paths against each other.
- A search that reaches 4 steps or 500 paths is truncated; it does not close the findings of paths it did not revisit.
- Disabled chains stay in the catalogue without firing; the reason is not shown in the interface.
- The page loads at most 100 chains; the counter at the top gives the total.
- The Sapper's proposals depend on a language model: it may find nothing, or stop before exhausting the targets. An accepted proposal is a graph rule written by the model and checked by Ctadel on its type, relationship and property names only; its relevance is what you grant it by accepting.
- Kubernetes workload identity (IRSA, Workload Identity) is not modelled: a path from a pod to cloud data through it is not found.