sbom_generate and vulnerability_scan¶
Software-composition analysis. sbom_generate catalogs what a target is built
from, using Syft. vulnerability_scan matches
packages against known vulnerabilities, using
Grype.
Syft and Grype are separate installs
Both must already be on PATH. Kerkov never downloads, installs, or updates
them — it invokes what you have, as a fixed argument vector with no shell.
They are two tools rather than one so an SBOM can be kept, inspected, and reused. Generate it once, then scan it as many times as the vulnerability database changes. Grype can also catalog a directory or image directly when a reusable SBOM is not worth having.
Target selection¶
Both tools take a target plus a source_type that says how to read it.
source_type |
sbom_generate |
vulnerability_scan |
|---|---|---|
directory |
✓ | ✓ |
file |
✓ | ✗ — scan the containing directory instead |
image |
✓ | ✓ |
sbom |
✗ — Syft produces SBOMs | ✓ |
Local targets must stay inside the engagement workspace. This is stricter
than read and write, which honour absolute
paths: a scan walks an entire tree, so the blast radius of a mistyped target is
much larger. Copy or clone what you want scanned into the workspace first.
Container images are the exception — they are not workspace paths. image_source
selects where the image comes from: auto, docker (a local daemon), or
registry (bypassing any local runtime). For images, scope chooses between the
squashed filesystem and all-layers.
sbom_generate¶
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
target |
string | . |
Workspace-local directory or file, or an image reference. |
source_type |
directory | file | image |
directory |
How to read the target. |
image_source |
auto | docker | registry |
auto |
Images only. |
output_format |
syft-json | cyclonedx-json | spdx-json |
syft-json |
Artifact format. |
scope |
squashed | all-layers |
squashed |
Images only. |
exclude |
array[string] | — | Syft path-exclusion globs. |
timeout_seconds |
integer | 300 |
Maximum Syft runtime. |
max_packages |
integer | 50 |
Packages returned to the model. The complete SBOM stays in the artifact. |
Returns¶
A bounded package summary as JSON output. The complete SBOM document is written to
artifacts/sbom/ in the engagement workspace, under a generated collision-proof
name, and its exact path comes back in metadata.report_artifact. The scanner's
console log lands beside it as metadata.log_artifact.
The JSON output carries status, engine, engine_version, runtime, format,
source, source_type, package_count, returned_package_count, packages_truncated,
counts_by_type, the packages themselves, and artifacts with the report and
log paths.
For a completed scan, metadata carries status, engine, format, package_count,
packages_truncated, report_artifact, log_artifact, and runtime_source.
A scan that finishes but whose report cannot be summarized returns
status: "completed_unsummarized" with the artifact paths — the SBOM exists and
is readable even when Kerkov could not normalize it.
Examples¶
{ "target": "src/", "source_type": "directory" }
A reusable CycloneDX SBOM of an image:
{
"target": "nginx:1.25",
"source_type": "image",
"image_source": "registry",
"output_format": "cyclonedx-json"
}
vulnerability_scan¶
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
target |
string | . |
Workspace-local directory or SBOM file, or an image reference. |
source_type |
directory | image | sbom |
directory |
How to read the target. |
image_source |
auto | docker | registry |
auto |
Images only. |
scope |
squashed | all-layers |
squashed |
Images only. |
minimum_severity |
unknown | negligible | low | medium | high | critical |
unknown |
Minimum severity in the summary. The full report always keeps every match. |
only_fixed |
boolean | false |
Report only vulnerabilities with a known fix. |
exclude |
array[string] | — | Grype path-exclusion globs, for cataloged sources. |
update_database |
boolean | true |
Let Grype check for and download its vulnerability database. |
timeout_seconds |
integer | 600 |
Maximum Grype runtime, database update included. |
max_findings |
integer | 50 |
Findings returned to the model. |
update_database defaults to true because a stale database is a scan that
misses things silently. Set it to false only for a deliberately offline scan
against a cached database — and expect the results to be as old as the cache.
Returns¶
A severity-sorted summary as JSON output. The complete Grype JSON report goes to
artifacts/vulnerability-scans/ in the engagement workspace, with its path and
the scanner log's path in metadata.report_artifact and metadata.log_artifact.
The JSON output carries status, engine, engine_version, runtime, source,
source_type, database (including when it was built), match_count,
filtered_match_count, returned_finding_count, findings_truncated,
minimum_severity, counts_by_severity, the findings, and artifacts.
For a completed scan, metadata carries status, engine, match_count,
filtered_match_count, findings_truncated, report_artifact, log_artifact,
runtime_source, and database_built.
Matches are a successful scan
success: false means the scan did not run — Grype was missing, the target
was unreadable, the run timed out. Forty critical findings is
success: true. Do not read a failure as "clean" or a success as "safe".
A failure carries reason and diagnostic_tail — the end of the scanner log — so
the cause is visible without reading the artifact.
Examples¶
Scan the SBOM generated above, using the path sbom_generate returned in
metadata.report_artifact:
{ "target": "artifacts/sbom/sbom-toolu_01abc-8f3k2p.cyclonedx.json", "source_type": "sbom" }
Actionable findings only:
{
"target": ".",
"source_type": "directory",
"minimum_severity": "high",
"only_fixed": true
}
An image straight from a registry:
{ "target": "target.example/api:latest", "source_type": "image", "image_source": "registry" }
Approval¶
Both prompt in strict and normal and run automatically in permissive and
yolo. Neither has an allow rule, and the comment in approvals.yaml says why:
a run may pull an image from a registry, refresh Grype's vulnerability database,
write report artifacts, and consume substantial CPU, disk, and network.
Approval offers no broad rung for either tool — a saved approval covers that
call and no other, since the cost of a run depends entirely on its target.
timeout_seconds never reaches a saved rule.
Both are gated by
EXECUTION_ENABLED; with execution off,
calls return metadata.policy = "execution_disabled".
Related¶
cve_lookup— a scan says which CVEs apply;cve_lookupsays which of them matter. KEV listing and EPSS beat a raw CVSS ranking.sast_scan— vulnerabilities in the code you wrote, rather than in the dependencies you pulled.read— open the complete report atmetadata.report_artifact; filter large reports withexecto inspect findings omitted from the summary.recall— retrieve a previous scan's returned summary. The report file is not automatically indexed in the knowledge base.exec— for Syft and Grype options these tools do not expose. You lose the artifact handling and the bounded output.