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.
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
sarif2hdfis a partial path. It is a lossy one, and thenative JSON carries materially more.
Measured fidelity gap
Scanned a real Terraform tree with
checkmarx/kics:latest, emitting JSON andSARIF 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[].targetagainst aCWEtoolComponent. Rule name, description,helpUriandriskScorealsosurvive.
What SARIF drops:
expected_valueactual_value, so you get what it is and never what it should beissue_typeMissingAttribute767 /IncorrectValue68 /RedundantAttribute14 — add-a-block versus fix-a-valuesimilarity_idresource_name,search_value,description_idCRITICALandHIGHboth collapse toerrorresource_typesurvives only as prose inside the message string, not as astructured 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.jsonfiles under/app/bin/assets/queries/, each withid,queryName,severity,category,descriptionText,descriptionUrl,platform,cloudProvider,cweandriskScore, with the rule'squery.regobeside it. Nothing has to be reverse-engineered or synthesized to produce
profile-grade output.
Every query carries a
cwe, sotags.nistresolves through the existing CWEmapping with no new mapping table.
Proposed mapping
query_id(stable UUID)query_namedescriptionseverity, five levels — see note belowtags.nist/tags.ccicwetagsplatform,cloud_provider,category,risk_score,issue_type,resource_typequery_urlcode_descfile_name,line,resource_type,search_keyresults[].messageexpected_valuevsactual_value— the remediation pairfiles_scanned,queries_total,kics_versionGranularity: 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
oldSeverityappears alongsideseverityin the catalog; KICS is migratingits scale. A converter must read
severityand ignoreoldSeverity, orfindings silently downgrade.
CRITICAL/HIGH/MEDIUM/LOW/INFO) need fiveimpact values. Mapping
INFOto0.0would report Not Applicable and dropthose findings from the compliance score.
platformandcloud_provider; resolution should not assumequery_idalone is unique perscan 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.tswrapping the mapper, guarded withcheckInputagainstINPUT_TYPES.KICS, a test undertest/commands/convert/, sample data undertest/sample_data/kics/, and acommand 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.