Best practices for Syft + Grype container image SBOM and vulnerability scanning workflow

Hi Anchore community,

I’m currently using Syft and Grype for private container image security reporting.

Workflow:

syft <private-registry>/<namespace>/<image>:<tag> \
  -o cyclonedx-json \
  --scope squashed \
  > image.cyclonedx.json

grype sbom:./image.cyclonedx.json
–add-cpes-if-none
–show-suppressed
–output template
–template /path/to/html_Grype.tmpl
–distro auto
–verbose \

report_image.cyclonedx_sbom.html

I want to confirm whether this is the best workflow for accurate and deep container vulnerability scanning.

Questions:

  1. Is --scope squashed the best choice for final image/runtime assessment, or should I use --scope all-layers?
  2. Is scanning grype sbom:./image.cyclonedx.json equivalent in accuracy to scanning the image directly with grype <image>?
  3. Should I use --add-cpes-if-none, or can it increase false positives?
  4. Is --distro auto reliable when scanning a CycloneDX SBOM generated by Syft?
  5. Are there any recommended flags/configs to improve accuracy and reduce false positives?
  6. Is there a way to make Syft prefer Docker/local image provider by default for private registry images?

Thanks!



Hi @danvuong0514 thanks for the post. These are great questions!

That depends. The main difference is that packages that are added in one layer and then later removed, so that they’re not in the final image, will show up in the scan with all-layers but not with squashed.

No. CycloneDX is lossy compared to Syft’s native format. syft -o json > mysbom.json ; grype mysbom.json does result in equivalent scans right now.

It can increase false positives, but may also decrease false negatives.

You should scan a syft -o json SBOM, in which case syft will detect the distro from /etc/os-release and similar. I don’t know off the top of my head why --distro auto does with CycloneDX.

We try to make the defaults be as good as we can.

Syft by default will try top guess what it’s input is and try to fetch it however it can. If you pass --from docker it will only try to use the local docker daemon.

Let me know if you have any questions! I hope that helps!