diff --git a/HISTORY.md b/HISTORY.md index 256d7b434..7eddd21ba 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,13 @@ All notable changes to this project will be documented in this file. +* Changed + * The provided XML validation capabilities are hardened (via [#1064]; concerns [#1061]) + This is considered a security measure concerning XML external entity (XXE) injection. + +[#1061]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1061 +[#1064]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1064 + ## 6.7.1 -- 2024-05-07 Reverted v6.7.0, back to v6.6.1 diff --git a/src/validation/xmlValidator.node.ts b/src/validation/xmlValidator.node.ts index 667657ad0..91f9e4b06 100644 --- a/src/validation/xmlValidator.node.ts +++ b/src/validation/xmlValidator.node.ts @@ -48,7 +48,11 @@ async function getParser (): Promise { const xmlParseOptions: Readonly = Object.freeze({ nonet: true, - compact: true + compact: true, + // explicitly prevent XXE + // see https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + noent: false, + dtdload: false }) export class XmlValidator extends BaseValidator { diff --git a/tests/_data/xxe_flag.txt b/tests/_data/xxe_flag.txt new file mode 100644 index 000000000..1e47dc1e1 --- /dev/null +++ b/tests/_data/xxe_flag.txt @@ -0,0 +1,4 @@ +This file is target of XXE injection tests. +The flag is: + +vaiquia2zoo3Im8ro9zahNg5mohwipouka2xieweed6ahChei3doox2fek3ise0lmohju3loh5oDu7eigh3jaeR2aiph2Voo diff --git a/tests/integration/Validation.XmlValidator.test.js b/tests/integration/Validation.XmlValidator.test.js index 17a273aa8..fc54ee081 100644 --- a/tests/integration/Validation.XmlValidator.test.js +++ b/tests/integration/Validation.XmlValidator.test.js @@ -18,6 +18,10 @@ Copyright (c) OWASP Foundation. All Rights Reserved. */ const assert = require('assert') +const { realpathSync } = require('fs') +const { join } = require('path') +const { pathToFileURL } = require('url') + const { describe, it } = require('mocha') let hasDep = true @@ -99,5 +103,32 @@ describe('Validation.XmlValidator', () => { const validationError = await validator.validate(input) assert.strictEqual(validationError, null) }) + + it('is not affected by XXE injection', async () => { + const validator = new XmlValidator(version) + const input = ` + + ]> + + + + bar + 1.337 + ${version === '1.0' ? 'false' : ''} + + + &flag; + + + + + ` + const validationError = await validator.validate(input) + assert.doesNotMatch( + JSON.stringify(validationError), + /vaiquia2zoo3Im8ro9zahNg5mohwipouka2xieweed6ahChei3doox2fek3ise0lmohju3loh5oDu7eigh3jaeR2aiph2Voo/ + ) + }) })) })