Triage findings
A finding is one issue a scan reported. Each finding carries two separate statuses.
triageStatusis zkao’s own verdict on the finding. You read it. You cannot set it.resolutionStatusis your team’s decision about it. You set it.
Reading findings needs the read scope. Every change on this page needs findings:write.
List findings
Section titled “List findings”The list holds every finding in the project, most severe first. Filter it to one scan with its id.
zkao findings listzkao findings list --scan <scanId> --limit 100const { items, total } = await zkao.listFindings({ scanId, limit: 100 });curl -H "Authorization: Bearer $ZKAO_API_TOKEN" \ "https://zkao.io/api/v1/projects/$ZKAO_PROJECT_ID/findings?scanId=<scanId>&limit=100"The list paginates with page and limit. The default limit is 50 and the maximum is 100. Each item has these fields.
| Field | Meaning |
|---|---|
title, location, category |
What the issue is and where. |
severity |
The effective severity: your override if set, otherwise zkao’s. |
triageStatus |
zkao’s verdict, such as CONFIRMED, FALSE_POSITIVE or DUPLICATE. |
confirmationEvidence |
For a CONFIRMED finding, POC when a proof of concept ran, or ANALYSIS when code analysis alone confirmed it. |
resolutionStatus |
Your team’s decision. New findings start at NOT_STARTED. |
notesCount |
How many comments the finding has. |
See List findings for the full schema.
Read one finding
Section titled “Read one finding”The detail view adds the description, the proof of concept report, the recommended fix, the commit, the repository, and every comment.
zkao findings get <findingId>const finding = await zkao.getFinding(findingId);console.log(finding.description, finding.pocReport, finding.notes);curl -H "Authorization: Bearer $ZKAO_API_TOKEN" \ https://zkao.io/api/v1/projects/$ZKAO_PROJECT_ID/findings/<findingId>ZK- labels
Section titled “ZK- labels”A finding page on zkao shows a short label such as ZK-3f9a2c1b. It is the last eight characters of the finding id. Every finding endpoint accepts it in place of the full id, with or without the ZK- prefix.
A label is unique within a project in practice, but not by construction. A label that matches two findings returns 409. Use the full id then.
Comment
Section titled “Comment”A comment is a Markdown note on the finding. Your team sees it on zkao.
zkao findings comment <findingId> "Reproduced on the release branch."const { noteId } = await zkao.addFindingNote(findingId, "Reproduced on the release branch.");curl -X POST -H "Authorization: Bearer $ZKAO_API_TOKEN" -H "Content-Type: application/json" \ -d '{"content":"Reproduced on the release branch."}' \ https://zkao.io/api/v1/projects/$ZKAO_PROJECT_ID/findings/<findingId>/notesThe response returns the new noteId. You can pin that note as the finding’s resolution note with Pin a note or the SDK’s pinFindingNote.
Override severity
Section titled “Override severity”The levels are CRITICAL, HIGH, MEDIUM, LOW and INFO. Clearing the override restores zkao’s severity.
zkao findings severity <findingId> LOWzkao findings severity <findingId> none # clear the overrideawait zkao.setFindingSeverity(findingId, "LOW");await zkao.setFindingSeverity(findingId, null); // clear the overridecurl -X PATCH -H "Authorization: Bearer $ZKAO_API_TOKEN" -H "Content-Type: application/json" \ -d '{"severity":"LOW"}' \ https://zkao.io/api/v1/projects/$ZKAO_PROJECT_ID/findings/<findingId>/severitySet a resolution
Section titled “Set a resolution”| Status | Meaning |
|---|---|
NOT_STARTED |
Nobody has looked at it yet. |
IN_PROGRESS |
Someone is working on it. |
RESOLVED |
Fixed. |
MITIGATED |
Not fixed, but its risk is reduced. |
WONT_FIX |
Accepted as is. |
FALSE_POSITIVE |
Not a real issue. |
DUPLICATE |
Already covered by another finding. |
A status alone records the outcome, not the reason. Attach the reason in the same call, in one of two ways.
noteis free text. It becomes a comment on the finding.reasonis a short code from a fixed catalog. It is also recorded as a comment.
Pass one or the other. When both are present, the note wins. Both are ignored for NOT_STARTED and IN_PROGRESS.
zkao findings resolution <findingId> FALSE_POSITIVE \ --note "The caller checks the length before this point."
zkao findings resolution <findingId> WONT_FIX --reason risk_acceptedawait zkao.setFindingResolution(findingId, "FALSE_POSITIVE", { note: { content: "The caller checks the length before this point." },});
await zkao.setFindingResolution(findingId, "WONT_FIX", { reason: "risk_accepted" });curl -X PATCH -H "Authorization: Bearer $ZKAO_API_TOKEN" -H "Content-Type: application/json" \ -d '{"resolutionStatus":"WONT_FIX","reason":"risk_accepted"}' \ https://zkao.io/api/v1/projects/$ZKAO_PROJECT_ID/findings/<findingId>/resolutionOver HTTP, note can also reuse an existing comment: {"existingNoteId": "<noteId>"}.
Reason codes
Section titled “Reason codes”Each status offers its own codes. A code from another status returns 400 with the valid list.
| Status | Codes |
|---|---|
RESOLVED |
fixed_in_code, fixed_upstream, code_removed |
MITIGATED |
compensating_control, limited_exposure, monitored |
FALSE_POSITIVE |
not_reachable, guarded_elsewhere, intended_behavior, misread_code, bad_assumption |
WONT_FIX |
risk_accepted, out_of_scope, not_worth_fixing, code_being_removed |
DUPLICATE |
duplicate_of_finding, same_root_cause |
A triage pass
Section titled “A triage pass”-
Find the latest completed scan.
Terminal window zkao scans list -
List its findings.
Terminal window zkao findings list --scan <scanId> -
Read each one in full, including the proof of concept.
Terminal window zkao findings get <findingId> -
Record the verdict, with the reason.
Terminal window zkao findings severity <findingId> MEDIUMzkao findings resolution <findingId> RESOLVED --reason fixed_in_code
Some knowledge applies to the whole repository, not one finding. A known non-issue is one example. A comment does not carry it into future scans. Put it in the repository guidance instead.

