hdf CLI
Command-line tool for validating, inspecting, querying, and converting Heimdall Data Format (HDF) files. Part of the hdf-libs monorepo.
HDF (Heimdall Data Format) is a standardized JSON format for security assessment results. It normalizes outputs from vulnerability scanners, compliance checkers, configuration auditors, and cloud security tools into a unified schema that can be viewed in Heimdall.
The CLI is Go only, by design. Most packages in this monorepo ship a TypeScript implementation alongside the Go one, and there is deliberately no TypeScript CLI: shipping a single static binary means a user needs no Node runtime and inherits no npm dependency tree at execution time. The TypeScript libraries remain the path for programmatic and web use.
Table of Contents
- Installation
- Terminology
- Commands
- validate -- Validate an HDF file against the schema
- list -- Summarize a document, or list items with
--detail - query -- Search and filter requirements
- diff -- Compare two HDF documents
- events -- Derive, fold, and apply requirement-change events
- convert -- Convert between formats
- system -- View and manage HDF system documents
- plan -- View and manage HDF assessment plans
- amend -- Apply, list, and verify amendments (waivers/attestations)
- enrich -- Attach external context (STIX CTI) to results
- evidence -- Build and inspect evidence packages
- label -- Add, remove, or show labels on targets
- generate -- Generate InSpec profiles, thresholds, and baseline upgrades
- fetch -- Fetch from live APIs
- fetch aws-config -- AWS Config compliance data
- fetch aws-securityhub -- AWS Security Hub ASFF findings
- fetch defectdojo -- DefectDojo findings
- fetch gitlab -- GitLab CI/CD security artifacts
- fetch gitlab-vulnerabilities -- GitLab Vulnerability Report with triage state (Ultimate)
- fetch sonarqube -- SonarQube issues
- fetch splunk -- Splunk HDF events
- mcp -- Run the HDF MCP server (stdio transport)
- version -- Print version information
- Global Flags
- Supported Conversions
- Credential Handling
- Development
- License
Installation
Pre-built binaries (recommended)
Download the latest release for your platform from GitHub Releases. Binaries are available for:
- macOS (amd64, arm64)
- Linux (amd64, arm64)
- Windows (amd64)
Release assets are versioned, so set VERSION to the release you want (without the v prefix):
VERSION=3.7.2
# Example: download and install on macOS (Apple Silicon)
curl -sL https://github.com/mitre/hdf-libs/releases/download/v${VERSION}/hdf_${VERSION}_darwin_arm64.tar.gz | tar xz
sudo mv hdf /usr/local/bin/
# Linux (amd64)
curl -sL https://github.com/mitre/hdf-libs/releases/download/v${VERSION}/hdf_${VERSION}_linux_amd64.tar.gz | tar xz
sudo mv hdf /usr/local/bin/Archive naming: hdf_<version>_<os>_<arch>.tar.gz (e.g., hdf_3.7.2_darwin_arm64.tar.gz).
Build from source
Requirements: Go 1.26+, pnpm
# From the hdf-libs monorepo root
pnpm install
pnpm build # builds schema types first, then the hdf binary
# Or build only the CLI
cd hdf-cli
go build -o hdf ./cmd/hdfThe binary is written to hdf-cli/hdf. Add it to your PATH or invoke it directly.
go install …@latestis not supported: the CLI'sgo.moduses localreplacedirectives, so it's distributed as pre-built release binaries (goreleaser) or built from source as above.
Terminology
| Term | Definition |
|---|---|
| HDF | Heimdall Data Format -- a JSON schema for security assessment data |
| HDF Results | An assessed HDF file containing pass/fail results for each requirement |
| HDF Baseline | An unassessed HDF file defining security requirements without results |
| Requirement | A single security check or control (called "control" in InSpec terminology) |
| Baseline/Profile | A named collection of requirements (e.g., "RHEL 8 STIG") |
Commands
validate
Validate an HDF results or baseline file against the JSON schema. Returns exit code 0 on success, 1 on failure.
USAGE
hdf validate <file> [flags]
FLAGS
-t, --type string Schema type (auto-detected if omitted): results, baseline, comparison, system, plan, amendments, evidence-package, requirement-change-event
--schema-ver string HDF major schema version to validate against: 2 (legacy Heimdall/InSpec exec-json) or 3 (default, latest). Accepts 'hdf@2'/'hdf@3'; majors only.
-q, --quiet Suppress output on success (exit code only)
--source-name string Name to report for a document read from stdin; one line, no control characters (default "<stdin>")
Legacy HDF v2 documents (the InSpec exec-json profiles[]/platform shape SAF converters emit) can be validated directly with `--schema-ver 2`, rather than converting to v3 first.
EXAMPLES
hdf validate results.json
hdf validate baseline.json --type baseline
hdf validate --json results.json # machine-readable validation output
cat results.json | hdf validate - # read from stdin
curl -s https://example.com/scan.json | hdf validateExample output:
$ hdf validate results.json
✓ results.json is a valid HDF results file
Agent-attributed overrides: 0
$ echo '{"not":"hdf"}' | hdf validate -
✗ <stdin> — input not recognized as any HDF document type
Use --type to specify: results, baseline, comparison, system, plan, amendments, evidence-package, requirement-change-eventFor a results document the success line is followed by Agent-attributed overrides: N -- the number of status overrides whose appliedBy.type is agent, so an auditor can see at a glance how much AI-attributed judgment a document carries. --quiet suppresses it, and --json reports it as the agentOverrides field.
validate threshold
Validate HDF results against compliance thresholds — the CI/CD compliance-gate companion to hdf generate threshold. Exit code 0 if all thresholds pass, 1 on any violation.
USAGE
hdf validate threshold <results.json> [flags]
FLAGS
-T, --template stringArray Threshold YAML template file (repeatable; every spec must pass)
-I, --inline stringArray Inline threshold, repeatable (e.g. "{compliance.min: 80}, {failed.total.max: 0}")
--no-findings Suppress the list of requirements printed under each violation
--source-name string Name to report for a document read from stdin; one line, no control characters (default "<stdin>")
EXAMPLES
hdf validate threshold results.json -T threshold.yaml
hdf validate threshold results.json -I "{compliance.min: 80}, {failed.total.max: 0}"
cat results.json | hdf validate threshold - -T threshold.yaml --source-name grype.json
# Several specs are a conjunction: every one is evaluated, the run fails if any
# fails, and the violation names which. -T and -I may be combined, and one file
# may hold several YAML documents (reported as policy.yaml#1, policy.yaml#2).
hdf validate threshold results.json -T baseline.yaml -T repo-specific.yaml
# A rule is a filter predicate plus a bound, for policies the count bounds and
# controls lists cannot express — selecting by field rather than by id.
# -I accepts anything a file accepts, so this is the same language either way.
hdf validate threshold results.json \
-I "{rules: [{name: nothing fails without a plan, where: {status: [failed], poams: none-valid}, max: 0}]}"list
Summarize any HDF document, or expand a section to item-level detail with --detail. The default summary reports document counts and, for results, the status breakdown — this replaces the former info and stats commands.
USAGE
hdf list <file> [file...] [--detail <section>] [flags]
(alias: hdf ls)
DETAIL SECTIONS by document type
results: requirements, baselines, components
baseline: requirements, groups
system: components, dataFlows
plan: assessments
amendments: overrides
evidence-package: contents
Short aliases: r (requirements), b (baselines), t/c (components),
g (groups), a (assessments), o (overrides)
FLAGS
-s, --status string Filter requirements by status: passed, failed, notApplicable, notReviewed,
error (not_applicable and not_reviewed also accepted). A value outside the
vocabulary is rejected, not matched against nothing. The listed forms are
rendered from the engine's vocabulary, so help and refusal cannot disagree.
-a, --all Show all details (expand every section)
EXAMPLES
hdf list results.json # summary (counts + status breakdown)
hdf list results.json --detail requirements # list individual requirements
hdf list results.json --detail requirements -s failed
hdf list system.json --detail components # list system components
hdf list amendments.json --detail overrides # list waivers/attestations
hdf list results.json --jsonExample output:
$ hdf list results.json
Baselines: 5
Requirements: 1603
Components: 0
✓ passed 134
✗ failed 271
○ not_applicable 233
? not_reviewed 965
$ hdf list results.json --detail requirements -s failed
Requirements: 271
ID Status Title
--------- ------ ------------------------------------------------------------
V-242387 failed The Kubernetes Kubelet must have the read-only port flag ...
V-242391 failed The Kubernetes Kubelet must have anonymous authentication...
V-242392 failed The Kubernetes kubelet must enable explicit authorization.query
Search and filter controls by status, severity, framework mapping, tags, and free text. Multiple filters combine with AND logic.
USAGE
hdf query <file> [flags]
FLAGS
-s, --status stringArray Filter by status (repeatable, OR logic): passed, failed, notApplicable,
notReviewed, error (not_applicable and not_reviewed also accepted)
--severity stringArray Filter by severity (repeatable, OR logic): critical, high, medium, low, informational
--impact string Filter by EFFECTIVE impact — the score after any governing impact
override (e.g., ">0.5", ">=0.7", "0.5")
--raw-impact string Filter by the requirement's own impact, ignoring overrides. Same
comparison grammar; the pair expresses policies like "an override
may not move a critical below 0.7"
--cvss string Filter by CVSS score — computedScore where a consumer recomputed
one, else baseScore; a requirement with several CVSS entries
resolves to its highest (e.g., ">=7")
--epss string Filter by EPSS exploit probability — the score, NOT the
percentile rank (e.g., ">=0.5")
--kev string Filter by CISA Known Exploited Vulnerabilities membership:
true or false. false includes findings carrying no KEV data
--cwe stringArray Filter by CWE id (repeatable, OR logic). CWE-79, "CWE 79" and
cwe79 are one value. Reads the first-class cwe[] field only and
never tags.cwe, so a SARIF-derived document matches nothing
until the SARIF converter populates cwe[]
--cci stringArray Filter by CCI identifier (repeatable, OR logic; e.g., CCI-000366)
--nist stringArray Filter by NIST control (repeatable, OR logic; supports globs; e.g., AC-2, CM-6*)
--id string Filter by requirement ID, STIG ID, GID, or group title (exact; * or ? globs)
-t, --tag stringArray Filter by tag key:value (repeatable, OR logic; e.g., severity:high)
--status / --severity A value outside the vocabulary is rejected, not matched against nothing.
not_applicable and notApplicable are one value; the pre-3.7 severity
"none" still names informational.
--disposition stringArray Filter by what governs the requirement — the most recently applied
non-expired override or POA&M, where a governing plan reports "poam"
(repeatable, OR logic): waiver, attestation, poam, inherited,
falsePositive, riskAdjustment, operationalRequirement (false_positive
also accepted)
--poam-type stringArray Filter by the KIND of the governing POA&M (repeatable, OR logic):
remediation, mitigation, riskAcceptance, vendorDependency.
disposition reports every governing plan as "poam"; this names
which kind it is, and reads the GOVERNING plan only
--poams string Filter by remediation-plan validity: valid (a POA&M still in force) or
none-valid (none, an empty list, or only lapsed ones)
--search string Search in control title and description
-p, --baseline string Filter by profile name
--baseline-label stringArray Filter by the BASELINE's labels as key:value (repeatable, OR logic;
glob allowed on the value, e.g. environment:prod*). Labels say which
system, component or environment a baseline covers. A baseline carrying
no labels matches nothing — an absent label is not a wildcard.
-c, --count Show only the count of matching controls
-l, --limit int Limit number of results (0 = unlimited)
Repeatable filters (`--status`, `--severity`, `--cci`, `--nist`, `--tag`,
`--disposition`) OR their own values together; different filter types combine with AND.
`--status` reports EFFECTIVE status, so a requirement with a governing waiver is
already off `failed` before the filter sees it. `--disposition` names the type of
the most recent non-expired override of any kind — which is not always the one
that set the status, since an override carrying only an impact governs the
disposition without touching the status — and `--poams` reports whether a
remediation plan is still in force — `none-valid` deliberately covers "no POA&M", "an empty list" and "only
lapsed ones" as one condition, because a plan that has expired is not a plan.
EXAMPLES
hdf query results.json --status failed
hdf query results.json --status failed --severity high
hdf query results.json --nist "AC-2"
hdf query results.json --cci CCI-000366
hdf query results.json --id V-230221
hdf query results.json --id '*CVE-2022-27943' # a glob reaches a converter's prefixed id
hdf query results.json --tag "severity:high"
hdf query results.json --search "password policy"
hdf query results.json --disposition waiver --severity critical
hdf query results.json --status failed --poams none-valid
hdf query results.json --impact ">0.5" --status failed
hdf query results.json --status failed --count
hdf query results.json --limit 20 --status failedExample output:
$ hdf query results.json --status failed --limit 5
Found 5 matching requirement(s):
ID Status Severity Title
-------- ------ -------- -------------------------------------------------------
V-242387 failed HIGH The Kubernetes Kubelet must have the read-only port ...
V-242391 failed HIGH The Kubernetes Kubelet must have anonymous authentic...
V-242392 failed HIGH The Kubernetes kubelet must enable explicit authoriz...
V-242393 failed MED Kubernetes Worker Nodes must not have sshd service r...
V-242394 failed MED Kubernetes Worker Nodes must not have the sshd servi...
$ hdf query results.json --status failed --count
271diff
Compare two HDF documents and classify each requirement as fixed, regressed, unchanged, updated, new, or absent. Results documents are compared temporally; system documents by component drift. Document type is auto-detected.
USAGE
hdf diff <old-file> <new-file> [flags]
FLAGS
-f, --format string Output format: table, json, markdown (default "table")
-o, --output string Write output to file instead of stdout
--stat Summary counts only (like git diff --stat)
--all Include unchanged requirements/components in output
--name-only List only changed requirement IDs
--group-by string Group results by label key (e.g., baseline)
--regressed Show only regressions (also --fixed, --new, --absent)
-q, --quiet Suppress output, return exit code only (implies --exit-code)
--exit-code POSIX diff exit codes: 0=identical, 1=differences, 2=error
--detailed-exitcode Nuanced codes: 10=fixes, 11=regressions, 12=mixed, 13=baseline, 14=drift
--system string System document for component-aware comparison
--sbom Treat inputs as CycloneDX/SPDX SBOM documents
EXAMPLES
hdf diff old-scan.json new-scan.json
hdf diff old-scan.json new-scan.json -f markdown -o report.md
hdf diff old-scan.json new-scan.json --regressed
hdf diff old-scan.json new-scan.json --name-only
hdf diff old-scan.json new-scan.json --group-by baseline
hdf diff old-scan.json new-scan.json --detailed-exitcode # exit code encodes outcome
hdf diff --sbom old.cdx.json new.cdx.jsonExample output:
$ hdf diff old-scan.json new-scan.json
HDF Comparison: old-scan.json → new-scan.json
ID Title Old Status New Status State
------- ----------------------------- ---------- ---------- ---------
REQ-001 Test Requirement passed failed regressed
REQ-002 Audit logging must be enabled - passed new
Summary: 0 fixed, 1 regressed, 1 new, 0 absent, 0 unchanged, 0 updated (2 total)events
Batch operations over the HDF requirement-change-event stream (continuous monitoring): derive emits one NDJSON Requirement_Change_Event per requirement whose effective posture moved between two same-target results documents; fold materializes an event batch into a systemDrift hdf-comparison; apply reassembles the reconciled hdf-results (seed + events), stamped with a derivation block so it never masquerades as scanner output.
Every invocation is stateless and deterministic: event identity is a UUIDv5 over the entity key + sequence + the next document's timestamp — identical inputs produce byte-identical events. Sequencing across repeated derive runs is the caller's job (--start-sequence); fold and apply read events from any number of batch-file arguments or stdin, in any order — the fold contract ((source, eventId) dedup, per-key sequence as the only ordering authority) makes multi-batch delivery order-independent. Chain anomalies (gaps, duplicate keys, unknown tombstones) are warnings on stderr, never silent and never fatal.
USAGE
hdf events derive --prev <results.json> --next <results.json> [flags]
hdf events fold --seed <results.json> [events.ndjson ...] [flags]
hdf events apply --seed <results.json> [events.ndjson ...] [flags]
DERIVE FLAGS
--system-ref string System document reference for the entity key (required)
--component-id string Component UUID (default: the next document's sole component)
--source string Producer URI recorded in the envelope
--start-sequence int Sequence assigned to the first emitted event (default 1)
--schema-ref string Optional schemaRef URI stamped on every event
-o, --output string Output file (default: stdout)
FOLD / APPLY FLAGS
-o, --output string Output file (default: stdout)
--seed-uri string (apply) Seed URI for the derivation block (default: the --seed path)
--source string (apply) Stream source for the derivation block (default: first event's source)
EXAMPLES
hdf events derive --prev monday.hdf.json --next tuesday.hdf.json \
--system-ref prod.hdf-system.json --component-id 6e0f2a3b-9c01-4d5e-8f7a-1b2c3d4e5f60 \
-o events.ndjson
hdf events fold --seed monday.hdf.json events.ndjson -o drift.comparison.json
hdf events apply --seed monday.hdf.json batch-1.ndjson batch-2.ndjson -o reconciled.hdf.json
cat events.ndjson | hdf events apply --seed monday.hdf.json -o reconciled.hdf.jsonA complete runnable example — a live container scanned with a MITRE SAF STIG baseline, driven through seed → drift → derive → apply → amendment → chaos → re-center — lives at mitre/hdf-conmon-demo.
Example loop (real output):
$ hdf events derive --prev scan-before.json --next scan-after.json \
--system-ref prod.hdf-system.json --component-id 6e0f2a3b-... -o events.ndjson
$ cut -c1-80 events.ndjson | head -2
{"after":{"descriptions":[{"data":"The system must disable root SSH login","labe
{"after":{"descriptions":[{"data":"The audit subsystem must be active","label":"
$ hdf events apply --seed scan-before.json events.ndjson -o reconciled.hdf.json
$ hdf validate reconciled.hdf.json
✓ reconciled.hdf.json is a valid HDF results fileBecause reconciled.hdf.json is a results document, hdf validate also prints the Agent-attributed overrides: N readout described under validate; the count depends on the overrides carried by the applied events.
convert
Convert security assessment data between HDF and other formats. Supports auto-detection, explicit --from/--to flags, stdin, and stdout.
USAGE
hdf convert <file> -o <output> # Auto-detect format
hdf convert --from <source> <file> -o <output> # Explicit source format
hdf convert --from <source> --to <dest> <file> -o <output> # Explicit both
hdf convert <file> # Auto-detect, stdout
hdf convert <file> [file...] -o <output-dir>/ # Bulk convert to a directory
hdf convert <file|dir> [...] --to html -o <file> # Several HDF results in one combined HTML report
hdf convert --from <source>@<version> <file> # Select a schema version
cat scan.json | hdf convert - # stdin
INPUT/OUTPUT
<file> File path or "-" for stdin
<dir> With --to html: every HDF results document under the directory, searched
recursively; other files there are passed over and counted on stderr
-o <output> Output file path; defaults to stdout if omitted
-o <dir>/ One output per input, named after the input file; inputs that share a file
name are each numbered in argument order (results.1, results.2)
FLAGS
--from string Source format (auto-detected if omitted)
--to string Destination format (default: hdf)
--catalog string OSCAL catalog JSON path (required for oscal-profile → HDF Baseline)
--component-id string Set componentId (a UUID) on all components in the output (--to hdf only;
warns and still writes when the converter emits no components)
--labels strings Labels applied to all targets, --to hdf only (key=value, e.g. --labels system=Portal,env=prod)
--nist-rev int NIST 800-53 revision for emitted control tags (4 or 5; default 5)
--report-type string Detail level for --to html: executive, manager or administrator (default administrator)
--nist-strict Fail if input references rules mapped only at a different NIST revision
--no-validate Skip schema validation of converter output before writing
-f, --force Allow overwriting the input file with output
EXAMPLES
hdf convert scan.nessus -o results.json
hdf convert --from oscal-profile profile.json --catalog catalog.json -o baseline.json
hdf convert --from nessus scan.nessus -o results.json
hdf convert --from sarif findings.sarif -o results.json
hdf convert --from gosec gosec-output.json -o results.json
hdf convert --from grype grype-output.json -o results.json
hdf convert --from snyk snyk-output.json -o results.json
hdf convert --from trufflehog secrets.json -o results.json
hdf convert --from xccdf xccdf-results.xml -o results.json
hdf convert --from gitlab gl-sast-report.json -o results.json
hdf convert --from junit test-results.xml -o results.json
hdf convert --from zap zap-report.json -o results.json
hdf convert --from legacyhdf old-scan.json -o new-scan.json
hdf convert --from hdf --to csv results.json -o controls.csv
hdf convert --from hdf --to xml results.json -o controls.xml
hdf convert results.json --to html -o report.html
hdf convert results.json --to html --report-type manager -o report.html
hdf convert scan1.json scan2.json --to html -o report.html # one combined report
hdf convert scans/ --to html -o report.html # every results document under scans/
cat scan.json | hdf convert --from sarif - -o output.jsonExample output:
$ hdf convert compliance.nessus -o results.json
Detected: Nessus 2 (confidence: 100%)
compliance.nessus: 5 requirements, matching the input's Nessus report items
$ hdf convert --from nessus compliance.nessus -o results.json
compliance.nessus: 5 requirements, matching the input's Nessus report items
$ hdf validate results.json
✓ results.json is a valid HDF results file
Agent-attributed overrides: 0On auto-detection the source format and a confidence score are reported on the Detected: line; an explicit --from skips only that line. Both forms write to -o (or stdout) and print the per-file <file>: N requirements, ... summary on stderr whenever the converter declares how many requirements its input must yield; if the produced count differs, the conversion is refused and no output is written.
See Supported Conversions for the full list.
system
View and manage HDF system documents — a system's authorization boundary, components, baselines, and data flows.
USAGE
hdf system <subcommand> <file> [flags]
SUBCOMMANDS
create Bootstrap a system document from a results file or SBOM (positional input; --from only verifies a detected BOM format)
info Summarize a system document
add-component Add a component from an SBOM
update-component Update a component's SBOM reference
set Set/unset top-level fields
EXAMPLES
hdf system create results.json --name "Portal Prod" -o portal.hdf-system.json
hdf system info portal.hdf-system.json
hdf system info portal.hdf-system.json --jsonhdf system create takes its input as a positional file path or URL and auto-detects the format. Its --from flag (cyclonedx | spdx | cyclonedx-mlbom | spdx-ai) does not select a parser the way hdf convert --from does: it only asserts that the detected BOM format matches, and the command fails if it does not.
hdf system update-component --component-name <name> selects the component to refresh, and the name must match exactly one: a component name is a label, not identity (componentId is), so a document may legitimately carry two components with the same name, and an ambiguous name is refused before anything is written rather than refreshing whichever came first. Omit --component-name to reconcile every subject by its stable boms[].uniqueId. hdf label set/remove --component-name applies the same rule through the same selector, with the same message.
Example output:
$ hdf system info portal-prod.hdf-system.json
System: Portal Prod
System ID: aaaaaaaa-1111-2222-3333-444444444444
Components (2):
WebTier (application)
Baselines: RHEL9-STIG
DatabaseTier (application)
Baselines: PostgreSQL-STIGplan
View and manage HDF assessment plan documents — which baselines run against which targets, with resolved inputs and scheduling.
USAGE
hdf plan <subcommand> <file> [flags]
SUBCOMMANDS
create Create an assessment plan
info Summarize a plan document
set Set/unset top-level fields
EXAMPLES
hdf plan info quarterly-plan.hdf-plan.json
hdf plan info quarterly-plan.hdf-plan.json --jsonExample output:
$ hdf plan info quarterly-plan.hdf-plan.json
Plan: portal-prod-assessment-plan
ID: 4737569f-8bb5-49b1-8e3a-3586a88d092e
Type: automated
System: system.json
Assessments (2):
1. Baseline: RHEL9-STIG
2. Baseline: PostgreSQL-STIGamend
Apply, list, and verify HDF amendments — standalone waiver / attestation / POA&M documents that modify requirement compliance status in results.
USAGE
hdf amend <subcommand> [flags]
SUBCOMMANDS
apply Merge amendments into a results file (sets effectiveStatus); refuses
a document that does not verify
create Create waivers, attestations, and other amendments
draft Scaffold an incomplete amendments draft from a results file.
--status accepts the same vocabulary as `hdf list`/`hdf query`
(passed, failed, notApplicable, notReviewed, error; not_applicable
and not_reviewed also accepted) and rejects anything outside it
before reading the input, rather than writing a draft with no stubs.
list List amendments in an amendments file
verify Verify amendment structure, expiration, and chain integrity
set Set/unset top-level fields
EXAMPLES
hdf amend apply --results results.json --amendments waivers.json -o merged.json
hdf amend list waivers.json
hdf amend verify waivers.json # structure, expiry, chain
hdf amend verify waivers.json results.json # also check against resultsExample output:
$ hdf amend list waivers.json
Amendments: Q1 Waivers
System: portal-prod.hdf-system.json
Amendments (1):
Requirement Type Status Impact Expires Reason
----------- ------ ------ ------ ---------- ---------------------
AC-1 waiver passed 2099-12-31 Risk accepted per ATO
$ hdf amend verify waivers.json
Total amendments: 1
Valid: 1
Expired: 0
Invalid: 0
Chain: not established
All amendments are valid.verify exits non-zero when any amendment is expired, structurally invalid, or when the previousChecksum chain is broken. An expired amendment is a failure, not a warning, and no flag makes one pass — so the command is safe to wire directly into CI as a gate. apply refuses the same documents rather than merging them, as does the hdf_apply_amendment MCP tool.
enrich
Overlay an enrichment source onto an HDF results document, attaching inert externalReferences[] to findings (matched by CVE) or to the document root. Enrichment is informational — it adds context and never changes a finding's status or impact. Positional parity with convert: <results> <source>, with --from as the optional format assertion.
USAGE
hdf enrich <results> <source> [flags]
FLAGS
--from string Enrichment source format (auto-detected if omitted; e.g. stix)
--recompute-cvss Also author an E:H CVSS riskAdjustment on exploited, 3.1-base-vector findings
-o, --output string Output file (default: stdout)
EXAMPLES
hdf enrich results.json log4shell-bundle.json -o enriched.json # auto-detect STIX
hdf enrich results.json feed.json --from stix -o enriched.json # assert the format
hdf enrich results.json bundle.json --recompute-cvss -o enriched.json # + CVSS E:H recompute
hdf enrich results.json bundle.json # write to stdoutSupported sources: stix (a STIX 2.1 bundle, {type:"bundle", objects:[…]}). A CVE-bearing STIX object attaches to the finding whose requirement ID is that CVE; everything else (non-CVE objects, and CVEs with no matching finding) attaches to the document root. Each reference carries the raw STIX object losslessly in document.
With --recompute-cvss, when a matched STIX object shows active exploitation (a sighting, a targets/exploits relationship, or an indicator/report reference) and the finding carries a CVSS 3.1 base vector, an inline riskAdjustment is authored: Exploit Maturity E:H is applied and the Threat score recomputed via the CVSS engine, with impact.value = computedScore/10 and an externalReferences[] back to the STIX source. Findings with no base vector, or a CVSS 4.0 base vector, are left unchanged (no fabrication). Enrichment without --recompute-cvss never changes status or impact.
evidence
Build and inspect HDF evidence packages — bundles of references to all HDF documents for audit, authorization, and compliance review.
USAGE
hdf evidence <subcommand> <file> [flags]
SUBCOMMANDS
build Bundle HDF documents into an evidence package
info Summarize an evidence package (with per-document checksum status)
verify Verify an evidence package against its assessment plan
export Export package documents to another format
set Set/unset top-level fields
add-evidence Reference external native-format evidence (logs/telemetry) by uri + hash + format
EXAMPLES
hdf evidence build --system system.json --results r1.json --results r2.json -o q1.hdf-evidence-package.json
hdf evidence info q1.hdf-evidence-package.json
hdf evidence verify q1.hdf-evidence-package.json
hdf evidence add-evidence q1.hdf-evidence-package.json --uri logs/q1.ndjson --format ecs --collector elastic-agentExample output:
$ hdf evidence info q1-2026.hdf-evidence-package.json
Evidence Package: Portal Prod Q1 Evidence
System: system.json
Contents (4):
hdf-system system.json ✓ checksum
hdf-plan plan.json ✓ checksum
hdf-results rhel9-results.json ✓ checksum
hdf-results postgres-results.json ✓ checksumlabel
Add, remove, or show key=value labels and external IDs on the targets of an HDF document.
USAGE
hdf label <subcommand> <file> [flags]
SUBCOMMANDS
show Display labels and external IDs on all targets
set Set labels and external IDs on all targets
remove Remove labels and external IDs from all targets
FLAGS (set)
--component-id string Set componentId (a UUID) on all components
--generate-component-id Generate a unique componentId for each component
--external-id stringArray Set an external ID as scheme=value (repeatable)
--component-name string Apply --external-id only to the component with this name
-o, --output string Write to a different file instead of modifying in-place
FLAGS (remove)
--external-id stringArray Remove an external ID scheme (repeatable)
--component-name string Remove --external-id only from the component with this name
-o, --output string Write to a different file instead of modifying in-place
EXAMPLES
hdf label show results.json
hdf label set results.json system=Portal environment=production -o labeled.json
hdf label remove results.json system environment -o cleaned.json
hdf label set results.json --external-id cmdb=CI0012345 --external-id emass=1234
hdf label remove results.json --external-id cmdbLabels group and select components; an external ID is a foreign key into another system (CMDB asset ID, eMASS system ID, cloud resource ID) and is written to components[].externalIds, never to labels. --external-id merges: a scheme named on the command line is overwritten and the others are left alone. The value is carried verbatim and may be any non-empty string. set exits non-zero and writes nothing when the pair is malformed, a scheme is given twice, the document has no components, or --component-name matches none or more than one. --component-id and --generate-component-id are refused on a document with no components for the same reason — there is nothing to stamp, and rewriting the file while reporting success would claim an id was attached when it was not.
Example output:
$ hdf label set results.json system=Portal environment=production -o labeled.json
Labels written to labeled.json
$ hdf label show labeled.json
Component: web01.example.com [host]
environment = production
system = Portal
$ hdf label set labeled.json --external-id cmdb=CI0012345
Labels updated in labeled.json
$ hdf label show labeled.json
Component: web01.example.com [host]
environment = production
system = Portal
External IDs:
cmdb = CI0012345generate
Generate security templates and skeletons from HDF baselines, results, or XCCDF benchmarks.
USAGE
hdf generate <subcommand> <file> [flags]
SUBCOMMANDS
inspec-profile Generate an InSpec profile from an HDF Baseline or XCCDF Benchmark
threshold Generate a compliance threshold template from HDF results
upgrade Upgrade a baseline with new upstream metadata, preserving customizations (alias: delta)
EXAMPLES
hdf generate inspec-profile baseline.json my-profile/ # <input> <output-dir>
hdf generate inspec-profile U_RHEL_9_STIG_xccdf.xml rhel9-stig/ # XCCDF auto-detected
hdf generate threshold results.json -o threshold.yml
hdf generate upgrade profile/ new-stig-xccdf.xml # <current> <upstream>Example output:
$ hdf generate threshold results.json
compliance:
min: 100
passed:
high:
min: 1
total:
min: 1fetch
Fetch security data from a live API and convert to HDF in a single step. No intermediate files needed.
Every fetch subcommand except splunk supports --format raw to skip HDF conversion and return the tool's native output. All of them, splunk included, support --output / -o to write to a file instead of stdout.
For endpoints behind a custom TLS chain, every fetch subcommand accepts --ca-cert <pem> (a PEM CA bundle for corporate/custom CAs) and --insecure (skip TLS verification — prints a warning; use only against trusted hosts).
Credentials are resolved from environment variables or tool-specific config files. See Credential Handling.
fetch aws-config
Fetch AWS Config compliance evaluation results and convert to HDF.
Credentials are resolved via the standard AWS credential chain: environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), shared credentials file (~/.aws/credentials), or IAM instance role.
Service-linked rules are excluded. Config rules owned by an AWS service (CreatedBy set — Security Hub, conformance packs, Organizations) can't be read via the Config API by a customer principal, so they're skipped (a WARNING: skipped N service-linked rule(s) is printed to stderr). Fetch their findings through the owning service instead — e.g. hdf fetch aws-securityhub for Security Hub controls.
Remediation surfaces as a fix description. A customer-managed rule with an attached remediation configuration (SSM Automation document) gains a fix description in its HDF requirement describing the remediation.
USAGE
hdf fetch aws-config [output] [flags]
FLAGS
-r, --region string (required) AWS region (e.g., us-east-1)
-p, --profile string AWS CLI named profile
--format string Output format: hdf or raw (default "hdf")
--no-validate Skip schema validation of converter output before writing
-o, --output string Output file path (default: stdout)
EXAMPLES
hdf fetch aws-config --region us-east-1 output.json
hdf fetch aws-config --region us-east-1 --profile my-audit-account output.json
hdf fetch aws-config --region us-east-1 --format raw | jq '.ConfigRules | length'
hdf fetch aws-config --region us-east-1 | jq '.baselines[0].requirements | length'fetch aws-securityhub
Fetch ASFF findings from AWS Security Hub and convert to HDF via the asff-to-hdf converter. Use --check to verify credentials without downloading findings.
Credentials are resolved via the same AWS chain as fetch aws-config (env vars, ~/.aws/credentials / ~/.aws/config, IAM instance role, AssumeRole).
USAGE
hdf fetch aws-securityhub [output] [flags]
FLAGS
-r, --region string (required) AWS region (e.g., us-east-1)
-p, --profile string AWS CLI named profile
--format string Output format: hdf or raw (default "hdf")
--filter-json string Path to a JSON file with an ASFF AwsSecurityFindingFilters object
--no-validate Skip schema validation of converter output before writing
-o, --output string Output file path (default: stdout)
--check Verify credentials only; skip findings download
EXAMPLES
# Fetch all findings in a region
hdf fetch aws-securityhub --region us-east-1 output.json
# Use a named AWS CLI profile
hdf fetch aws-securityhub --region us-east-1 --profile my-audit-account output.json
# Save raw ASFF JSON instead of HDF
hdf fetch aws-securityhub --region us-east-1 --format raw asff.json
# Narrow the pull with a Security Hub filter (see "Filtering findings" below)
hdf fetch aws-securityhub --region us-east-1 --filter-json failed-only.json output.json
# Verify credentials only -- exits 0 on success, non-zero on auth failure
hdf fetch aws-securityhub --region us-east-1 --checkFiltering findings
By default the fetch pulls every active finding, which on a busy account is a lot. --filter-json narrows it: point it at a file containing a Security Hub AwsSecurityFindingFilters object, which is passed straight to the GetFindings API. Each field is an array of matchers; multiple values on one field OR together, and different fields AND together. String matchers take a Comparison (EQUALS, NOT_EQUALS, PREFIX, PREFIX_NOT_EQUALS, CONTAINS, NOT_CONTAINS) and values are case-sensitive.
Only failed compliance findings (the common "what needs remediation" pull):
{ "ComplianceStatus": [{ "Value": "FAILED", "Comparison": "EQUALS" }] }Only critical and high severity (OR within the field):
{ "SeverityLabel": [
{ "Value": "CRITICAL", "Comparison": "EQUALS" },
{ "Value": "HIGH", "Comparison": "EQUALS" }
] }Active findings that are not resolved (AND across fields):
{ "RecordState": [{ "Value": "ACTIVE", "Comparison": "EQUALS" }],
"WorkflowStatus": [{ "Value": "RESOLVED", "Comparison": "NOT_EQUALS" }] }Findings updated in the last 7 days — the continuous-monitoring incremental pull (date fields take a DateRange in DAYS instead of a Comparison):
{ "UpdatedAt": [{ "DateRange": { "Unit": "DAYS", "Value": 7 } }] }Combined — failed criticals from the last 30 days:
{ "ComplianceStatus": [{ "Value": "FAILED", "Comparison": "EQUALS" }],
"SeverityLabel": [{ "Value": "CRITICAL", "Comparison": "EQUALS" }],
"UpdatedAt": [{ "DateRange": { "Unit": "DAYS", "Value": 30 } }] }The AwsSecurityFindingFilters reference lists every filterable field (product, account, standard, resource type, and more) — --filter-json accepts any of them.
fetch defectdojo
Fetch findings from a DefectDojo instance and convert to HDF.
Token must be set via the DEFECTDOJO_API_TOKEN environment variable.
Findings are grouped into HDF baselines by their underlying scanner (test_type), and risk-accepted findings carry a full HDF status override (who accepted the risk, when, why, and when it expires) reconstructed from the finding's inline risk-acceptance provenance.
USAGE
hdf fetch defectdojo [output] [flags]
FLAGS
-u, --url string (required) DefectDojo instance URL
--product-name string Filter findings to a product by name
--engagement string Filter findings to an engagement by id
--test string Filter findings to a single test by id
--format string Output format: hdf or raw (default "hdf")
--check Verify credentials only; skip findings download
--no-validate Skip schema validation of converter output before writing
-o, --output string Output file path (default: stdout)
EXAMPLES
export DEFECTDOJO_API_TOKEN=<your-token>
hdf fetch defectdojo --url https://defectdojo.example.com -o output.json
hdf fetch defectdojo --url https://defectdojo.example.com --product-name "My App" -o output.json
hdf fetch defectdojo --url https://defectdojo.example.com --checkfetch gitlab
Fetch a GitLab CI/CD security scan artifact (SAST, DAST, secret detection, etc.) and convert to HDF.
Token is resolved from: GITLAB_TOKEN env var, GLAB_TOKEN env var, or glab CLI config (glab auth login).
The --scan-type flag selects the default artifact filename:
| Scan Type | Default Artifact |
|---|---|
sast (default) | gl-sast-report.json |
dast | gl-dast-report.json |
secret-detection | gl-secret-detection-report.json |
dependency-scanning | gl-dependency-scanning-report.json |
container-scanning | gl-container-scanning-report.json |
api-fuzzing | gl-api-fuzzing-report.json |
USAGE
hdf fetch gitlab [output] [flags]
FLAGS
-u, --url string GitLab instance URL (default "https://gitlab.com")
--project string (required) Project ID or namespace/project path
--ref string Branch or tag name (default "main")
--scan-type string Scan type (default "sast")
--artifact-path string Override default artifact filename
--job string (required) CI job name that produced the artifact
--format string Output format: hdf or raw (default "hdf")
--max-response-size int Max response size in bytes (default 10MB, -1 for no limit)
-o, --output string Output file path (default: stdout)
EXAMPLES
hdf fetch gitlab --project my-org/my-project --job semgrep-sast -o output.json
hdf fetch gitlab --url http://gitlab.local:9090 --project 42 \
--scan-type dast --ref develop --job dast -o output.json
hdf fetch gitlab --project my-org/my-project --job secret_detection \
--scan-type secret-detection --ref master -o secrets.json
hdf fetch gitlab --project 42 --job semgrep-sast --format raw | jq '.vulnerabilities | length'fetch gitlab-vulnerabilities
Fetch a project's GitLab Vulnerability Report over GraphQL and convert to HDF. Unlike fetch gitlab, which downloads the raw report one CI job wrote, this reads the deduplicated, persisted, triaged view GitLab Ultimate maintains: each finding's state, dismissal reason and statement, who decided and when, and the full state history. Dismissals become attributed, expiring HDF overrides; the scanner's raw result is never rewritten. The mapping and the empty-report semantics are documented in the GitLab Vulnerability Report guide.
Token is resolved from: GITLAB_TOKEN env var, GLAB_TOKEN env var, or glab CLI config (glab auth login). It needs the read_api scope and Developer access to the projects. The Vulnerability Report requires GitLab Ultimate; on Free or Premium the API answers with an empty list, so the command refuses to write a document for a report that was never populated and names the reason instead.
With --group, every non-archived project in the group (subgroups included by default) is fetched and one file per project is written to --out-dir, named after the project path with / replaced by __. A project that cannot be fetched is reported on stderr and the command exits non-zero after the others are written.
--check runs the probe only and downloads no findings. With --project it prints that project's diagnosis. With --group it probes every project in the group and prints one line each, under a count of how many have a populated report, how many never did, and how many could not be probed; it needs no --out-dir.
USAGE
hdf fetch gitlab-vulnerabilities [output] [flags]
FLAGS
-u, --url string GitLab instance URL (default "https://gitlab.com")
--project string Project full path (namespace/project)
--group string Group full path; fetches every non-archived project in it
--include-subgroups With --group, include projects of subgroups (default true)
--state string Comma-separated vulnerability states to fetch: DETECTED, CONFIRMED, DISMISSED, RESOLVED (default: all)
--report-type string Comma-separated report types to fetch: SAST, DAST, DEPENDENCY_SCANNING, ... (default: all)
--format string Output format: hdf (convert to HDF) or raw (fetched envelope) (default "hdf")
-o, --output string Output file path with --project (default: stdout)
--out-dir string Output directory with --group; one file per project
--page-size int Findings requested per GraphQL page (default: 25, sized to GitLab's query complexity cap)
--max-pages int Maximum pages per project, group listing or finding history (default: 500)
--max-response-size int Maximum response size in bytes per request (default: 25MB, -1 for no limit)
--no-validate Skip schema validation of converter output before writing
--check Run the probe only and print the tier and ingestion diagnosis (every project with --group)
EXAMPLES
hdf fetch gitlab-vulnerabilities --project my-org/my-project -o output.json
hdf fetch gitlab-vulnerabilities --url https://gitlab.example.com --group my-org --out-dir ./hdf/
hdf fetch gitlab-vulnerabilities --project my-org/my-project --state DETECTED,CONFIRMED -o open.json
hdf fetch gitlab-vulnerabilities --project my-org/my-project --state DISMISSED -o dismissed.json
hdf fetch gitlab-vulnerabilities --project my-org/my-project --check
hdf fetch gitlab-vulnerabilities --url https://gitlab.example.com --group my-org --check
hdf fetch gitlab-vulnerabilities --project my-org/my-project --format raw | jq '.vulnerabilities | length'fetch sonarqube
Fetch SonarQube project issues and convert to HDF.
Token must be set via the SONARQUBE_TOKEN environment variable.
USAGE
hdf fetch sonarqube [output] [flags]
FLAGS
-u, --url string (required) SonarQube server URL
--project-key string (required) SonarQube project key
--branch string Branch name
--pull-request string Pull request ID
--organization string SonarCloud organization key
--sonarqube-version string SonarQube server version (auto-detected if omitted; affects auth method)
--format string Output format: hdf or raw (default "hdf")
--no-validate Skip schema validation of converter output before writing
-o, --output string Output file path (default: stdout)
NOTE
--branch and --pull-request are mutually exclusive.
EXAMPLES
export SONARQUBE_TOKEN=squ_abc123
hdf fetch sonarqube --url https://sonarqube.example.com --project-key my-project -o output.json
hdf fetch sonarqube --url https://sonarqube.example.com --project-key my-project \
--branch develop -o output.json
hdf fetch sonarqube --url https://sonarqube.example.com --project-key my-project \
--pull-request 42 -o output.jsonfetch splunk
Fetch HDF evaluation events from a Splunk index and reassemble into an HDF results file.
Token must be set via the SPLUNK_TOKEN environment variable.
USAGE
hdf fetch splunk [output] [flags]
FLAGS
-u, --url string (required) Splunk server URL
-i, --index string (required) Splunk index name
-g, --guid string (required) Evaluation GUID to fetch
--no-validate Skip schema validation of converter output before writing
-o, --output string Output file path (default: stdout)
EXAMPLES
export SPLUNK_TOKEN=your-splunk-token
hdf fetch splunk --url https://splunk.example.com --index hdf --guid abc123 -o output.json
hdf fetch splunk --url https://splunk.example.com --index hdf --guid abc123 | jq .mcp
Run the HDF Model Context Protocol (MCP) server over stdio, so an MCP client (an AI agent or any MCP-aware host) can read, analyze, and author HDF documents through a small typed tool surface instead of shelling out to the CLI. The client launches hdf mcp as a subprocess; stdout carries only JSON-RPC frames and must not be shared with any other output, and logs go to stderr.
USAGE
hdf mcp [flags]
FLAGS
--tools string tools to advertise: comma-separated names (hdf_open,hdf_query) or a profile (read|all); default all
EXAMPLES
hdf mcp # advertise every tool
hdf mcp --tools read # read/analysis tools only
hdf mcp --tools hdf_open,hdf_query # an explicit tool list
HDF_MCP_ROOT=/data/hdf hdf mcp # confine file access to one directory--tools accepts a comma-separated mix of exact tool names and profile words. The read profile is hdf_open, hdf_inspect, hdf_query, hdf_compliance, hdf_aggregate, hdf_diff, and hdf_validate; all (the default) adds the write tools hdf_convert, hdf_author, and hdf_apply_amendment. Advertising fewer tools shrinks the schema an agent re-sends every turn. An unknown name is a startup error that lists the valid tools and profiles.
Environment variables:
| Variable | Description | Default |
|---|---|---|
HDF_MCP_ROOT | Path-confinement root; every tool path and write output is resolved under it and anything outside is refused | process working directory |
HDF_MCP_ENABLE_WRITES | Write gate; 1, true, yes, or on permits writes to disk, anything else leaves the write tools in preview mode | disabled |
HDF_MCP_MAX_SIZE | Per-document input ceiling in bytes, applied before a file is read | 50 MB |
HDF_MCP_CACHE_BYTES | Budget for the parsed-document cache | 256 MB |
HDF_MCP_LOG_LEVEL | Stderr log level: error, warn, info, or debug | info |
HDF_MCP_TOOLS | Same syntax as --tools; the flag takes precedence when both are set | all tools |
The tool contracts, the source and handle model, response budgets, and a worked example are documented in the HDF MCP Server guide.
version
Print version, commit hash, build date, and Go version.
USAGE
hdf version [flags]
EXAMPLES
hdf version
hdf version --jsonGlobal Flags
These flags apply to all commands.
| Flag | Short | Default | Description |
|---|---|---|---|
--json | false | Output in JSON format | |
--debug | -d | false | Enable debug output |
--fail-fast | -F | false | Abort on first file that fails instead of continuing |
--max-size | 256 | Maximum input file size in MB | |
--no-follow-symlinks | false | Refuse to read symlinked files | |
--no-headers | false | Suppress column headers in table output | |
--schema-dir | Load schemas from a directory instead of the embedded copies |
Supported Conversions
To HDF
| Source Format | Aliases | Description |
|---|---|---|
asff | AWS Security Finding Format — Security Hub / AWS-integrated tool findings (JSON) | |
aws-config | AWS Config compliance evaluation results (JSON) | |
burpsuite | PortSwigger BurpSuite web scanner (XML) | |
checkov | Checkov IaC static analysis (JSON) | |
ckl | DISA STIG Viewer checklist (.ckl XML) | |
cklb | DISA STIG Viewer 3.x checklist (.cklb JSON) | |
conveyor | Conveyor container security (JSON) | |
csaf-vex | CSAF VEX advisory (csaf_vex profile) → HDF Amendments (JSON) | |
cyclonedx | CycloneDX SBOM (JSON) — VEX-bearing BOMs auto-route to cyclonedx-vex | |
cyclonedx-vex | CycloneDX BOM with VEX analysis statements → HDF Amendments (JSON) | |
dbprotect | DbProtect database scanner (XML) | |
defectdojo | DefectDojo findings export via API (JSON) | |
deptrack | dependency-track | Dependency-Track vulnerability audit (JSON) |
fortify | Micro Focus Fortify SAST (FVDL XML) | |
gitlab | gitlab-sast, gitlab-dast | GitLab CI/CD security scan reports (JSON) |
gitlab-vulnerabilities | — | GitLab Vulnerability Report envelope from hdf fetch gitlab-vulnerabilities (JSON; triage state preserved) |
gosec | gosec Go security checker (JSON or SARIF) | |
grype | Anchore Grype vulnerability scan (JSON) | |
hadolint | hadolint Dockerfile linter (JSON or SARIF) | |
hipcheck | MITRE Hipcheck supply-chain risk report (hc check --format json) | |
ionchannel | Ion Channel supply chain analysis (JSON) | |
jfrog-xray | xray | JFrog Xray SCA scan (JSON) |
junit | JUnit XML test results | |
kics | KICS IaC misconfiguration scan (JSON) | |
legacyhdf | inspec | Legacy HDF (InSpec exec-json format) to current HDF |
msft-defender-cloud | defender-cloud | Microsoft Defender for Cloud (JSON) |
msft-defender-devops | msdo | Microsoft Defender for DevOps (SARIF) |
msft-defender-endpoint | defender-endpoint | Microsoft Defender for Endpoint (JSON) |
msft-secure-score | Microsoft Secure Score (JSON) | |
nessus | Tenable Nessus scan results (.nessus XML) | |
netsparker | invicti | Netsparker/Invicti web scanner (XML) |
neuvector | NeuVector container security (JSON) | |
nikto | Nikto web server scanner (JSON) | |
openvex | OpenVEX statements → HDF Amendments (JSON) | |
oscal | OSCAL document (auto-detect type) | |
oscal-sar | oscal-assessment-results | OSCAL Assessment Results → HDF Results |
oscal-assessment-plan | oscal-sap | OSCAL Assessment Plan → HDF Plan |
oscal-catalog | OSCAL Catalog → HDF Baseline | |
oscal-component-definition | oscal-component | OSCAL Component Definition → HDF Baseline |
oscal-profile | OSCAL Profile → HDF Baseline (requires --catalog) | |
oscal-ssp | OSCAL System Security Plan → HDF System | |
oscal-poam | OSCAL Plan of Action and Milestones → HDF Amendments | |
prisma | Prisma Cloud/Twistlock container scan (JSON) | |
sarif | SARIF 2.1.0 (Static Analysis Results Interchange Format) | |
scoutsuite | NCC Group ScoutSuite cloud audit (JSON) | |
semgrep | Semgrep static analysis scan (JSON or SARIF) | |
snyk | Snyk vulnerability scan (JSON) | |
sonarqube | SonarQube issues export (JSON) | |
spdx-vex | SPDX 3.0 security-profile VEX (JSON-LD) → HDF Amendments | |
splunk | Splunk HDF events (JSON) | |
trivy | Trivy scanner — native JSON (vuln/misconfig/secret/license); SARIF, CycloneDX, ASFF, and GitLab output are auto-routed to their converters | |
trufflehog | TruffleHog secret scanner (JSON, NDJSON, or single object) | |
twistlock | Palo Alto Twistlock container scan (JSON) | |
veracode | Veracode SAST/DAST results (XML) | |
xccdf | arf, xccdf-benchmark, xccdf-results | XCCDF/ARF benchmark or results (XML) |
zap | OWASP ZAP web scanner (JSON) |
Auto-detection: hdf convert <file> identifies the input format automatically. Use --from <format> only when auto-detection fails or you want to force a specific parser.
From HDF
| Source | Destination | Description |
|---|---|---|
hdf | csv | Export requirements to CSV spreadsheet |
hdf | html | Render a self-contained HTML report (--report-type executive, manager or administrator); several inputs or a directory with -o <file> make one combined report |
hdf | ecs | Export findings as Elastic Common Schema (ECS 9.4.0) NDJSON events |
hdf | splunk | Export findings as Splunk HEC (CIM Vulnerabilities) NDJSON events |
hdf | ocsf | Export findings as OCSF v1.8.0 Finding NDJSON (Compliance / Vulnerability Finding) |
hdf | asff | Export findings as an AWS Security Finding Format {"Findings":[...]} envelope (Security Hub / BatchImportFindings) |
hdf | xml | Export requirements to XML |
hdf | xccdf | Export to XCCDF results XML |
hdf | ckl | Export to DISA STIG Viewer checklist (.ckl XML) |
hdf | cklb | Export to DISA STIG Viewer 3.x checklist (.cklb JSON) |
hdf | oscal-sar | Export to OSCAL Assessment Results |
hdf | hdf@2 | Export to the legacy Heimdall HDF schema (InSpec exec-json shape; loads in Heimdall2) |
hdf-amendments | csaf-vex | Export HDF Amendments as CSAF VEX advisory (partial-fidelity round-trip) |
hdf-amendments | openvex | Export HDF Amendments as OpenVEX statements (partial-fidelity round-trip) |
hdf-amendments | cyclonedx-vex | Export HDF Amendments as CycloneDX BOM with VEX analysis (partial-fidelity round-trip) |
hdf-amendments | oscal-poam | Export to OSCAL Plan of Action and Milestones |
Both --from and --to accept format@version when a format has more than one schema version: --to hdf@2 writes the legacy Heimdall schema, --to hdf@3 (the default) writes the modern one, and --from hdf@2 reads a legacy document back. The same syntax selects an input schema version elsewhere, as in --from sarif@2.0. Note that hdf@1 is not a distinct schema — for raw InSpec output use --from inspec.
Credential Handling
The fetch commands connect to live APIs. Credentials are never accepted as CLI flags to prevent exposure in shell history, process listings, and CI logs.
| Service | Environment Variable | Config File Fallback |
|---|---|---|
| AWS Config | AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY | ~/.aws/credentials (via AWS SDK credential chain) |
| DefectDojo | DEFECTDOJO_API_TOKEN | None |
| GitLab | GITLAB_TOKEN or GLAB_TOKEN | glab CLI config (glab auth login) |
| SonarQube | SONARQUBE_TOKEN | None |
| Splunk | SPLUNK_TOKEN | None |
For GitLab, the glab CLI config is read from the platform's standard config directory:
| Platform | Config Path |
|---|---|
| Linux | $XDG_CONFIG_HOME/glab-cli/config.yml (default: ~/.config/glab-cli/) |
| macOS | ~/Library/Application Support/glab-cli/config.yml |
| Windows | %LOCALAPPDATA%\glab-cli\config.yml |
Override with the GLAB_CONFIG_DIR environment variable on any platform.
Development
See the monorepo root README and the developer guide for full architecture and contribution guidelines.
Quick Reference
From the monorepo root:
pnpm build # build everything (schema types + hdf binary)
pnpm test # run all tests (Go + TypeScript)
pnpm lint # run golangci-lintFrom within hdf-cli/ directly:
go build -o hdf ./cmd/hdf # build the binary
go test ./... -v # run all Go tests
pnpm fmt # gofmt -s -w .
pnpm vet # go vet ./...
pnpm test:coverage # coverage report (generates coverage.out)Adding a New Converter
See Writing a Converter for the full process. In brief:
- Implement Go converter in
hdf-converters/converters/<name>/go/converter.go - Implement TypeScript converter in
hdf-converters/converters/<name>/typescript/converter.ts - Register the converter in
hdf-converters/registry/convert/converter_<name>.gowith aninit()that calls the helper for its output type:registerHDFConverter(results),registerHDFBaselineConverter(baseline),registerHDFPlanConverter(plan), orregisterHDFAmendmentsConverter(amendments) - Add the converter's fingerprint blank-import to
hdf-converters/registry/all/all.goso auto-detection sees it - Add tests for all layers, including the CLI integration test at
hdf-cli/cmd/hdf/cmd/converter_<name>_test.go(the CLI holds no per-converter registration code;converter_registry.goonly re-exports the shared registry) - Source real fixtures from tool output -- never fabricate test data
Test Fixtures
Command tests (validate, query, list, etc.) load HDF fixtures from ../hdf-schema/test/fixtures/. Converter tests load format-specific fixtures from ../hdf-converters/converters/{tool}/fixtures/. Both skip gracefully if the fixture directories are absent.
License
Apache 2.0 -- Approved for Public Release; Distribution Unlimited. Case Number 18-3678.
Copyright 2024-2026 The MITRE Corporation.