Triage and exports
Not every finding deserves a code change today. The commands on this page record what you decided and carry that decision with your build artifacts:
acceptrecords a reviewed finding with a reason, an approver, and an expiry in.securock/exceptions.yaml, soauditstops failing on it until the date passes.vex exportwrites those decisions as a VEX document, so what you decided about an advisory can travel with the SBOM.sbom exportturnssecurock.lockinto a CycloneDX or SPDX bill of materials;sbom verifychecks an SBOM against the lockfile.
Accept findings
Use the finding id that audit prints:
sh
securock accept known-vulnerability:GHSA-xxxx-xxxx-xxxx \
--subject npm:lodash \
--reason "only used in a build script, tracked in ENG-142" \
--approver alice --expires 90d
securock accept list # active and expired exceptions
securock accept remove known-vulnerability:GHSA-xxxx-xxxx-xxxx --subject npm:lodash--reasonand--expiresare required.--expiresis a date (2026-12-31, the last day it applies, in UTC) or a number of days such as90d.--subjectlimits the exception to one package.npm:lodash@4.17.20matches that artifact;npm:lodashmatches any version. Without it, the exception covers every package with that finding.- For a vulnerability,
--justificationsays it does not affect you rather than that you accept the risk:component_not_present,vulnerable_code_not_present,vulnerable_code_not_in_execute_path,vulnerable_code_cannot_be_controlled_by_adversary, orinline_mitigations_already_exist. It only changes whatvex exportwrites. - Accepting the same finding and package again renews it.
- Exceptions live in
.securock/exceptions.yaml(override with--exceptions). Commit the file and review it like code. It never changessecurock.lockor any trust status; see Trust model. auditkeeps accepted findings in its output, marked suppressed (suppressedin JSON,suppressionsin SARIF), and they do not count toward--fail-on. Once an exception expires the finding returns, with anexception-expiredfinding alongside it.
VEX export
vex export writes the vulnerabilities you recorded with accept as a VEX document:
sh
securock vex export --author "Security Team" > product.openvex.json # OpenVEX 0.2.0
securock vex export --author "Security Team" --spec cyclonedx > product.vex.json # CycloneDX 1.6- An exception with
--justificationbecomesnot_affected, with your reason as the impact statement. Any other becomesaffectedwith an action statement,Risk accepted by alice until 2026-12-31: <reason>: you are affected and have chosen to wait. - Packages are named by purl. An exception that names no package covers every package in
securock.lockthat has the advisory; one with--subjectcovers only those. - Expired exceptions, exceptions for advisories not in
securock.lock, and exceptions that are not for a known vulnerability are left out. Packages with no purl (URL imports) are skipped. If nothing is left, the command fails instead of writing an empty document, since an OpenVEX document needs at least one statement. - In the CycloneDX form, each affected package is declared as a component with its purl as
bom-ref, so every reference resolves within the document. --authoris required: a VEX document says who vouches for it. The timestamp is the current time, orSOURCE_DATE_EPOCHwhen set, which also makes the output reproducible.
SBOM export and verify
sbom export turns securock.lock into a software bill of materials on stdout. It reads the lockfile, so run securock lock first and the SBOM describes exactly what you locked.
sh
securock sbom export > bom.cdx.json # CycloneDX 1.6 (default)
securock sbom export --spec spdx > bom.spdx.json # SPDX 2.3
securock sbom verify bom.cdx.json # compare against securock.lock- Each package carries a Package URL (
purl) and, when the lockfile digest is a standard SHA-1/256/384/512, ahashes/checksumsentry. Other digests, such as Go'sh1, are kept assecurock:digest. - Trust evidence (status and reasons, provenance, signature, capabilities, ownership, source-to-build chain) is written as
securock:*component properties in CycloneDX and assecurock:key=valueannotations in SPDX. - Licenses recorded as release health are exported: a license expression made of known SPDX identifiers becomes a CycloneDX
expression/ SPDXlicenseDeclared; any other text is a CycloneDX license name and stays out oflicenseDeclared. The raw text is always kept assecurock:license. - Known vulnerabilities and malicious-package reports from the lockfile appear in the CycloneDX
vulnerabilitieslist. - CycloneDX output is deterministic: it has no timestamp. SPDX requires a creation time and uses the current time. Set
SOURCE_DATE_EPOCHto stamp either format with a fixed time and make both reproducible. sbom verifyreports a finding for each package that is missing, unexpected, or differs in version, purl, digest, or trust status (and for a policy digest mismatch in CycloneDX). It exits1on any finding and supports--format json(sbom-verify-reportschema). It accepts SBOMs from other tools too, matching packages by purl. In SARIF output, results point at the SBOM file.
Next steps
- Usage — the lock / diff / verify loop and shared flags
- Trust model — what an exception does not change
- Source code analysis — findings for
sastuse the same acceptance flow