---
title: "Get Finding"
method: GET
path: "/v1/findings/{finding_id}"
tags: ["findings"]
---

# Get Finding

`GET /v1/findings/{finding_id}`

## Request

- Base URL: `https://api.cybret.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.cybret.ai/v1/findings/{finding_id}`
- Auth: HTTP bearer

## Path parameters

- `finding_id` string, required

## Response `200`

Successful Response

- NormalizedFinding: Stable, tenant-scoped finding suitable for APIs and exports.
  - `finding_id` string, required
  - `tenant_id` string, required
  - `run_id` string, required
  - `stable_id` string, required
  - `severity` 'info' | 'low' | 'medium' | 'high' | 'critical', required
  - `confidence` number, required
  - `title` string, required
  - `description` string, required
  - `remediation` string, nullable
  - `cwe_ids` string[]
  - `owasp_categories` string[]
  - `endpoint` string, required: HTTP path or source file path. File-path locators (for example handlers.go) do not need a leading slash.
  - `http_method` string, required: HTTP verb or store token. CODE is a store token for file-path locators, not a live HTTP verb.
  - `identity_id` string, nullable
  - `owner_identity_id` string, nullable
  - `peer_identity_id` string, nullable
  - `remediation_path` string, nullable
  - `remediation_line` integer, nullable
  - `remediation_symbol` string, nullable
  - `auth_mode` 'unauthenticated' | 'secret_store' | 'controller' | 'mixed' | 'unknown': Secret-free description of how report evidence was collected.
  - `evidence` object[]
  - `artifact_refs` ArtifactRef[]
    - `digest` string, required
    - `media_type` string, required
    - `producing_activity` string, required
  - `reproduction` string, nullable
  - `proof` ProofBundle: A finding's complete, self-contained, replayable proof. The bundle is the unit that makes the product promise true: it can be stored, exported, and re-executed later as a regression test without the original run, database, or credentials. Three digests serve different purposes and are deliberately layered: ``finding_ref`` Stable identity of the *finding* (endpoint, class, title). Constant across runs, so proofs for the same issue can be correlated over time. ``replay.sequence_digest`` and ``artifact_hashes`` Stable identity of the *evidence*. Unchanged by later grading, so the recorded exchanges can be integrity-checked independently. ``proof_digest`` Covers the whole graded proof, including which pillars are satisfied. It therefore changes when a reproduction upgrades the grade — that is intended: a differently graded proof is a different proof.
    - `proof_id` string, required
    - `finding_ref` string, required
    - `endpoint_key` string, required
    - `vuln_class` string, required
    - `replay` ReplaySequence, required: The exact, ordered action sequence that reproduces a finding.
      - `actions` ReplayAction[], required
        - `index` integer, required
        - `role` 'setup' | 'baseline' | 'attack' | 'control' | 'observe', required: Why an action exists in the sequence. The roles carry evaluation semantics: ``BASELINE`` actions are positive controls whose failure makes a later replay inconclusive rather than fixed, and ``ATTACK`` actions are the decisive ones whose assertions define whether the vulnerability still reproduces.
        - `method` string, required
        - `url` string, required
        - `headers` object
        - `query` object
        - `body` string, nullable
        - `identity_label` string, nullable
        - `assertion` ReplayAssertion: The machine-checkable condition that made an action decisive. An assertion is what turns a finding into a regression test: re-running the action later either satisfies it (the vulnerability persists) or does not (it was fixed).
          - `statuses` integer[]
          - `require_non_empty_body` boolean
          - `body_digest` string, nullable
          - `contains` string, nullable
          - `header_equals` array[]
            - unknown[]
              - …
          - `value_digests` array[]
            - unknown[]
              - …
        - `evidence_id` string, nullable
        - `note` string, nullable
      - `sequence_digest` string, required
    - `origin_worker` WorkerIdentity: Identity of the worker that executed a reproduction. Fresh-context reproduction is only meaningful if the second worker is demonstrably distinct from the first, so the pair ``(worker_id, context_digest)`` is compared rather than trusted prose.
      - `worker_id` string, required
      - `context_digest` string, required
    - `reproductions` ReproductionAttempt[]
      - `worker` WorkerIdentity, required: Identity of the worker that executed a reproduction. Fresh-context reproduction is only meaningful if the second worker is demonstrably distinct from the first, so the pair ``(worker_id, context_digest)`` is compared rather than trusted prose.
        - `worker_id` string, required
        - `context_digest` string, required
      - `origin_worker` WorkerIdentity: Identity of the worker that executed a reproduction. Fresh-context reproduction is only meaningful if the second worker is demonstrably distinct from the first, so the pair ``(worker_id, context_digest)`` is compared rather than trusted prose.
        - `worker_id` string, required
        - `context_digest` string, required
      - `attempted_at` string, date-time, required
      - `reproduced` boolean, required
      - `observation_digest` string, nullable
      - `note` string, nullable
    - `negative_controls` NegativeControl[]
      - `kind` 'identity' | 'object' | 'payload', required: What the negative control varied in order to isolate the cause.
      - `description` string, required
      - `identity_label` string, nullable
      - `attack_status` integer, nullable
      - `control_status` integer, nullable
      - `distinguishing` boolean, required
      - `evidence_id` string, nullable
    - `state_evidence` StateEvidence: Before/after observations bracketing a state-changing action.
      - `before` ObservedState, required: A single point-in-time observation of target state.
        - `label` string, required
        - `status_code` integer, nullable
        - `body_digest` string, nullable
        - `row_count` integer, nullable
      - `after` ObservedState, required: A single point-in-time observation of target state.
        - `label` string, required
        - `status_code` integer, nullable
        - `body_digest` string, nullable
        - `row_count` integer, nullable
      - `changed` boolean, required
      - `note` string, nullable
    - `blind_signal` BlindSignal: Evidence for a vulnerability with no direct in-band response signal. ``applicable`` is false for findings whose evidence is fully in-band; the pillar is then not required. When it is applicable, ``observed`` must be backed by a planted canary or an out-of-band interaction. Canary values are stored only as digests so the marker cannot be replayed by a third party.
      - `applicable` boolean
      - `mechanism` 'not_applicable' | 'planted_canary' | 'out_of_band': How a vulnerability without an in-band signal was observed.
      - `canary_digest` string, nullable
      - `observed` boolean
      - `note` string, nullable
    - `artifact_hashes` object
    - `required_pillars` ProofPillar[], required
    - `satisfied_pillars` ProofPillar[], required
    - `confidence_tier` 'unsupported' | 'reported' | 'corroborated' | 'proven', required: Explicit confidence, derived from which pillars a proof actually carries. Ordered weakest to strongest. The tier is computed from evidence, never reported by a model, so two findings with the same tier carry the same class of proof.
    - `confidence` number, required
    - `claimed_confidence` number
    - `rationale` string
    - `created_at` string, date-time
    - `scanner_version` string
    - `proof_digest` string, required
    - `missing_pillars` ProofPillar[], required: ADR-0003 pillars this proof requires and does not satisfy. Empty when every required pillar is met (including a proven tier). Non-empty when confidence_tier is not proven and pillars are unmet, so a client can explain UNPROVEN.
  - `proof_id` string, nullable
  - `proof_digest` string, nullable
  - `confidence_tier` 'unsupported' | 'reported' | 'corroborated' | 'proven': Explicit confidence, derived from which pillars a proof actually carries. Ordered weakest to strongest. The tier is computed from evidence, never reported by a model, so two findings with the same tier carry the same class of proof.
  - `status` 'open' | 'fixed' | 'reopened' | 'accepted_risk' | 'false_positive' | 'not_reproduced'
  - `status_note` string, nullable
  - `linked_pr` string, nullable
  - `verify_outcome` 'fixed' | 'reproduced' | 'inconclusive', nullable
  - `confirmation` 'needs_review' | 'confirmed' | 'refuted' | 'inconclusive': Grey/black oracle state for a White CODE hypothesis. DAST rows leave this unset. White ingest is ``needs_review`` until a live probe writes ``confirmed`` or ``refuted``. ``inconclusive`` is a writeback-only verdict; locally the row stays ``needs_review``.
  - `confirmation_settled_at` string, date-time, nullable: When Grey set confirmation to confirmed or refuted and did not attach a proof bundle. proof.created_at is the settlement clock when a bundle is present. Null when confirmation is unsettled or the row was stored before this column existed. White republish arrives as needs_review; scanner_republish_verdict copies this value from the previous row, so last_observed_at can move without recording a new Grey judgment.
  - `live_confirmed` boolean: True when a captured live exchange matched this CODE finding's route and method. Derived from evidence.exchange. Does not change severity, confirmation, or the sink gate.
  - `evidence_class` string, nullable: What the evidence demonstrated (sink_policy.EvidenceClass value). Unset is not a sink. Medium+ without real evidence is capped.
  - `severity_downgrade_reason` string, nullable: Stable reason recorded when a gate capped severity: 'sink_absent' (ADR-0003) or 'evidence_absent' (no real evidence). None when not downgraded.
  - `original_severity` 'info' | 'low' | 'medium' | 'high' | 'critical'
  - `compose_provenance` 'white' | 'website-dast' | 'both', nullable: Compose plane that produced this finding: white (repo CODE), website-dast (live Grey/Black), or both (White hypothesis confirmed by website DAST). Absent when the run is not a White+website compose.
  - `risk_score` number, nullable: Published 0-10 score copied from an upstream risk_score. Read a present score as Critical at or above 9.0, High at or above 7.0, Medium at or above 4.0, Low at or above 1.0, otherwise Info. The band does not replace severity.
  - `plane` string, nullable: White finding plane copied from upstream (code, sast, white, secret, sca, iac, container, dast). Null on Grey/Black rows and on findings ingested before the column existed. Customer severity for unconfirmed CODE/SAST uses this plane; it does not replace severity.
  - `repository` string, nullable: Repository locator White published (owner/name or the same class of repo string). Null when the payload did not name one. Not part of stable_id.
  - `severity_score` number, nullable: Published 0-10 score copied from an upstream severity_score. Does not replace severity. When risk_score is absent, the same number is also stored as risk_score.
  - `location` string, nullable: Repository-relative file path White published. Display and export only — line numbers stay on remediation_line and are not part of stable_id when content_hash is present.
  - `code_context` CodeContext: Customer-safe code context for a White/CODE finding. Carries what an engineer needs to judge impact: whether a route reaches the code, which route, the cited source and the code-graph path. It never names the detector, the rule, or the rule message.
    - `reachability` 'reachable' | 'not_traced' | 'client_only', nullable: reachable: coverage uniquely named one inventoried HTTP route. not_traced: no unique server route was tied to the sink. That is not proof it is unreachable. client_only: the sink is a client fetch, so no server route is claimed. Null when upstream and coverage said nothing.
    - `grounded` boolean, nullable: True when every claim cites source White verified.
    - `entrypoint` string, nullable: Route that reaches the code, as 'METHOD /path'. Never invented.
    - `excerpts` CodeExcerpt[]
      - `path` string, required
      - `start_line` integer, required
      - `end_line` integer, required
      - `highlight_line` integer, nullable: Finding line inside this window. Null when it falls outside.
      - `text` string, required
    - `flow` string[]: Ordered code-graph nodes from input to the flagged call.
    - `commit_sha` string, nullable: Commit White scanned. Null when the scan did not report one.
  - `suggested_owners` SuggestedOwners: CODEOWNERS match persisted for a finding's file path. ``owners`` is the last matching rule, in file order. ``source_path`` is the CODEOWNERS file. ``pattern`` is that rule's pattern. Null on the finding when publish had no match.
    - `owners` string[], required
    - `source_path` string, required
    - `pattern` string, required
  - `assignee` FindingAssignee: Customer view of who is assigned. Never an email hash.
    - `id` string, required
    - `display_name` string, nullable
  - `provenance` PatternEngineProvenance: Structured PE attribution. Applicability score is not CVSS.
    - `source` 'pattern_engine'
    - `pattern_id` string, required
    - `score` number, required
    - `band` 'high' | 'medium' | 'low', required
    - `operator` string, nullable
  - `secret_mask` string, nullable: Masked matched secret (for example the first and last four characters). Null when no matched secret was sealed. Never the full value.
  - `revealable` boolean: True when ciphertext is stored for this finding and POST /v1/findings/{finding_id}/reveal can return the plaintext to a caller who can read the finding. False for historical rows that never stored a matched secret.
  - `first_observed_at` string, date-time, required
  - `last_observed_at` string, date-time, required
  - `fixed_at` string, date-time, nullable
  - `reopened_at` string, date-time, nullable
  - `scanner_version` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/cybret/apis/api-scanner-control-plane.md) · [All operations](https://skmtc.dev/cybret/apis/api-scanner-control-plane/llms.txt) · [OpenAPI document](https://skmtc.dev/cybret/apis/api-scanner-control-plane/revisions/4c9b522246af?raw)
