Skip to content

Commit ac6397d

Browse files
Produce Metaschemas without XXEs (#1665) (#1901)
* Produce Metaschemas without XXEs (#1665) * ADR for XXE resolution * Accepted ADR 5 * Apply suggestions from code review Co-authored-by: A.J. Stein <alexander.stein@nist.gov> * Revert release artifact archive readme extension change --------- Co-authored-by: A.J. Stein <alexander.stein@nist.gov>
1 parent 563ecb3 commit ac6397d

File tree

6 files changed

+148
-11
lines changed

6 files changed

+148
-11
lines changed

build/Makefile

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ help: ## Show this help message
1414
all: artifacts checks archives ## Run all pipelines
1515

1616
.PHONY: artifacts
17-
artifacts: schemas converters ## Generate all artifacts
17+
artifacts: schemas converters resolved-metaschemas ## Generate all artifacts
1818

1919
.PHONY: checks
2020
checks: linkcheck validate test-profile-resolution ## Run all tests and checks
@@ -26,11 +26,13 @@ node_modules: package.json package-lock.json
2626
npm ci
2727

2828
.PHONY: clean
29-
clean: clean-schemas clean-linkcheck clean-converters clean-archives ## Remove all generated content
29+
clean: clean-schemas clean-linkcheck clean-converters clean-archives clean-resolved-metaschemas ## Remove all generated content
3030

3131
METASCHEMA_XSLT_COMMAND:=metaschema-xslt/bin/metaschema-xslt
3232
SRC_DIR:=../src/metaschema
33-
# Contains the metaschemas that do not contain "common" or "metadata"
33+
# Contains all OSCAL metaschema modules, including those without exported roots
34+
ALL_METASCHEMAS:=$(shell find $(SRC_DIR) -name '*_metaschema.xml')
35+
# Contains the OSCAL metaschema modules that contain root assemblies
3436
METASCHEMAS:=$(shell find $(SRC_DIR) -name '*_metaschema.xml' -a ! -name '*common*' -a ! -name '*metadata*')
3537
GENERATED_DIR:=generated
3638

@@ -71,6 +73,33 @@ clean-converters: ## Remove generated converters
7173
rm -fr $(GENERATED_DIR)/*_xml-to-json-converter.xsl
7274
rm -fr $(GENERATED_DIR)/*_json-to-xml-converter.xsl
7375

76+
###################################
77+
# Resolved Metaschemas Generation #
78+
###################################
79+
80+
POM_PATH:=./pom.xml
81+
define EXEC_SAXON
82+
mvn --quiet -f "$(POM_PATH)" exec:java \
83+
-Dexec.mainClass="net.sf.saxon.Transform" \
84+
-Dexec.args="$1"
85+
endef
86+
87+
RESOLVER_STYLESHEET:=./resolve-entities.xsl
88+
89+
RESOLVED_METASCHEMA_SUFFIX:=RESOLVED
90+
RESOLVED_METASCHEMAS:=$(patsubst $(SRC_DIR)/%_metaschema.xml,$(GENERATED_DIR)/%_metaschema_$(RESOLVED_METASCHEMA_SUFFIX).xml,$(ALL_METASCHEMAS))
91+
92+
$(GENERATED_DIR)/%_metaschema_$(RESOLVED_METASCHEMA_SUFFIX).xml: $(SRC_DIR)/%_metaschema.xml
93+
@mkdir -p $(GENERATED_DIR)
94+
$(call EXEC_SAXON,-s:$(SRC_DIR)/$*_metaschema.xml -xsl:$(RESOLVER_STYLESHEET) -o:$@ importHrefSuffix=$(RESOLVED_METASCHEMA_SUFFIX))
95+
96+
.PHONY: resolved-metaschemas
97+
resolved-metaschemas: $(RESOLVED_METASCHEMAS) ## Generate the resolved metaschema modules
98+
99+
.PHONY: clean-resolved-metaschemas
100+
clean-resolved-metaschemas: ## Remove generated resolvd metaschema modules
101+
rm -f $(RESOLVED_METASCHEMAS)
102+
74103
######################
75104
# Archive Generation #
76105
######################
@@ -83,14 +112,15 @@ ARCHIVE_TEMP_DIR:=$(GENERATED_DIR)/archive_temp
83112
.PHONY: archives
84113
archives: $(ZIP_ARCHIVE) ## Archive converters and schemas
85114

86-
$(ZIP_ARCHIVE) $(TARBZ2_ARCHIVE): converters schemas
115+
$(ZIP_ARCHIVE) $(TARBZ2_ARCHIVE): converters schemas resolved-metaschemas
87116
@echo Generating archive
88-
mkdir -p $(ARCHIVE_TEMP_DIR)/{json,xml}/{convert,schema}
89-
cp ../src/release/README.txt "$(ARCHIVE_TEMP_DIR)/README.md"
117+
mkdir -p $(ARCHIVE_TEMP_DIR)/{{json,xml}/{convert,schema},metaschema}
118+
cp ../src/release/release-readme.txt "$(ARCHIVE_TEMP_DIR)/README.txt"
90119
cp $(XSD_OUTPUTS) "$(ARCHIVE_TEMP_DIR)/xml/schema"
91120
cp $(JSONSCHEMA_OUTPUTS) "$(ARCHIVE_TEMP_DIR)/json/schema"
92121
cp $(XML2JSON_CONVERTERS) "$(ARCHIVE_TEMP_DIR)/xml/convert"
93122
cp $(JSON2XML_CONVERTERS) "$(ARCHIVE_TEMP_DIR)/json/convert"
123+
cp $(RESOLVED_METASCHEMAS) "$(ARCHIVE_TEMP_DIR)/metaschema"
94124

95125
(cd "$(ARCHIVE_TEMP_DIR)" && zip -r $(abspath $(ZIP_ARCHIVE)) .)
96126
tar -jcvf "$(TARBZ2_ARCHIVE)" -C "$(ARCHIVE_TEMP_DIR)" .
@@ -161,3 +191,17 @@ validate-composition-%:
161191
.PHONY: test-profile-resolution
162192
test-profile-resolution: ## Unit test the profile resolver
163193
$(MAKE) -C ../src/utils/resolver-pipeline test
194+
195+
###################
196+
# Utility Targets #
197+
###################
198+
199+
# These targets may be used by consumers of the OSCAL repository
200+
201+
# All artifacts typically included in a release
202+
RELEASE_ARTIFACTS:=$(XSD_OUTPUTS) $(JSONSCHEMA_OUTPUTS) $(XML2JSON_CONVERTERS) $(JSON2XML_CONVERTERS) $(RESOLVED_METASCHEMAS) $(ZIP_ARCHIVE) $(TARBZ2_ARCHIVE)
203+
204+
# This target is used by OSCAL-Reference to generate meta-redirects for release assets
205+
.PHONY: list-release-artifacts
206+
list-release-artifacts: ## Print out a list of all artifacts typically included in an OSCAL release
207+
@echo $(RELEASE_ARTIFACTS)

build/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ Developers can generate schemas locally using the `make artifacts` command.
3434
Developers can also generate individual artifacts using the following commands:
3535

3636
* `make schemas`: Generates the JSON Schemas and XSDs off of the source Metaschemas;
37-
* `make converters`: Generates the XSLT stylesheets for JSON<->XML conversion off of the source Metaschemas.
37+
* `make converters`: Generates the XSLT stylesheets for JSON<->XML conversion off of the source Metaschemas;
38+
* `make resolved-metaschemas`: Resolves external entities (XXE) present in the source OSCAL Metaschema modules for use with tools that do not support XXEs.
3839

3940
### Checks
4041

build/resolve-entities.xsl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Entity resolver for OSCAL Metaschemas
4+
5+
This stylesheet:
6+
1. Copies an input metaschema module, resolving all external entities
7+
2. Replace all import/@href's to match a given $importHrefSuffix parameter
8+
-->
9+
<xsl:stylesheet version="1.0"
10+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
11+
xmlns:metaschema="http://csrc.nist.gov/ns/oscal/metaschema/1.0">
12+
<xsl:output omit-xml-declaration="no" indent="yes"/>
13+
14+
<xsl:param name="importHrefSuffix" select="'RESOLVED'"/>
15+
16+
<!--
17+
XSLT1.0 compatible string replacement
18+
19+
Via https://gist.github.com/ijy/6572481
20+
-->
21+
<xsl:template name="string-replace">
22+
<xsl:param name="string" />
23+
<xsl:param name="replace" />
24+
<xsl:param name="with" />
25+
26+
<xsl:choose>
27+
<xsl:when test="contains($string, $replace)">
28+
<xsl:value-of select="substring-before($string, $replace)" />
29+
<xsl:value-of select="$with" />
30+
<xsl:call-template name="string-replace">
31+
<xsl:with-param name="string" select="substring-after($string,$replace)" />
32+
<xsl:with-param name="replace" select="$replace" />
33+
<xsl:with-param name="with" select="$with" />
34+
</xsl:call-template>
35+
</xsl:when>
36+
<xsl:otherwise>
37+
<xsl:value-of select="$string" />
38+
</xsl:otherwise>
39+
</xsl:choose>
40+
</xsl:template>
41+
42+
<!-- Simple identity transform, resolving entities implicitly -->
43+
<xsl:template match="@*|node()">
44+
<xsl:copy>
45+
<xsl:apply-templates select="@*|node()"/>
46+
</xsl:copy>
47+
</xsl:template>
48+
49+
<!-- Transform import/@href using $importHrefSuffix -->
50+
<xsl:template match="metaschema:import/@href">
51+
<xsl:attribute name="href">
52+
<!-- oscal_poam_metaschema.xml => oscal_poam_metaschema_$importHrefSuffix.xml -->
53+
<xsl:call-template name="string-replace">
54+
<xsl:with-param name="string" select="." />
55+
<xsl:with-param name="replace" select="'.xml'" />
56+
<xsl:with-param name="with" select="concat('_', $importHrefSuffix, '.xml')" />
57+
</xsl:call-template>
58+
</xsl:attribute>
59+
</xsl:template>
60+
</xsl:stylesheet>

decisions/0005-repository-reorganization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Date: 2023/07/06
55

66
## Status
77

8-
Proposed
8+
Approved
99

1010
## Context
1111

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Production of transformed source Metaschema modules without external entities (XXEs)
2+
3+
Date: 08/25/2023
4+
5+
## Status
6+
7+
Approved
8+
9+
## Context
10+
11+
We wish to remove or mitigate points friction encountered by NIST or community OSCAL developers producing tooling that consumes the OSCAL Metaschema module sources.
12+
13+
The OSCAL Metaschema modules currently use external entities to prevent duplication of constraint data.
14+
These external entities are important for modeling ergonomics and cannot be removed until a Metaschema-native approach is stabilized, however external entities have a storied history of abuse.
15+
So called "XML External Entity (XXE) Attacks", along with the additional complexity needed to support external entity resolution, have led to a situation where many XML parsers do not ship with XXE functionality.
16+
This has put additional burden on OSCAL tool developers seeking to consume the source Metaschemas, who have either had to choose from the small subset of XML parsers that support external entities (if one exists for their target language at all) and inherit all additional risks that come with XXEs, or perform transformation of the source Metaschema modules before consuming them.
17+
18+
- Related to Issue [#1665](https://github.com/usnistgov/OSCAL/issues/1665)
19+
20+
## Decision
21+
22+
The NIST OSCAL Team should include the "resolved" Metaschema module sources as an artifact generated upon release.
23+
Additionally, the NIST OSCAL Team should document the process for obtaining a resolved Metaschema module as part of the [streamlined build process](./0005-repository-reorganization.md#streamlined-build-process).
24+
25+
In the event that Metaschema stabilizes constraint imports, the NIST OSCAL Team will review this ADR and potentially determine a deprecation strategy for these generated artifacts in the relevant releases.
26+
27+
## Consequences
28+
29+
This decision will not have any breaking changes to our process, however:
30+
31+
1. The NIST team will be responsible for reviewing the additional artifacts before performing a release.
32+
2. In the event that Metaschema stabilizes constraint imports, the NIST OSCAL team will have to maintain deprecated artifacts until the next major version.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Documentation for the OSCAL models can be found at: https://pages.nist.gov/OSCAL
99

1010
This release provides 2 types of resources, each located in a different subdirectory:
1111

12-
- xml: Provides the XML schemas and content converters that are needed to support the OSCAL model XML-based formats. Instructions for using this information can be found at: https://github.com/usnistgov/OSCAL/tree/master/xml.
13-
- json: Provides the JSON schemas and content converters that are needed to support the OSCAL model JSON-based formats. Instructions for using this information can be found at: https://github.com/usnistgov/OSCAL/tree/master/json.
12+
- `xml/` and `json/`: Provides the XML and JSON schemas and content converters that are needed to support the OSCAL model. Instructions for using these artifacts can be found at https://github.com/usnistgov/OSCAL/blob/develop/build/README.md#artifact-usage
13+
- `metaschema/`: Provides the source OSCAL Metaschema modules with all external entities (XXE) resolved for tools that do not support XXEs.
1414

1515
These directories provide stable, released versions of the resources provided on the OSCAL GitHub repository: https://github.com/usnistgov/OSCAL.
1616

@@ -32,6 +32,6 @@ OSCAL is being developed in a public GitHub repository, in collaboration with in
3232
- Help with developing OSCAL models and associated content.
3333
- Assistance with developing documentation, tutorials, and other informational resources.
3434

35-
If you are interested in helping, please visit or contributing page for more information at: https://github.com/usnistgov/OSCAL/blob/master/CONTRIBUTING.md.
35+
If you are interested in helping, please visit or contributing page for more information at: https://github.com/usnistgov/OSCAL/blob/main/CONTRIBUTING.md.
3636

3737
Please direct any questions, comments, concerns, or kudos by email to: oscal@nist.gov.

0 commit comments

Comments
 (0)