diff --git a/docs/dev/decisions/XmlValidator.md b/docs/dev/decisions/XmlValidator.md index 7be0de95b..01a437953 100644 --- a/docs/dev/decisions/XmlValidator.md +++ b/docs/dev/decisions/XmlValidator.md @@ -22,7 +22,8 @@ There are several implementations for this: * [`libxmljs3`](https://www.npmjs.com/package/libxmljs3) * unmaintained copy of `libxmljs2` * ! DO NOT USE ! -* Any alternative? Please open a pull-request to add them. +* [`libxml2-wasm`](https://www.npmjs.com/package/libxml2-wasm) + * maintained WASM implementation of a libxml2 wrapper At the moment of writing (2023-04-21), `libxmljs` and `libxmljs2` are both working on several test environments. Both had the needed capabilities. @@ -38,6 +39,10 @@ as it was more popular/used and had a more active community. Decided to replace `libxmljs2`, as it is end of life. +#### 2024-11-26 + +Decided to replace `libxmljs2` with `libxml2-wasm`, since it's maintained and a functioning XML validator. + ## WebBrowsers there seams to exist no solution for validating XML according to XSD diff --git a/package.json b/package.json index 7887fa6b2..0075b9b54 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "ajv-formats-draft2019": "^1.6.1", - "libxmljs2": "^0.31 || ^0.32 || ^0.33 || ^0.35", + "libxml2-wasm": "^0.4.1", "xmlbuilder2": "^3.0.2" }, "devDependencies": { diff --git a/src/_optPlug.node/__xmlValidators/libxml2-wasm.ts b/src/_optPlug.node/__xmlValidators/libxml2-wasm.ts new file mode 100644 index 000000000..463858641 --- /dev/null +++ b/src/_optPlug.node/__xmlValidators/libxml2-wasm.ts @@ -0,0 +1,53 @@ +/*! +This file is part of CycloneDX JavaScript Library. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +import { readFile } from 'fs/promises'; +import { ParseOption, XmlDocument, XsdValidator } from 'libxml2-wasm'; +import { pathToFileURL } from 'url'; + +import type { ValidationError } from '../../validation/types'; +import type { Functionality, Validator } from '../xmlValidator'; + +/** @internal */ +export default (async function (schemaPath: string): Promise { + const schema = XmlDocument.fromString( + await readFile(schemaPath, 'utf-8'), + { + option: ParseOption.XML_PARSE_NONET | ParseOption.XML_PARSE_COMPACT, + url: pathToFileURL(schemaPath).toString() + }); + const validator = XsdValidator.fromDoc(schema); + + return function (data: string): null | ValidationError { + const doc = XmlDocument.fromString(data, { option: ParseOption.XML_PARSE_NONET | ParseOption.XML_PARSE_COMPACT }); + let errors = null; + try { + validator.validate(doc); + } + catch (validationErrors) { + errors = validationErrors; + } + + doc.dispose(); + validator.dispose(); + schema.dispose(); + + return errors; + } +}) satisfies Functionality diff --git a/src/_optPlug.node/__xmlValidators/libxmljs2.ts b/src/_optPlug.node/__xmlValidators/libxmljs2.ts deleted file mode 100644 index a72989722..000000000 --- a/src/_optPlug.node/__xmlValidators/libxmljs2.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*! -This file is part of CycloneDX JavaScript Library. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -SPDX-License-Identifier: Apache-2.0 -Copyright (c) OWASP Foundation. All Rights Reserved. -*/ - -import { readFile } from 'fs/promises' -import { type ParserOptions, parseXml } from 'libxmljs2' -import { pathToFileURL } from 'url' - -import type { ValidationError } from '../../validation/types' -import type { Functionality, Validator } from '../xmlValidator' - -const xmlParseOptions: Readonly = Object.freeze({ - nonet: true, - compact: true, - // explicitly prevent XXE - // see https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html - // see https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1061 - noent: false, - dtdload: false -}) - -/** @internal */ -export default (async function (schemaPath: string): Promise { - const schema = parseXml(await readFile(schemaPath, 'utf-8'), - { ...xmlParseOptions, baseUrl: pathToFileURL(schemaPath).toString() }) - - return function (data: string): null | ValidationError { - const doc = parseXml(data, xmlParseOptions) - return doc.validate(schema) - ? null - : doc.validationErrors - } -}) satisfies Functionality diff --git a/src/_optPlug.node/xmlValidator.ts b/src/_optPlug.node/xmlValidator.ts index 67b92a2be..1f4aed70e 100644 --- a/src/_optPlug.node/xmlValidator.ts +++ b/src/_optPlug.node/xmlValidator.ts @@ -27,7 +27,7 @@ export default opWrapper('XmlValidator', [ /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-require-imports -- needed */ - ['libxmljs2', () => require('./__xmlValidators/libxmljs2').default] + ['libxml2-wasm', () => require('./__xmlValidators/libxml2-wasm').default] // ... add others here, pull-requests welcome! /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-require-imports */