Browse documentation
Core concepts.
Four ideas explain most of the platform: a scan is a plan of tools in an untrusted band; a finding is a node in an ontology; lineage is a walk over provenance-tagged edges; a decision is a signed, fail-closed evaluation.
1 · Scans and the tool plan
A scan targets a repository, an image, a URL, an API specification, a cloud account or a cluster. For a repository the platform builds a tool plan: the native engine and the baseline tools always, plus language-specific tools for the languages it detects. All tools for a scan run in one isolated, short-lived environment.
Every scan ends in an explicit outcome: completed, partial (some tools missed their deadline or failed; results from the others are kept and the gap is shown) or failed with a reason — time-out, missing dependency or invalid configuration. Each tool has its own time limit, so a slow tool never hangs a scan.
2 · The finding ontology
Results are observations. They are accepted or quarantined, matched to existing entities using available identifying context, and folded into logical findings. A logical finding is an entity with edges: it affects a Package, a File span or a CloudResource; corroborating tool results become corroborates edges rather than duplicate rows.
The shared model connects repositories, builds, images, workloads, identities, findings and controls. Relationships retain their source and confidence so teams can distinguish evidence from a candidate connection.
Every edge carries a provenance class:
- observed — reported by telemetry, a provider API or a verified attestation (SCM webhook, CI run record, cluster state, SLSA provenance).
- derived — a deterministic join over immutable identifiers (image digest, full commit SHA, ARN, Kubernetes UID).
- inferred — a heuristic candidate (tag match, name similarity, uncorroborated OCI label). Displayed, never part of a strict path.
3 · Lineage, blast radius, exploit paths
Lineage walks the code-origin template Repository → Commit → Build → ContainerImage → Registry → Workload (→ KubeService → KubeIngress) using observed and derived edges. Hops are satisfied, missing (with reason no_producer_data, source_gap, unbound_endpoint) or conflicting (two claims disagree). Missing and conflicting are read-time states and are never stored as edges.
Blast radius shows the known workloads, services and ingress points associated with an affected asset. It depends on connected inventory and is not a guarantee that every affected asset has been discovered.
Exploit paths start at exposure edges and traverse identities, roles, policies and data stores; chokepoints and candidate interventions are ranked. An empty result says why: no_exposure_edges or no_attack_paths_computed.
Risk is a versioned model on a fixed scale with factor groups and an explanation per score; incremental scoring re-evaluates only what an event touched.
4 · Policy, decisions, disposition
Policies are Open Policy Agent Rego, authored directly or through the visual builder (rules → AND/OR groups → action, compiled to Rego from an allow-listed field model). Evaluation runs OPA over a structured input and parses the result; any evaluator error is a DENY with reason OPA_EVALUATION_FAILED. Control decisions are digitally signed and the audit log is hash-chained, so both can be verified independently.
Disposition (true positive, false positive, by design, accepted risk) is written only through POST /api/v2/findings/{id}/disposition by a signed-in principal with a reason code. Any other writer, including AI triage, is refused in the application and again in storage. Exceptions carry an owner, an expiry, an approver chain and optional dual control.
Next steps
- Policy authoring — write the Rego that gates a release.
- API reference — read lineage and record dispositions.
- Glossary — security and platform terms, explained.