From 7b133ff30f65f7520dfdb69f1be4b012fc74c6ac Mon Sep 17 00:00:00 2001 From: Matthew Burket Date: Mon, 12 Jan 2026 12:40:15 -0600 Subject: [PATCH] Fix schema ordering when adding tailoring to ARF files Now the tailoring is added just before the extended-components (i.e. SCE). Created in part by Claude Code. Fixes #2260 --- src/DS/rds.c | 11 +++- tests/API/XCCDF/tailoring/all.sh | 24 ++++++++- .../API/XCCDF/tailoring/ds_with_sce.xccdf.xml | 53 +++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/API/XCCDF/tailoring/ds_with_sce.xccdf.xml diff --git a/src/DS/rds.c b/src/DS/rds.c index af3ae006fd..fc872b2be9 100644 --- a/src/DS/rds.c +++ b/src/DS/rds.c @@ -737,7 +737,16 @@ static int _ds_rds_create_from_dom(xmlDocPtr *ret, xmlDocPtr sds_doc, xmlSetProp(tailoring_component, BAD_CAST "id", BAD_CAST tailoring_component_id); xmlSetProp(tailoring_component, BAD_CAST "timestamp", BAD_CAST tailoring_doc_timestamp); xmlAddChild(tailoring_component, tailoring_res_node); - xmlAddChild(sds_res_node, tailoring_component); + + // Insert tailoring component after regular components but before extended-components + // to maintain proper schema ordering (all components must come before extended-components) + xmlNodePtr first_extended_component = node_get_child_element(sds_res_node, "extended-component"); + if (first_extended_component == NULL) { + // no extended component yet, add to the end + xmlAddChild(sds_res_node, tailoring_component); + } else { + xmlAddPrevSibling(first_extended_component, tailoring_component); + } xmlNodePtr checklists_element = NULL; xmlNodePtr datastream_element = node_get_child_element(sds_res_node, "data-stream"); diff --git a/tests/API/XCCDF/tailoring/all.sh b/tests/API/XCCDF/tailoring/all.sh index de6cc043e8..7c1d97acbb 100755 --- a/tests/API/XCCDF/tailoring/all.sh +++ b/tests/API/XCCDF/tailoring/all.sh @@ -169,6 +169,28 @@ function test_api_xccdf_tailoring_profile_generate_guide { rm -f $guide } +function test_api_xccdf_tailoring_with_extended_component_ordering { + # Regression test for the fix ensuring tailoring extended-component is inserted + # before existing extended-components (e.g. SCE scripts) to maintain schema ordering + # See https://github.com/OpenSCAP/openscap/issues/2260 for more details + + local INPUT=$srcdir/$1 + local TAILORING=$srcdir/$2 + + result=`mktemp` + stderr=`mktemp` + + # Generate ARF with tailoring + $OSCAP xccdf eval --tailoring-file $TAILORING --profile "xccdf_org.open-scap.sce-community-content_profile_pci-dss" --results-arf $result $INPUT 2>$stderr || [ "$?" == "2" ] + + # Validate the ARF against schema - this would fail if ordering is wrong + $OSCAP ds rds-validate $result 2>$stderr + + # Verify that tailoring extended-component exists + assert_exists 1 '/arf:asset-report-collection/arf:report-requests/arf:report-request/arf:content/ds:data-stream-collection/ds:component/xccdf:Tailoring' + rm -f "$result" "$stderr" +} + # Testing. test_init "test_api_xccdf_tailoring.log" @@ -191,6 +213,6 @@ test_run "test_api_xccdf_tailoring_simple_include_in_arf_xlink_namespace" test_a test_run "test_api_xccdf_tailoring_profile_include_in_arf" test_api_xccdf_tailoring_profile_include_in_arf baseline.xccdf.xml baseline.tailoring.xml test_run "test_api_xccdf_tailoring_profile_generate_fix" test_api_xccdf_tailoring_profile_generate_fix baseline.xccdf.xml baseline.tailoring.xml test_run "test_api_xccdf_tailoring_profile_generate_guide" test_api_xccdf_tailoring_profile_generate_guide baseline.xccdf.xml baseline.tailoring.xml - +test_run "test_api_xccdf_tailoring_with_extended_component_ordering" test_api_xccdf_tailoring_with_extended_component_ordering ds_with_sce.xccdf.xml baseline.tailoring.xml test_exit diff --git a/tests/API/XCCDF/tailoring/ds_with_sce.xccdf.xml b/tests/API/XCCDF/tailoring/ds_with_sce.xccdf.xml new file mode 100644 index 0000000000..15ae7c2c77 --- /dev/null +++ b/tests/API/XCCDF/tailoring/ds_with_sce.xccdf.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + draft + SCE in DS + + + + + 1.0 + + + + + + + + + + + + + + + + + + + + + + #!/bin/sh + exit $XCCDF_RESULT_PASS + + +