Findings
How findings are structured, ingested, and staged in Bevor
A finding is a single security observation — tied to a specific location in your code, carrying a severity and an explanation, and always living inside an analysis version. This page covers what a finding actually contains, the ways to get findings into Bevor, and the staging lifecycle every finding goes through before it becomes part of your security posture.
Anatomy of a Finding
Every finding has two required parts — a node (the entrypoint it impacts) — and 3 optional parts — metadata (what it is), a source (who produced it), and a location (where it occurs, in the context of the entrypoint).
Location
Bevor's security model is entrypoint-centric: findings are ultimately understood in terms of the entrypoints that reach them. A location can be expressed three ways:
-
By node id — the most direct method, for callers that already know Bevor's graph. Two ids are involved:
node_id— the entrypoint being analyzed.location_id— where the finding actually occurs (optionally), if different from the entrypoint (e.g. "entrypointAcalls into vulnerable functionB" —Ais thenode_id,Bis thelocation_id).
location_iddefaults tonode_idwhen omitted. Providinglocation_idalone — without anode_id— fans the finding out to every entrypoint that reaches that node. This is intentionally permissive: you can report a vulnerability in a shared internal function once, and Bevor will surface it against every entrypoint it affects. -
By physical location — a file URI plus a region (line range, character offset/length, or byte offset/length). For tools that only know source coordinates and haven't resolved them to a Bevor node. Bevor resolves the region to node(s) internally.
-
By logical name — a fully-qualified symbol name (e.g.
Owner.onlyOwner). For tools that only have a symbol reference.
Metadata
When present, metadata describes the finding itself: type, level (severity), name, explanation, and optionally recommendation and reference.
Note
Metadata is all-or-nothing. Submitting a finding without metadata is not an error — it explicitly marks that location as analyzed with no issues found, distinguishing "not yet looked at" from "looked at, clean." This matters for coverage: without it, there's no way to tell whether an entrypoint was skipped or was checked and passed.
In Bevor, type is well-defined, but we allow for you to pass any arbitrary type for your own purposes.
Source
An optional free-text field identifying which tool or pipeline produced the finding — bevor internal, bevor chat, slither, the name of your own scanner or agent, etc. Left empty for ad hoc or manually-entered findings. We highly recommend populating this field so you can assess performance and utility across different tool sets.
Getting Findings Into Bevor
As covered in Analyses, findings reach Bevor three ways: Bevor's own security pipeline, your own pipeline via BYOS, or Bevor's chat interface. This section is about the BYOS path — bringing findings from anywhere else.
Bevor's finding schema is the same whether it's typed by a human, generated by a script, or produced by an LLM agent — there's one shape to target, not a different format per integration:
- Add one finding at a time — for manual triage or a single ad hoc observation. Via the Bevor CLI,
.yaml/.ymlfiles are supported. See the SDK or the CLI for more information. - Bulk import — for a batch from a tool or pipeline run. For the CLI, SARIF
.sariffiles, a.yaml/.ymlfile (including multiple findings in one file,----separated), or a directory of YAML files are supported. See the SDK or the CLI for more information.
Tip
Any tool — including an LLM-driven agent — can target the native JSON/YAML schema directly rather than going through SARIF. Publishing the schema and a worked example means an integration only needs to produce well-shaped output once, with no translation layer in between.
An example finding, using the node-id location strategy:
source: my-local-ai-tool
metadata:
type: reentrancy
level: high
name: Reentrancy in withdraw()
explanation: >
External call to msg.sender happens before the balance is updated,
allowing a malicious contract to re-enter withdraw() and drain funds.
recommendation: Apply checks-effects-interactions — update balances before the external call.
location:
strategy: node_id
node_id: node_a1b2c3
location_id: node_d4e5f6
Staging and Committing
However a finding arrives, it doesn't immediately become part of the analysis version's persisted finding set. Findings are staged by default — think git add. A staged finding exists as a pending change against the current analysis version.
Each staged change carries a draft operation describing what will happen on commit — whether a new finding will be added, an existing finding's metadata will be edited, or a finding will be removed. This is what lets you review a batch of incoming findings (from a CI run, an agent, a bulk import) as a set of proposed changes before they take effect, the same way you'd review a diff before merging it.
- Committing staged changes produces a new, immutable analysis version — see Creating New Versions.
- Reverting a specific staged change discards it before commit, without affecting any other pending changes. Useful when a bulk import or an agent run produces something you don't want to keep, or you want to further triage with Bevor chat to de-dup, triage, or attest to these staged changes.
- Editing a finding's metadata works the same way — it stages a metadata change rather than mutating the finding in place, and goes through the same commit/revert lifecycle as an addition.
Warning
Staged findings are not yet real. If you're building an integration that reads findings back to check ingestion succeeded, remember that a newly-added finding won't appear in the committed set — and won't affect security posture — until it's committed.
Acknowledgement vs. Staging
Acknowledgement is a separate, orthogonal concept from staging. Staging is about whether a change has been committed to the analysis version's history; acknowledgement is a review/triage status on a finding that's already committed — has a human looked at it and accepted, dismissed, or actioned it. Findings can be filtered by acknowledgement status independently of their staged/committed state, and acknowledging a finding has no effect on whether it's part of any particular analysis version.

