Skip to content

Add a kics2hdf convert command (native JSON, not SARIF) #9618

Description

@clem-field

Summary

There is no KICS converter in hdf-libs, heimdall2 or the SAF CLI today. KICS
(Checkmarx, Apache-2.0) is a widely used IaC scanner covering Terraform,
CloudFormation, ARM, Kubernetes, Ansible, Docker, CI/CD definitions and more —
1,811 queries in the current image.

KICS emits SARIF, so sarif2hdf is a partial path. It is a lossy one, and the
native JSON carries materially more.

Measured fidelity gap

Scanned a real Terraform tree with checkmarx/kics:latest, emitting JSON and
SARIF from the same run: 849 findings across 72 queries.

What SARIF preserves — and this is better than most scanners manage — is the CWE
taxonomy: 72 of 72 rules carry a proper relationships[].target against a
CWE toolComponent. Rule name, description, helpUri and riskScore also
survive.

What SARIF drops:

Native field Fate in SARIF Why it matters
expected_value dropped on all 849 findings the message keeps only actual_value, so you get what it is and never what it should be
issue_type dropped MissingAttribute 767 / IncorrectValue 68 / RedundantAttribute 14 — add-a-block versus fix-a-value
similarity_id dropped KICS's own stable finding fingerprint, the natural cross-run dedup key
resource_name, search_value, description_id dropped
severity coarsened 5 → 4 CRITICAL and HIGH both collapse to error

resource_type survives only as prose inside the message string, not as a
structured field, so it cannot be filtered on.

Why this is a cheap converter to build

Unlike most scanners, KICS ships its own catalog as data: 1,811
metadata.json files under /app/bin/assets/queries/, each with id,
queryName, severity, category, descriptionText, descriptionUrl,
platform, cloudProvider, cwe and riskScore, with the rule's query.rego
beside it. Nothing has to be reverse-engineered or synthesized to produce
profile-grade output.

Every query carries a cwe, so tags.nist resolves through the existing CWE
mapping with no new mapping table.

Proposed mapping

HDF field Source
control / requirement id query_id (stable UUID)
title query_name
desc description
impact severity, five levels — see note below
tags.nist / tags.cci derived from cwe
tags platform, cloud_provider, category, risk_score, issue_type, resource_type
refs query_url
code_desc file_name, line, resource_type, search_key
results[].message expected_value vs actual_value — the remediation pair
passthrough scan counters, files_scanned, queries_total, kics_version

Granularity: one control per query, with each occurrence a result. KICS already
groups its output that way — queries[].files[] — so it maps directly.

Gotchas found while measuring

  • oldSeverity appears alongside severity in the catalog; KICS is migrating
    its scale. A converter must read severity and ignore oldSeverity, or
    findings silently downgrade.
  • Five native severities (CRITICAL/HIGH/MEDIUM/LOW/INFO) need five
    impact values. Mapping INFO to 0.0 would report Not Applicable and drop
    those findings from the compliance score.
  • The same query id appears across platforms with different platform and
    cloud_provider; resolution should not assume query_id alone is unique per
    scan context.

Fixtures

Reproducible from a small synthetic Terraform tree — no proprietary input
required. Happy to contribute the converter along with fixtures covering
findings across severities, a scan reporting parse failures, and the
zero-findings case.

Scope in this repo

src/commands/convert/kics2hdf.ts wrapping the mapper, guarded with
checkInput against INPUT_TYPES.KICS, a test under
test/commands/convert/, sample data under test/sample_data/kics/, and a
command section plus TOC entry in the README.

Sequencing: this depends on the mapper landing in hdf-converters and being
published, so it follows mitre/heimdall2#8572 rather than proceeding in
parallel.

Related: mitre/hdf-libs#238 tracks the same converter for the v3 line.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions