Observation
cognis_mil.exporters.to_oscal sets each finding's target.target-id to the raw NIST id straight off the finding:
"target": {
"type": "objective-id",
"target-id": f.nist_800_53 or f.id,
...
}
So an enhancement control comes out as AC-6(2). Meanwhile comint_osquery.feeds._to_oscal_id already normalizes the same id to the canonical OSCAL form ac-6.2 for catalog lookups. The two representations disagree within the same tool.
Why it matters
GRC platforms that ingest the OSCAL SAR and try to line the target-id up against a NIST 800-53 rev5 OSCAL catalog (control ids are lowercase dotted, e.g. ac-6.2) won't match AC-6(2). The finding's control reference then dangles.
Suggested fix
Normalize target-id (and the implementation-statement-uuid seed) through the same AC-6(2) → ac-6.2 transform the feeds layer uses, or expose that normalizer from a shared place so both call sites agree. Keep the human-readable id in a prop if it's useful for display.
Low risk, deterministic; would need the existing test_oscal_export.py expectations updated.
Observation
cognis_mil.exporters.to_oscalsets each finding'starget.target-idto the raw NIST id straight off the finding:So an enhancement control comes out as
AC-6(2). Meanwhilecomint_osquery.feeds._to_oscal_idalready normalizes the same id to the canonical OSCAL formac-6.2for catalog lookups. The two representations disagree within the same tool.Why it matters
GRC platforms that ingest the OSCAL SAR and try to line the
target-idup against a NIST 800-53 rev5 OSCAL catalog (control ids are lowercase dotted, e.g.ac-6.2) won't matchAC-6(2). The finding's control reference then dangles.Suggested fix
Normalize
target-id(and theimplementation-statement-uuidseed) through the sameAC-6(2)→ac-6.2transform the feeds layer uses, or expose that normalizer from a shared place so both call sites agree. Keep the human-readable id in a prop if it's useful for display.Low risk, deterministic; would need the existing
test_oscal_export.pyexpectations updated.