{"id":1371183,"name":"@xmldom/xmldom","ecosystem":"npm","description":"A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.","homepage":"https://github.com/xmldom/xmldom","licenses":"MIT","normalized_licenses":["MIT"],"repository_url":"https://github.com/xmldom/xmldom","keywords_array":["w3c","dom","xml","parser","javascript","DOMParser","XMLSerializer","ponyfill"],"namespace":"xmldom","versions_count":54,"first_release_published_at":"2021-08-19T19:35:11.460Z","latest_release_published_at":"2026-08-21T22:32:42.389Z","latest_release_number":"0.9.12","last_synced_at":"2026-10-09T12:21:05.150Z","created_at":"2022-04-08T22:45:25.721Z","updated_at":"2026-10-09T12:21:05.151Z","registry_url":"https://www.npmjs.com/package/@xmldom/xmldom","install_command":"npm install @xmldom/xmldom","documentation_url":null,"metadata":{"funding":null,"dist-tags":{"lts":"0.8.15","latest":"0.9.12"},"contentPolicy":null},"repo_metadata":{"id":37351951,"uuid":"229145432","full_name":"xmldom/xmldom","owner":"xmldom","description":"A pure JavaScript W3C standard-based (XML DOM Level 2 Core) `DOMParser` and `XMLSerializer` module.","archived":false,"fork":false,"pushed_at":"2026-10-06T06:08:36.000Z","size":4906,"stargazers_count":471,"open_issues_count":63,"forks_count":100,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-10-06T17:55:21.480Z","etag":null,"topics":["dom","hacktoberfest","html","javascript","xml"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xmldom.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2019-12-19T21:59:46.000Z","updated_at":"2026-10-04T11:40:41.000Z","dependencies_parsed_at":"2026-08-17T09:33:35.670Z","dependency_job_id":null,"html_url":"https://github.com/xmldom/xmldom","commit_stats":{"total_commits":764,"total_committers":58,"mean_commits":"13.172413793103448","dds":0.5615183246073299,"last_synced_commit":"1dab19d106f445f4878681fd70e4b5e0f57adc58"},"previous_names":[],"tags_count":100,"template":false,"template_full_name":null,"purl":"pkg:github/xmldom/xmldom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmldom","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/sbom","scorecard":{"id":165596,"data":{"date":"2025-08-16T12:55:34Z","repo":{"name":"github.com/xmldom/xmldom","commit":"1bb6a48841941c0f00bb760b96ad3130b601db25"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":8.4,"checks":[{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: RenovateBot: renovate.json:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:25","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:26","Info: topLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:18","Info: topLevel 'contents' permission set to 'read': .github/workflows/dependency-review.yml:13","Info: topLevel 'contents' permission set to 'read': .github/workflows/examples.yml:11","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:18","Info: topLevel 'contents' permission set to 'read': .github/workflows/test-node.js.yml:13","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":7,"reason":"dependency not pinned by hash detected -- score normalized to 7","details":["Warn: npmCommand not pinned by hash: examples/typescript-node-es6/pretest.sh:6","Warn: npmCommand not pinned by hash: examples/typescript-node-es6/pretest.sh:7","Warn: npmCommand not pinned by hash: .github/workflows/examples.yml:39","Info:  17 out of  17 GitHub-owned GitHubAction dependencies pinned","Info:   8 out of   8 third-party GitHubAction dependencies pinned","Info:   2 out of   5 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":5,"reason":"badge detected: Passing","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Branch-Protection","score":5,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'master'","Warn: 'stale review dismissal' is disabled on branch 'master'","Warn: required approving review count is 1 on branch 'master'","Warn: codeowners review is not required on branch 'master'","Warn: 'last push approval' is disabled on branch 'master'","Info: 'up-to-date branches' is required to merge on branch 'master'","Info: status check found to merge onto on branch 'master'","Info: PRs are required in order to make changes on branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 0.9.8 not signed: https://api.github.com/repos/xmldom/xmldom/releases/203058035","Warn: release artifact 0.9.7 not signed: https://api.github.com/repos/xmldom/xmldom/releases/195528492","Warn: release artifact 0.9.6 not signed: https://api.github.com/repos/xmldom/xmldom/releases/189102275","Warn: release artifact 0.9.5 not signed: https://api.github.com/repos/xmldom/xmldom/releases/182073233","Warn: release artifact 0.9.4 not signed: https://api.github.com/repos/xmldom/xmldom/releases/179708206","Warn: release artifact 0.9.8 does not have provenance: https://api.github.com/repos/xmldom/xmldom/releases/203058035","Warn: release artifact 0.9.7 does not have provenance: https://api.github.com/repos/xmldom/xmldom/releases/195528492","Warn: release artifact 0.9.6 does not have provenance: https://api.github.com/repos/xmldom/xmldom/releases/189102275","Warn: release artifact 0.9.5 does not have provenance: https://api.github.com/repos/xmldom/xmldom/releases/182073233","Warn: release artifact 0.9.4 does not have provenance: https://api.github.com/repos/xmldom/xmldom/releases/179708206"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (30) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: OSSFuzz integration found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"CI-Tests","score":10,"reason":"30 out of 30 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}},{"name":"Contributors","score":10,"reason":"project has 11 contributing companies or organizations","details":["Info: found contributions from: CACI-International, MayOneUS, abolishmalapportionment-us, apple, baidu, bettermarks, bettermarks gmbh, glyphr-studio, ks-tech, rooseveltframework, xmldom"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}}]},"last_synced_at":"2025-08-16T14:44:35.948Z","repository_id":37351951,"created_at":"2025-08-16T14:44:35.948Z","updated_at":"2025-08-16T14:44:35.948Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":343170754,"owners_count":38101773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-06T02:00:06.537Z","response_time":86,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"},"owner_record":{"login":"xmldom","name":"xmldom","uuid":"34722805","kind":"organization","description":"The group of maintainers behind the the xmldom library","email":null,"website":"https://xmldom.org","location":null,"twitter":null,"company":null,"icon_url":"https://avatars.githubusercontent.com/u/34722805?v=4","repositories_count":3,"last_synced_at":"2026-10-06T10:59:02.633Z","metadata":{"has_sponsors_listing":false,"funding":null},"html_url":"https://github.com/xmldom","funding_links":[],"total_stars":474,"followers":7,"following":0,"created_at":"2022-11-02T16:25:18.619Z","updated_at":"2026-10-06T10:59:02.647Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmldom","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmldom/repositories"},"tags":[{"name":"0.9.11","sha":"1f0610959ab7b82cc7ad702d1be0243efc5791c0","kind":"tag","published_at":"2026-08-12T19:34:49.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.11","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.11","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.11","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.11","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.11/manifests"},{"name":"0.8.14","sha":"8a83f8ebf53604a733cb580bfc4ff9c0ae014d92","kind":"tag","published_at":"2026-08-12T19:18:39.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.14","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.14","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.14","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.14","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.14/manifests"},{"name":"0.9.10","sha":"bf396a575c4dd32ce4bd925b849dcb7e778d957c","kind":"tag","published_at":"2026-04-18T11:33:59.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.10","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.10","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.10","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.10","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.10/manifests"},{"name":"0.8.13","sha":"e5c14802592685bb872c042c54c3f73758875c85","kind":"tag","published_at":"2026-04-18T11:27:40.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.13","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.13","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.13","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.13","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.13/manifests"},{"name":"0.1.23","sha":"b7a4daa6714b28086171cd5ff08f0a21c684fb9a","kind":"tag","published_at":"2026-04-08T08:28:01.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.23","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.23","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.23","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.23","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.23/manifests"},{"name":"0.1.31","sha":"91e456310880c24ae97629bd5754f96ffcb623c5","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.31","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.31","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.31","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.31","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.31/manifests"},{"name":"0.1.30","sha":"1710ba339a81ad18235d4a4c626c6e8805b1a17d","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.30","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.30","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.30","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.30","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.30/manifests"},{"name":"0.1.29","sha":"226be66a785fd6ccc11ccdd14bd32fa4c9f65780","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.29","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.29","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.29","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.29","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.29/manifests"},{"name":"0.1.27","sha":"b53aa82a36160d85faab394035dcd1784764537f","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.27","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.27","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.27","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.27","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.27/manifests"},{"name":"0.1.26","sha":"b53aa82a36160d85faab394035dcd1784764537f","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.26","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.26","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.26","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.26","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.26/manifests"},{"name":"0.1.25","sha":"b53aa82a36160d85faab394035dcd1784764537f","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.25","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.25","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.25","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.25","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.25/manifests"},{"name":"0.1.24","sha":"b53aa82a36160d85faab394035dcd1784764537f","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.24","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.24","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.24","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.24","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.24/manifests"},{"name":"0.1.22","sha":"29a83b315aef56c156602286b2d884a3b4c2521f","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.22","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.22","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.22","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.22","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.22/manifests"},{"name":"0.1.21","sha":"57b1d7757130502d30fd311d651ae4e46c77dde6","kind":"tag","published_at":"2026-04-08T06:25:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.21","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.21","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.21","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.21","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.21/manifests"},{"name":"0.1.20","sha":"2d3c3dbb0a561e916f53fccfa02d8df5f6a9c89f","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.20","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.20","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.20","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.20","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.20/manifests"},{"name":"0.1.19","sha":"c033b1907c049ee10a9cc71133925480f03e7134","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.19","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.19","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.19","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.19","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.19/manifests"},{"name":"0.1.18","sha":"9ddac14e5e2ad9672832ee5a6f503fa8e5d579a3","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.18","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.18","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.18","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.18","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.18/manifests"},{"name":"0.1.17","sha":"87f63e6f3aaab8c8b6e5a297b07be4c685061290","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.17","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.17","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.17","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.17","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.17/manifests"},{"name":"0.1.16","sha":"b47c082dad42811f63e46b76e8daf12495c7902b","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.16","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.16","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.16","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.16","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.16/manifests"},{"name":"0.1.15","sha":"557752baf569befed6bc2fa531084d499d1ff746","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.15","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.15","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.15","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.15","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.15/manifests"},{"name":"0.1.14","sha":"b17cf5a6611d2c3c51c48136ebe5ea4467a729d8","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.14","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.14","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.14","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.14","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.14/manifests"},{"name":"0.1.13","sha":"eb17b3af06eae4d7d29c5debe74780e347deb0b3","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.13","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.13","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.13","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.13","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.13/manifests"},{"name":"0.1.12","sha":"47fa9b8e64dfb8da193959544b1aa69e2195517f","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.12","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.12","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.12","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.12","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.12/manifests"},{"name":"0.1.11","sha":"a3b013dab1b574cc4467bbe59257c0fa6457aae8","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.11","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.11","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.11","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.11","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.11/manifests"},{"name":"0.1.10","sha":"f98cfea177a4faec36b4cdfa1cb841c0c836872a","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.10","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.10","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.10","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.10","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.10/manifests"},{"name":"0.1.9","sha":"f385dbe00546110e4233e2bd1a0df13b1d09a5dd","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.9","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.9/manifests"},{"name":"0.1.8","sha":"c9f94a8c0c3bfd8eea5c2050bffed09d765f61f3","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.8","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.8/manifests"},{"name":"0.1.7","sha":"7b37f00b149c4424d24ea12077c41516a3b8630a","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.7","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.7/manifests"},{"name":"0.1.6","sha":"ae0a15e8c39ab580d8f06dc957d0f0794123a24c","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.6","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.6/manifests"},{"name":"0.1.5","sha":"36d3a1d0f09f2f0fea3d9922113bddcb3dd0e957","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.5","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.5/manifests"},{"name":"0.1.4","sha":"93959ad15beaa76f2683a7470094a9e378474088","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.4","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.4/manifests"},{"name":"0.1.3","sha":"2943798f56d56922b04f6bb7701f981369198095","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.3","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.3/manifests"},{"name":"0.1.2","sha":"7ff5ef0f37173bfd3629dbf762660df5b34e9652","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.2","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.2/manifests"},{"name":"0.1.1","sha":"d779f83facaefeb8f9f29a000323cb40a8bf7769","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.1/manifests"},{"name":"0.1.0","sha":"64cd7b6e5ef838e98d418d0e90aba5f5db1e4478","kind":"tag","published_at":"2026-04-08T06:25:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.1.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.1.0/manifests"},{"name":"0.9.9","sha":"7ffb16bce1170c7314151379531147637ab772a1","kind":"tag","published_at":"2026-03-29T19:46:26.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.9","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.9/manifests"},{"name":"0.8.12","sha":"189cb78a83e81e1515880988a399e863a8be85ac","kind":"tag","published_at":"2026-03-29T19:19:23.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.12","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.12","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.12","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.12","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.12/manifests"},{"name":"0.8.11","sha":"c0f14011c7cf93af60b2541898065b7136594f6b","kind":"tag","published_at":"2025-08-17T14:06:34.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.11","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.11","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.11","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.11","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.11/manifests"},{"name":"0.9.8","sha":"4a1e6e9a74d578fab0173ff89f674e8a22c5699e","kind":"tag","published_at":"2025-02-28T15:53:58.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.8","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.8/manifests"},{"name":"0.9.7","sha":"e10cdf11e83f90da3d0d8dcb73bd02977e1ea767","kind":"tag","published_at":"2025-01-19T19:39:15.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.7","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.7/manifests"},{"name":"0.9.6","sha":"0a64f48a968fe247aeaaeaa685739cfc611e459e","kind":"tag","published_at":"2024-12-05T06:26:14.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.6","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.6/manifests"},{"name":"0.9.5","sha":"e4d087e908e6aeb637c4cf322d3bf24da99fd210","kind":"tag","published_at":"2024-10-26T09:28:22.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.5","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.5/manifests"},{"name":"0.9.4","sha":"65d028a98f83285de536827515161e0d2631a85e","kind":"tag","published_at":"2024-10-13T22:59:15.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.4","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.4/manifests"},{"name":"0.9.3","sha":"5b7382fb0070e5fac8584b6d905b8df8e074a6d3","kind":"tag","published_at":"2024-09-21T11:28:26.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.3","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.3/manifests"},{"name":"0.9.2","sha":"b6d02cf7a948979a03c8383eb5a0dde2bb1003cf","kind":"tag","published_at":"2024-09-05T12:30:01.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.2","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.2/manifests"},{"name":"0.9.1","sha":"326e70303b2af9a5b2b84a6c3197a6b043582a63","kind":"tag","published_at":"2024-09-05T04:11:11.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.1/manifests"},{"name":"0.9.0","sha":"8c7c7afe89027641aa59c101d20eefedc0f54c6f","kind":"tag","published_at":"2024-08-29T20:32:35.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0/manifests"},{"name":"0.9.0-beta.11","sha":"6ca5743b796aec160914e90bf3c18173f2d943b1","kind":"tag","published_at":"2023-07-30T08:12:05.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.11","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.11","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.11","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.11","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.11/manifests"},{"name":"0.9.0-beta.10","sha":"1f882d792b43c346c8100cfb82b906f12b85b328","kind":"tag","published_at":"2023-07-19T19:01:00.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.10","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.10","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.10","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.10","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.10/manifests"},{"name":"0.8.10","sha":"252395e8f0409ad7193589a87b62aa6a8ced8cdc","kind":"tag","published_at":"2023-07-19T18:31:15.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.10","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.10","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.10","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.10","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.10/manifests"},{"name":"0.7.13","sha":"282f0ada331a445d721f3a8224836123e9b916b9","kind":"tag","published_at":"2023-07-19T18:25:26.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.13","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.13","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.13","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.13","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.13/manifests"},{"name":"0.9.0-beta.9","sha":"48953f6e6d1d49093c8014c4585b31833de78812","kind":"tag","published_at":"2023-07-13T03:11:43.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.9","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.9/manifests"},{"name":"0.8.9","sha":"b87f2bdd83c3fa27f8184b2cfbc492bd2442f90d","kind":"tag","published_at":"2023-07-13T02:46:05.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.9","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.9/manifests"},{"name":"0.7.12","sha":"f3c7be329e9a453b07624bf8e103a227d1964888","kind":"tag","published_at":"2023-07-13T02:36:34.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.12","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.12","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.12","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.12","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.12/manifests"},{"name":"0.9.0-beta.8","sha":"b4441ee72485aff9798b749bb9f1fa29442e6b7a","kind":"tag","published_at":"2023-06-11T14:44:40.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.8","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.8/manifests"},{"name":"0.9.0-beta.7","sha":"2db14b976cb929bbed222337843c89f9eade5741","kind":"tag","published_at":"2023-06-09T13:00:20.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.7","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.7/manifests"},{"name":"0.7.11","sha":"44477fc10639a61a689f99c131936564e4a696a5","kind":"tag","published_at":"2023-05-30T19:12:09.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.11","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.11","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.11","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.11","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.11/manifests"},{"name":"0.8.8","sha":"a26058a3367896141c51a7ae8dfea19f3c7a5bf7","kind":"tag","published_at":"2023-05-30T19:02:18.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.8","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.8/manifests"},{"name":"0.8.7","sha":"b69bbbe278f81c63900959c38a8869f690482631","kind":"tag","published_at":"2023-03-31T09:15:37.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.7","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.7/manifests"},{"name":"0.7.10","sha":"f97cb3a833e8fdac332adbb52b24684a1e1aa5b1","kind":"tag","published_at":"2023-03-31T08:48:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.10","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.10","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.10","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.10","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.10/manifests"},{"name":"0.7.9","sha":"927392f627e8f9cf1ea051612c7996596a904c78","kind":"tag","published_at":"2022-11-05T10:14:35.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.9","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.9/manifests"},{"name":"0.8.6","sha":"238b1ea8431fae8817812c68d55b4933248af07e","kind":"tag","published_at":"2022-11-05T10:00:42.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.6","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.6/manifests"},{"name":"0.9.0-beta.6","sha":"4ca999173d86f0e6ff89c3fd09295fe1c28562eb","kind":"tag","published_at":"2022-11-03T08:03:35.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.6","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.6/manifests"},{"name":"0.7.8","sha":"0d6e3a132ec6eb32a67cfca327477a2098d4b55c","kind":"tag","published_at":"2022-10-31T16:25:01.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.8","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.8/manifests"},{"name":"0.8.5","sha":"afc57ec6f7348e96a5ca6aa59d4c21a106ca2cd8","kind":"tag","published_at":"2022-10-31T08:59:36.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.5","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.5/manifests"},{"name":"0.9.0-beta.5","sha":"784786b4301b8d15bb73403d3a73fc2d7ae091ee","kind":"tag","published_at":"2022-10-31T08:41:12.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.5","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.5/manifests"},{"name":"0.8.4","sha":"27fec1ff2fbc5a57ac3ab372d0a1efa230ece918","kind":"tag","published_at":"2022-10-29T22:04:40.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.4","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.4/manifests"},{"name":"0.7.7","sha":"fe5b043fd07bbfed7f039b77d0b9e1a1eb832a2a","kind":"tag","published_at":"2022-10-29T21:56:23.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.7","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.7/manifests"},{"name":"0.9.0-beta.4","sha":"39bc1fcb5d7593f657349836c219f7b489c45518","kind":"tag","published_at":"2022-10-29T21:44:58.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.4","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.4/manifests"},{"name":"0.9.0-beta.3","sha":"4a990d364e513f4cf35b86ebd7c08ab67a6210a2","kind":"tag","published_at":"2022-10-18T05:33:39.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.3","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.3/manifests"},{"name":"0.7.6","sha":"3ca016d7da634686dbcadd076dda07d28a8ffd45","kind":"tag","published_at":"2022-10-16T16:31:37.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.6","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.6/manifests"},{"name":"0.8.3","sha":"c9df7a299aa2862780c7b6e308f0f0dbcffd0a8c","kind":"tag","published_at":"2022-10-11T03:54:58.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.3","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.3/manifests"},{"name":"0.9.0-beta.2","sha":"e20c2d4a030865559b6ceb6f8f6c7d7e3c447828","kind":"tag","published_at":"2022-10-11T03:47:00.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.2","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.2/manifests"},{"name":"0.9.0-beta.1","sha":"0b21623512cf859a6341122524abda5bbf92b44f","kind":"tag","published_at":"2022-10-09T00:14:47.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.9.0-beta.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.9.0-beta.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.9.0-beta.1/manifests"},{"name":"0.8.2","sha":"021211132164ad4686d0a561cf4aa063dd1674e1","kind":"tag","published_at":"2022-04-05T18:34:03.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.2","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.2/manifests"},{"name":"0.8.1","sha":"21b6142c641f4c7778c35afb545533ad3c22b393","kind":"tag","published_at":"2022-02-14T13:22:43.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.1/manifests"},{"name":"0.8.0","sha":"01672e13958c1b0bff7e42784dbdb3de32566e98","kind":"tag","published_at":"2021-12-22T20:08:02.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.8.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.8.0/manifests"},{"name":"0.7.5","sha":"03fcf987307a9b1963075007d9fe2e8720fa7e25","kind":"tag","published_at":"2021-09-14T05:24:49.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.5","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.5/manifests"},{"name":"0.7.4","sha":"e075e99f137e6b2c71533e837b5af12cfefcf4fb","kind":"tag","published_at":"2021-09-01T07:41:56.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.4","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.4/manifests"},{"name":"0.7.3","sha":"8333dfc82a6d782d691e927876aeac6fc5186977","kind":"tag","published_at":"2021-08-28T05:23:13.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.3","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.3/manifests"},{"name":"0.7.2","sha":"05736c315e4ef2e8a90b9b912ffbf7ef0e810a93","kind":"tag","published_at":"2021-08-20T12:52:54.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.2","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.2/manifests"},{"name":"0.7.1","sha":"24011dcc5a3df7dade831618107899f9a2da9116","kind":"tag","published_at":"2021-08-20T05:17:22.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.1/manifests"},{"name":"0.7.0+scoped","sha":"322c55b2fc59d5654a59279b575869aa768b2f40","kind":"commit","published_at":"2021-08-19T19:31:26.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.0+scoped","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.0+scoped","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.0%2Bscoped","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0+scoped","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0+scoped/manifests"},{"name":"v0.7.0","sha":"c568938641cc1f121cef5b4df80fcfda1e489b6e","kind":"tag","published_at":"2021-07-27T20:51:24.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.7.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.7.0/manifests"},{"name":"0.7.0","sha":"c568938641cc1f121cef5b4df80fcfda1e489b6e","kind":"commit","published_at":"2021-07-27T20:51:18.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0/manifests"},{"name":"0.7.0+unscoped","sha":"c568938641cc1f121cef5b4df80fcfda1e489b6e","kind":"commit","published_at":"2021-07-27T20:51:18.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.7.0+unscoped","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.7.0+unscoped","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.7.0%2Bunscoped","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0+unscoped","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.7.0+unscoped/manifests"},{"name":"0.6.0","sha":"c80a161172cc4d8733583bf0cf59abfa589f6d9e","kind":"commit","published_at":"2021-04-17T16:38:12.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.6.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.6.0/manifests"},{"name":"0.5.0","sha":"f763b002fb01d3e58010b04be35a3be50f9777e8","kind":"commit","published_at":"2021-03-09T03:57:53.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.5.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.5.0/manifests"},{"name":"0.4.0","sha":"9df224b212f8c3fab60d0a688679b16166a6a862","kind":"commit","published_at":"2020-10-27T00:42:58.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.4.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.4.0/manifests"},{"name":"0.3.0","sha":"69d754508a910919ddc108b47d18327f96a079f2","kind":"commit","published_at":"2020-03-04T16:31:42.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.3.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.3.0/manifests"},{"name":"0.2.1","sha":"cb7c16a953b9acd243091306445dbc6a4ee6b813","kind":"commit","published_at":"2019-12-20T00:39:16.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.2.1","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.2.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.2.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.2.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.2.1/manifests"},{"name":"0.2.0","sha":"1bcd95e788aa233bed2fac70da9508cc407434c5","kind":"commit","published_at":"2019-12-20T00:19:17.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/0.2.0","html_url":"https://github.com/xmldom/xmldom/releases/tag/0.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@0.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/0.2.0/manifests"},{"name":"v0.1.31","sha":"91e456310880c24ae97629bd5754f96ffcb623c5","kind":"commit","published_at":"2019-12-19T22:33:43.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.31","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.31","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.31","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.31","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.31/manifests"},{"name":"v0.1.30","sha":"1710ba339a81ad18235d4a4c626c6e8805b1a17d","kind":"commit","published_at":"2019-12-19T22:29:39.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.30","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.30","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.30","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.30","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.30/manifests"},{"name":"v0.1.29","sha":"226be66a785fd6ccc11ccdd14bd32fa4c9f65780","kind":"commit","published_at":"2019-12-19T22:10:04.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.29","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.29","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.29","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.29","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.29/manifests"},{"name":"v0.1.28-not-published","sha":"0be2ae910a8a22c9ec2cac042e04de4c04317d2a","kind":"tag","published_at":"2019-12-19T22:09:51.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.28-not-published","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.28-not-published","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.28-not-published","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.28-not-published","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.28-not-published/manifests"},{"name":"v0.1.27","sha":"0ee90e6092ffeeaada9d81d000a30d7f127413b4","kind":"tag","published_at":"2019-12-19T21:39:02.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.27","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.27","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.27","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.27","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.27/manifests"},{"name":"v0.1.28-xmldom-alpha","sha":"0be2ae910a8a22c9ec2cac042e04de4c04317d2a","kind":"commit","published_at":"2017-05-09T05:05:33.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.28-xmldom-alpha","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.28-xmldom-alpha","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.28-xmldom-alpha","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.28-xmldom-alpha","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.28-xmldom-alpha/manifests"},{"name":"xmldom-aplha@v0.1.28","sha":"ffd8cac8f65a56286bc654946aaaa49620018d49","kind":"commit","published_at":"2017-05-08T02:44:57.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/xmldom-aplha@v0.1.28","html_url":"https://github.com/xmldom/xmldom/releases/tag/xmldom-aplha@v0.1.28","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@xmldom-aplha%40v0.1.28","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/xmldom-aplha@v0.1.28","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/xmldom-aplha@v0.1.28/manifests"},{"name":"v0.1.16","sha":"b47c082dad42811f63e46b76e8daf12495c7902b","kind":"commit","published_at":"2013-05-04T14:59:01.000Z","download_url":"https://codeload.github.com/xmldom/xmldom/tar.gz/v0.1.16","html_url":"https://github.com/xmldom/xmldom/releases/tag/v0.1.16","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/xmldom/xmldom@v0.1.16","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.16","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/tags/v0.1.16/manifests"}]},"repo_metadata_updated_at":"2026-10-06T20:43:03.430Z","dependent_packages_count":605,"downloads":216251979,"downloads_period":"last-month","dependent_repos_count":85555,"rankings":{"downloads":0.048024230058513445,"dependent_repos_count":0.10648017713657855,"dependent_packages_count":0.10062089251142356,"stargazers_count":3.4745831625516144,"forks_count":3.181016574930531,"docker_downloads_count":0.056292940137003214,"average":1.1611696628876107},"purl":"pkg:npm/%40xmldom/xmldom","advisories":[{"uuid":"GSA_kwCzR0hTQS1jN3E4LTNjaDgtdnFwds4ABu86","url":"https://github.com/advisories/GHSA-c7q8-3ch8-vqpv","title":"xmldom: Processing Instruction Target Injection Bypasses requireWellFormed","description":"## Summary\n\n`Document.createProcessingInstruction()` in `@xmldom/xmldom` performs no validation on the `target` parameter. The `requireWellFormed: true` serializer option validates only for `:` in the target and a case-insensitive `xml` prefix, but does not check for `\u003e` characters. A `\u003e` in the target breaks the processing instruction boundary (`\u003c?...?\u003e`), allowing injection of arbitrary content into the serialized XML output.\n\n## Details\n\n`Document.createProcessingInstruction(target, data)` at `lib/dom.js` around line 2413 accepts any string as the `target` parameter and stores it on the PI node without validation.\n\nDuring serialization, the `requireWellFormed` code path (around line 3286) performs two checks on PI targets:\n\n1. Rejects targets containing `:` (namespace prefix check)\n2. Rejects targets matching `xml` case-insensitively (reserved prefix)\n\nHowever, it does NOT validate that the target conforms to the XML Name production, and critically does NOT check for `\u003e` characters. Since processing instructions are serialized as `\u003c?target data?\u003e`, a `\u003e` in the target prematurely closes the PI, causing the remaining content to be interpreted as document content by any downstream XML parser.\n\n### Root Cause\n\n1. `createProcessingInstruction()` performs no validation on `target`\n2. The serializer's `requireWellFormed` check is incomplete -- it only checks for `:` and `xml`, missing characters that break PI syntax (`\u003e`, `?`, whitespace)\n3. The serializer emits the target verbatim: `\u003c?${target} ${data}?\u003e`\n\n## Proof of Concept\n\n```javascript\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\nconst doc = impl.createDocument(null, 'root', null);\n\n// PI target containing \u003e breaks the PI boundary\nconst pi = doc.createProcessingInstruction('a\u003e', 'data');\ndoc.documentElement.appendChild(pi);\n\nconst output = serializer.serializeToString(doc, { requireWellFormed: true });\nconsole.log(output);\n// Output: \u003croot\u003e\u003c?a\u003e data?\u003e\u003c/root\u003e\n//\n// The \u003e in the target closes the PI prematurely.\n// A downstream XML parser sees:\n//   - Processing instruction: \u003c?a?\u003e  (target \"a\", no data)\n//   - Text content: \" data?\u003e\"\n//\n// requireWellFormed: true did NOT prevent the injection.\n```\n\n### Injecting elements via PI target\n\n```javascript\nconst pi2 = doc.createProcessingInstruction(\n  'a?\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script\u003e\u003c?b',\n  ''\n);\ndoc.documentElement.appendChild(pi2);\n\nconst output2 = serializer.serializeToString(doc, { requireWellFormed: true });\nconsole.log(output2);\n// Output includes:\n//   \u003c?a?\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script\u003e\u003c?b ?\u003e\n//\n// The injected \u003cscript\u003e element is valid XHTML that a browser would execute.\n```\n\n## Impact\n\nApplications that create processing instructions with user-controlled target strings and serialize the result are vulnerable to XML injection. This enables:\n\n- **XML structure injection**: Breaking the PI boundary to inject arbitrary elements, text, or additional processing instructions into the output\n- **XSS via XHTML**: If the serialized output is served as XHTML or processed by a browser-based XML parser, injected script elements will execute\n- **XXE chain**: Injected DOCTYPE declarations or entity references could trigger XXE in downstream XML parsers that consume the output\n- **requireWellFormed bypass**: The existing well-formedness checks are incomplete and provide a false sense of security\n\n## Fix Applied\n\nUnder `requireWellFormed`, the serializer validates a processing-instruction target as an XML `NCName` (a `Name` with no colon) and rejects a case-insensitive `xml`, throwing `InvalidStateError` when the target is ill-formed — so a `\u003e`, `?`, or whitespace in the target is now refused.\\\nOn 0.9.12 this replaces an earlier check that already rejected a colon or `xml`, so the no-colon rule is preserved.\\\n0.8.15 had no processing-instruction target check at all, so the whole target validation is new there.\\\nNon-breaking and opt-in. See the [XML `Name` production](https://www.w3.org/TR/xml/#NT-Name).\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\n### Proof of Concept - fixed path\n\n```javascript\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\nconst doc = impl.createDocument(null, 'root', null);\n\n// PI target containing \u003e breaks the PI boundary\nconst pi = doc.createProcessingInstruction('a\u003e', 'data');\ndoc.documentElement.appendChild(pi);\n\n// Default path: emits the ill-formed target verbatim.\nconsole.log(serializer.serializeToString(doc));\n// Output: \u003croot\u003e\u003c?a\u003e data?\u003e\u003c/root\u003e\n\n// Opt-in path: the target check now rejects the break-out character.\ntry {\n  serializer.serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name); // InvalidStateError\n}\n```\n\n### Why the default stays verbatim\n\nW3C DOM Parsing's require-well-formed flag defaults to false, and the browser `XMLSerializer` emits the target verbatim in that default mode. Unconditionally throwing on an ill-formed PI target would diverge from that platform behavior and would be an unjustified breaking change, so the stricter validation is gated behind `{ requireWellFormed: true }`. (See the [W3C XML Name production](https://www.w3.org/TR/xml/#NT-Name) and [XML Processing Instructions](https://www.w3.org/TR/xml/#sec-pi).)\n\n### Residual limitation\n\nThe default serialization path still emits the ill-formed target verbatim -- only the opt-in `requireWellFormed` path is protected. Creation-time validation of the `target` in `createProcessingInstruction()` is breaking and is deferred to the next breaking release, tracked at [xmldom/xmldom#1073](https://github.com/xmldom/xmldom/issues/1073).","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:03:28.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-c7q8-3ch8-vqpv","https://nvd.nist.gov/vuln/detail/CVE-2026-83616","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/1cde3e31a07c41c87cfd368d6946aa477f16b4f9","https://github.com/xmldom/xmldom/commit/3b694872bcb5c7e3cbadba961a4be2488750ce5b","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-c7q8-3ch8-vqpv"],"source_kind":"github","identifiers":["GHSA-c7q8-3ch8-vqpv","CVE-2026-83616"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.521Z","epss_percentage":0.00612,"epss_percentile":0.47568,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jN3E4LTNjaDgtdnFwds4ABu86","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jN3E4LTNjaDgtdnFwds4ABu86","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jN3E4LTNjaDgtdnFwds4ABu86/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1qeGpyLTNnN2ctMzk0NM4ABu85","url":"https://github.com/advisories/GHSA-jxjr-3g7g-3944","title":"xmldom: requireWellFormed element/attribute name validation is bypassable via an embedded line terminator","description":"## Summary\n\nAn embedded line terminator bypasses the `requireWellFormed` serializer check for element and\nattribute names. The check was added to fix GHSA-w2rr-34g9-rvrj and GHSA-4w3w-2rp5-g8jm; a name whose\nfirst line is well-formed slips past it and is serialized verbatim, so the characters after the line\nterminator break out of the start/end tag or attribute. Callers who enabled `requireWellFormed`\nspecifically to neutralize those name-injection issues remain exposed.\n\n## Details\n\nxmldom builds every grammar production through a shared regexp builder that compiles with the `m`\nflag. The anchored full-string matcher used for element and attribute names, `QName_exact =\nreg('^', QName, '$')`, therefore inherits `m`. When it is applied as `QName_exact.test(name)` against\nan already-assembled node name, the `m` flag makes `$` match at an interior line terminator, so the\nmatcher accepts any value in which **at least one line** is a valid `QName`; the other lines are never\nconstrained. A payload whose first line is a valid `QName`, followed by a line terminator and breakout\nmarkup, is what yields a working injection.\n\nThe serializer emits the accepted name verbatim into element start/end tags and attribute names, so\nthe bytes after the line terminator break out of the intended syntactic position. The check is\nreached whenever a caller serializes, with `requireWellFormed: true`, a node whose name was set\nthrough programmatic DOM construction (`createElement`, `createElementNS`, `createAttribute`,\n`createAttributeNS`) with attacker-influenced input.\n\n### Root Cause\n\n1. A shared regexp builder compiles anchored productions with the `m` flag.\n2. `^…$` under `m` are line anchors, not string anchors.\n3. A full-string validator built on such a production (`.test()`) accepts any string with one\n   conforming line, so a line terminator followed by breakout markup passes.\n\nThe triggering line terminators are the ECMAScript `LineTerminator` set: U+000A, U+000D, U+2028, U+2029.\n\n## Proof of Concept\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\n// Element name carrying an embedded line terminator + breakout markup:\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\nconst el = doc.createElement('a\\n\u003e\u003cscript\u003ealert(1)\u003c/script');\ndoc.documentElement.appendChild(el);\n\n// Caller opted into well-formed serialization, expecting invalid names to be rejected:\nconsole.log(new XMLSerializer().serializeToString(doc, { requireWellFormed: true }));\n// Observed on the affected version: NO throw; the output contains the injected `\u003e\u003cscript\u003e…`\n// breakout, because the name's first line (\"a\") satisfies the m-anchored QName check.\n// Expected: InvalidStateError (the name is not a valid XML QName).\n\n// Control — a single-line invalid name IS correctly rejected, proving the check is active and\n// that only the line terminator defeats it:\nconst ctrl = new DOMImplementation().createDocument(null, 'root', null);\nctrl.documentElement.appendChild(ctrl.createElement('a b'));\nnew XMLSerializer().serializeToString(ctrl, { requireWellFormed: true });\n// =\u003e throws InvalidStateError: The element name \"a b\" is not a valid XML QName\n```\n\n## Impact\n\n- **Bypass of a previously shipped security mitigation.** Applications that adopted\n  `requireWellFormed: true` specifically to neutralize GHSA-w2rr-34g9-rvrj / GHSA-4w3w-2rp5-g8jm\n  remain exposed to element/attribute name injection.\n- **XML / markup structure injection**, and, where the serialized output is placed into an HTML\n  context, downstream XSS.\n\n## Fix Applied\n\nThe anchored XML `Name`/`QName` validators used by the `requireWellFormed` serializer no\nlonger treat interior line terminators as satisfying the anchors, so a name is validated against the\nwhole string. A name containing a line terminator is rejected with `InvalidStateError`, closing the\nbypass for element and attribute names. The default serialization path is unchanged.\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\n### Proof of Concept - fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\nconst el = doc.createElement('a\\n\u003e\u003cscript\u003ealert(1)\u003c/script');\ndoc.documentElement.appendChild(el);\n\n// Default path (require-well-formed off) — unchanged, still emits the name verbatim,\n// so the `\u003e\u003cscript\u003e…` bytes break out of the start tag:\nnew XMLSerializer().serializeToString(doc);\n\n// Opted-in path — now rejected:\nnew XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n// throws InvalidStateError: The element name \"a\\n\u003e\u003cscript\u003ealert(1)\u003c/script\" is not a valid XML QName\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing require-well-formed flag defaults to false, and browser `XMLSerializer` emits\nnames verbatim when it is unset. Throwing unconditionally would be an unjustified breaking change, so\nthe check stays gated on the caller opting in with `{ requireWellFormed: true }`.\n\n### Residual limitation\n\nThe default serialization path (no `requireWellFormed`) still emits names verbatim by design (above).\nNames introduced through `createElement` / `setAttribute` are never validated at creation — those APIs\nstore the name unchecked by design — so the opt-in serializer check remains the only guard on that\npath.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:03:17.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-jxjr-3g7g-3944","https://nvd.nist.gov/vuln/detail/CVE-2026-83617","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/commit/7b2ec67e1750daadd0bb06c92e875e726544a362","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-jxjr-3g7g-3944"],"source_kind":"github","identifiers":["GHSA-jxjr-3g7g-3944","CVE-2026-83617"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.521Z","epss_percentage":0.0057,"epss_percentile":0.44767,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qeGpyLTNnN2ctMzk0NM4ABu85","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qeGpyLTNnN2ctMzk0NM4ABu85","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"= 0.9.11"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qeGpyLTNnN2ctMzk0NM4ABu85/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0yN3A4LTIzNTctNXFxds4ABu84","url":"https://github.com/advisories/GHSA-27p8-2357-5qqv","title":"xmldom: DocType `name` Injection Bypasses requireWellFormed","description":"## Summary\n\nThe `@xmldom/xmldom` serializer emits `DocumentType.name` verbatim into the\n`\u003c!DOCTYPE …\u003e` declaration with no well-formedness guard. GHSA-f6ww-3ggp-fr8h\n(CVE-2026-41674) hardened the serializer's `requireWellFormed` path for a\nDocumentType's sibling fields — `publicId`, `systemId`, and `internalSubset` —\nbut it did **not** add any check for `name`. A `\u003e` (or whitespace) in the name\nterminates the doctype declaration early, letting the remaining characters\nbecome sibling markup in the serialized output.\n\nBecause `requireWellFormed: true` — the recommended mitigation for the prior\nxmldom injection CVEs — performs no validation on the DocType `name`, this is a\nbypass of that control, in the same family as the open element-name\n(GHSA-w2rr-34g9-rvrj) and attribute-name (GHSA-4w3w-2rp5-g8jm) name-injection advisories.\n\n## Details\n\nThe serializer's `DOCUMENT_TYPE_NODE` case runs the `requireWellFormed` block\nonly against `publicId`, `systemId`, and `internalSubset`, then pushes\n`n.name` directly into the buffer between the `\u003c!DOCTYPE ` prefix and the\nclosing `\u003e`:\n\n- 0.9.x (v0.9.10, `bb7a085`):\n  [serializer DocType case, `lib/dom.js#L3256-L3283`](https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L3256-L3283)\n  — the `requireWellFormed` block ([#L3259-L3269](https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L3259-L3269))\n  validates `publicId`/`systemId`/`internalSubset` but not `name`, which is\n  emitted verbatim at [#L3270](https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L3270).\n- 0.8.x (v0.8.13, `e5c1480`):\n  [serializer DocType case, `lib/dom.js#L1914-L1946`](https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L1914-L1946)\n  — same structure; `name` is emitted verbatim at [#L1928](https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L1928).\n- unscoped `xmldom` (v0.6.0, `c80a161`):\n  [`lib/dom.js#L1105`](https://github.com/xmldom/xmldom/blob/c80a161172cc4d8733583bf0cf59abfa589f6d9e/lib/dom.js#L1105)\n  emits `node.name` verbatim; this line predates `requireWellFormed`, so there\n  is no well-formedness path at all.\n\n### Enabling write paths\n\n`DocumentType.name` is a plain, writable own-property, so the enabling vector\ndiffers by line:\n\n- **0.9.x** — `createDocumentType()` validates the name via\n  `validateQualifiedName` ([`lib/dom.js#L925-L936`](https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L925-L936),\n  validation at [#L926](https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L926)),\n  so the deliverable vector is a **direct property write**\n  (`dt.name = 'html\u003e\u003cscript\u003e…'`) to the unguarded own-property.\n- **0.8.x** — `createDocumentType()` does **not** validate the name\n  ([`lib/dom.js#L456-L464`](https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L456-L464)),\n  so the malicious name is reachable directly through `createDocumentType()` as\n  well as via direct property write.\n- **unscoped `xmldom` (\u003c= 0.6.0)** — `createDocumentType()` does not validate\n  the name ([`lib/dom.js#L286`](https://github.com/xmldom/xmldom/blob/c80a161172cc4d8733583bf0cf59abfa589f6d9e/lib/dom.js#L286)),\n  same as 0.8.x.\n\nThis is the same structural root cause the sibling name-injection advisories\nshare: the serializer's `requireWellFormed` path validates content delimiters\nbut no name field, and every name-like field is a plain writable property, so\nmutation / direct property-write bypasses any creation-time check.\n\n### Root Cause\n\n1. The serializer's `requireWellFormed` DocType block checks `publicId`,\n   `systemId`, and `internalSubset` (the fields hardened by GHSA-f6ww-3ggp-fr8h)\n   but has no check for `name`.\n2. `DocumentType.name` is a plain writable own-property; on 0.8.x and the\n   unscoped package `createDocumentType()` does not validate it either.\n3. The serializer emits `name` directly between the doctype delimiters:\n   `\u003c!DOCTYPE ${name}…\u003e`.\n\n## Proof of Concept\n\nRun against `@xmldom/xmldom` v0.9.10 (commit `bb7a085`):\n\n```javascript\nconst { DOMImplementation, XMLSerializer, DOMParser } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\n\n// 0.9.x createDocumentType validates the name, so overwrite it via direct property write\nconst dt = impl.createDocumentType('html', '', '');\ndt.name = 'html\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script';\nconst doc = impl.createDocument(null, 'r', dt);\n\nconst output = serializer.serializeToString(doc, { requireWellFormed: true });\nconsole.log(output);\n// Output: \u003c!DOCTYPE html\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script\u003e\u003cr/\u003e\n//\n// requireWellFormed: true did NOT prevent the injection (no exception thrown).\n// The injected \u003cscript\u003e is well-formed XHTML that a browser would execute.\n```\n\nConfirmed runtime behavior:\n\n- **0.9.x** — `createDocumentType()` rejects the malicious name at creation\n  (`InvalidCharacterError`); a direct write to `dt.name` bypasses that, and\n  `serializeToString(…, { requireWellFormed: true })` emits the breakout with no\n  exception.\n- **Re-parse confirmation** — re-parsing the output shows the injected\n  `\u003cscript\u003e` is a real second top-level element originating entirely from the\n  DocType name: the parser rejects it with\n  `HierarchyRequestError: Only one element can be added and only after doctype`.\n  A comment-injection variant (`dt.name = 'html\u003e\u003c!--INJECTED--'`, output\n  `\u003c!DOCTYPE html\u003e\u003c!--INJECTED--\u003e\u003cr/\u003e`) re-parses cleanly and the injected\n  comment node is enumerable, confirming the injected node is structurally live.\n- **0.8.x** (v0.8.13, `e5c1480`) — `createDocumentType('html\u003e\u003cscript\u003e…', '', '')`\n  accepts the malicious name directly (no creation-time validation), and\n  `serializeToString(doc, null, null, { requireWellFormed: true })` produces\n  `\u003c!DOCTYPE html\u003e\u003cscript\u003ealert(1)\u003c/script\u003e\u003cr/\u003e` with no exception.\n\nA browser reproduction does not apply: browsers keep `DocumentType.name`\n`readonly`, so the direct-write vector cannot be reproduced in a browser DOM.\nThe injection is specific to xmldom exposing `name` as writable and serializing\nit without a guard.\n\n## Impact\n\nApplications that build a `DocumentType` node with an attacker-influenced\n`name` — via direct property write on any affected line, or via\n`createDocumentType()` on 0.8.x and the unscoped package — and serialize the\ndocument are vulnerable to XML/markup injection:\n\n- **XML structure injection** — breaking out of the `\u003c!DOCTYPE …\u003e` declaration\n  to inject arbitrary sibling elements, comments, or additional markup into the\n  output.\n- **XSS via XHTML** — if the serialized output is served as XHTML or processed\n  by a browser-based XML parser, an injected `\u003cscript\u003e` element (in the XHTML\n  namespace) executes.\n- **requireWellFormed bypass** — applications that adopted\n  `requireWellFormed: true` as a mitigation for the prior injection CVEs\n  (including the sibling DocType fields fixed by GHSA-f6ww-3ggp-fr8h) remain\n  vulnerable through the DocType `name`.\n\n## Fix Applied\n\nUnder `requireWellFormed`, the serializer validates the DocType `name` as a well-formed XML\n`Name` and throws `InvalidStateError` when it is not — matching the sibling\n`publicId`/`systemId`/`internalSubset` checks. Non-breaking and opt-in; ships on both maintained versions. No\ncreation-time change is made: 0.9.x already validates the name at `createDocumentType`, and the\n0.8.x/unscoped creation gap cannot be closed without a breaking change, so it is left\nunfixed. See the [XML `Name` production](https://www.w3.org/TR/xml/#NT-Name).\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\n### Proof of Concept - fixed path\n\n```javascript\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\n\nconst dt = impl.createDocumentType('html', '', '');\ndt.name = 'html\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script';\nconst doc = impl.createDocument(null, 'r', dt);\n\n// Default path: the ill-formed name is still emitted verbatim (injection present).\nconsole.log(serializer.serializeToString(doc));\n// \u003c!DOCTYPE html\u003e\u003cscript xmlns=\"http://www.w3.org/1999/xhtml\"\u003ealert(1)\u003c/script\u003e\u003cr/\u003e\n\n// Opt-in path: serialization throws instead of emitting the breakout.\nserializer.serializeToString(doc, { requireWellFormed: true });\n// throws InvalidStateError\n```\n\n### Why the default stays verbatim\n\nW3C DOM Parsing's require-well-formed flag defaults to false, and the browser\n`XMLSerializer` emits the name verbatim in that default mode. Unconditionally\nthrowing would be an unjustified breaking change against that specified default,\nso the guard is opt-in behind `{ requireWellFormed: true }`.\n\n### Residual limitation\n\nThe default serialization path still emits the ill-formed DocType `name`\nverbatim; protection applies only when `requireWellFormed: true` is passed. No\ncreation-time validation is added for the DocType `name`: 0.9.x already validates\nat `createDocumentType`, and the 0.8.x/unscoped creation gap is left unfixed — it\ncannot be closed without a breaking change.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:02:51.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-27p8-2357-5qqv","https://nvd.nist.gov/vuln/detail/CVE-2026-83608","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/57aec90ac57b4408ae7c5d1746bf2a693b5ed90e","https://github.com/xmldom/xmldom/commit/85f12eb4d14b44de33216cfb72b50af4d24e9fdd","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-27p8-2357-5qqv"],"source_kind":"github","identifiers":["GHSA-27p8-2357-5qqv","CVE-2026-83608"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.522Z","epss_percentage":0.00612,"epss_percentile":0.47569,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0yN3A4LTIzNTctNXFxds4ABu84","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0yN3A4LTIzNTctNXFxds4ABu84","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0yN3A4LTIzNTctNXFxds4ABu84/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zcHgzLTU0Y3gtcm13Oc4ABu83","url":"https://github.com/advisories/GHSA-3px3-54cx-rmw9","title":"xmldom: Creation-time XML Name/QName validation is bypassable via an embedded line terminator, allowing injection on the default serialization path","description":"## Summary\n\nAn embedded line terminator bypasses xmldom's always-on, WHATWG-mandated creation-time name\nvalidation. `createElementNS`, `createAttributeNS`, `createDocumentType`, and `createAttribute` should\nreject a malformed qualified name with `InvalidCharacterError`, but a name whose first line is\nwell-formed slips through and enters the DOM. On serialization it is emitted verbatim, so the\ncharacters after the line terminator inject markup into the output. The injection reaches the default\nserialization path, and enabling `requireWellFormed` does not prevent it.\n\n## Details\n\n`createElementNS`, `createAttributeNS`, and `createDocumentType` route through `validateQualifiedName`,\nand `createAttribute` performs the analogous check; each validates the name with\n`g.QName_exact.test(name)`. `QName_exact = reg('^', QName, '$')` inherits the `m` flag from xmldom's\nshared regexp builder, so the matcher accepts any name whose first line is a valid `QName` and leaves\nthe remaining lines unconstrained (see Root Cause).\n\n### Root Cause\n\n1. A shared regexp builder compiles anchored productions with the `m` flag.\n2. `^…$` under `m` are line anchors, not string anchors.\n3. `validateQualifiedName` / `createAttribute` validate with `.test()` against such a production, so a\n   line terminator followed by breakout markup passes and the malformed name is stored.\n\nThe triggering line terminators are the ECMAScript `LineTerminator` set: U+000A, U+000D, U+2028, U+2029.\n\n## Proof of Concept\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\nconst impl = new DOMImplementation();\n\nconst doc = impl.createDocument('urn:x', 'root', null);\nconst el = doc.createElementNS('urn:x', 'a\\n\u003e\u003cscript\u003ex\u003c/script');  // ACCEPTED (no throw)\ndoc.documentElement.appendChild(el);\n\n// DEFAULT serialization — requireWellFormed NOT set:\nconsole.log(new XMLSerializer().serializeToString(doc));\n// Observed: \u003croot xmlns=\"urn:x\"\u003e\u003ca\n// \u003e\u003cscript\u003ex\u003c/script/\u003e\u003c/root\u003e          \u003c-- injected element on the default path\n// Control: createElementNS('urn:x', 'bad\u003ename') throws InvalidCharacterError, confirming the check is\n// active and specifically bypassed by the line terminator.\n```\n\n## Impact\n\n- **Bypass of the always-on WHATWG creation-time name validation** (`InvalidCharacterError`): a\n  malformed name the standard requires be rejected at creation is instead admitted to the DOM.\n- **Markup / structure injection.** An application relying on the `create*` APIs to reject malformed\n  names (the standard behavior) as a trust boundary is exposed; where the serialized output reaches an\n  HTML context, downstream XSS.\n- **No serializer option mitigates it.** The admitted name is emitted verbatim under *both* the default\n  path and `requireWellFormed: true` — the strict serializer shares the same `m`-flagged blind spot\n  (the subject of the sibling serializer advisories) — so the bypassed creation-time check was the only\n  layer that could have stopped it. Demonstrated for all four `create*` sites in\n  `poc_creation_strict_serialization_bypass.cjs`.\n\n## Fix Applied\n\n`createElementNS`, `createAttributeNS`, `createDocumentType`, and `createAttribute` now reject a name\ncontaining a line terminator with `InvalidCharacterError` — the same result they already give for\nother malformed names — because name validation now applies to the whole string. The\n`requireWellFormed` serializer's name checks are corrected by the same change. The fix is\nnon-breaking: such a name was already invalid, and no previously-accepted well-formed name is affected.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:02:33.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-3px3-54cx-rmw9","https://nvd.nist.gov/vuln/detail/CVE-2026-83609","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/commit/7b2ec67e1750daadd0bb06c92e875e726544a362","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-3px3-54cx-rmw9"],"source_kind":"github","identifiers":["GHSA-3px3-54cx-rmw9","CVE-2026-83609"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.523Z","epss_percentage":0.00543,"epss_percentile":0.43531,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcHgzLTU0Y3gtcm13Oc4ABu83","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zcHgzLTU0Y3gtcm13Oc4ABu83","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcHgzLTU0Y3gtcm13Oc4ABu83/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS12cjM0LWhwOTYtNzZwcM4ABu82","url":"https://github.com/advisories/GHSA-vr34-hp96-76pp","title":"xmldom: requireWellFormed DocType publicId/systemId validation is bypassable via an embedded line terminator","description":"## Summary\n\nAn embedded line terminator bypasses the `requireWellFormed` serializer check for a `DocumentType`'s\npublicId and systemId. The check was added to fix GHSA-f6ww-3ggp-fr8h; an id whose first line is a\nvalid literal slips past it and is emitted verbatim into the `\u003c!DOCTYPE …\u003e` declaration, so the markup\nafter the line terminator breaks out into the surrounding document. Callers who enabled\n`requireWellFormed` to neutralize DocumentType injection remain exposed.\n\n## Details\n\n`publicId` and `systemId` are stored as raw values **including their surrounding quotes**, and the\n`PubidLiteral`/`SystemLiteral` productions include those quotes. The serializer validates them with\n`g.PubidLiteral_match.test(publicId)` and `g.SystemLiteral_match.test(systemId)`, where both matchers\nare `reg('^', …, '$')` and inherit the `m` flag from xmldom's shared regexp builder. Under `m`, `$`\nmatches at an interior line terminator, so a value such as `\"valid pubid\"\\n\"\u003e\u003c!ENTITY …\u003e` satisfies\nthe matcher on its first line (`\"valid pubid\"` is a complete `PubidLiteral`) and the whole value —\nincluding the post-newline breakout — is emitted after `PUBLIC`/`SYSTEM`.\n\n### Root Cause\n\n1. A shared regexp builder compiles anchored productions with the `m` flag.\n2. `^…$` under `m` are line anchors, not string anchors.\n3. A full-string validator built on such a production (`.test()`) accepts any string with one\n   conforming line, so a complete, valid literal on the first line passes even though a line terminator\n   and breakout markup follow. `PubidChar` excluding `\u003c`/`\u003e` does not prevent it — the breakout is\n   appended *after* the literal, not embedded inside it.\n\nThe triggering line terminators are the ECMAScript `LineTerminator` set: U+000A, U+000D, U+2028, U+2029.\n\n## Affected Versions\n\nOnly `@xmldom/xmldom` 0.9.x is affected. The vulnerable matchers are built by `lib/grammar.js`'s\n`m`-flagged `reg()` builder, and the DocType `publicId`/`systemId` `requireWellFormed` check that\nconsumes them was introduced in 0.9.10 (the GHSA-f6ww-3ggp-fr8h fix); 0.9.10 and 0.9.11 carry it.\n`0.8.x` performs the same `requireWellFormed` check with inline, non-`m` regular expressions and is not\naffected. The unscoped `xmldom` package has no `grammar.js` and no `requireWellFormed` serializer, so\nthere is no check to bypass.\n\n## Proof of Concept\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\nconst impl = new DOMImplementation();\n\n// publicId: complete literal on line 1, then newline + breakout\nconst dt = impl.createDocumentType('html', '\"valid pubid\"\\n\"\u003e\u003c!ENTITY xxe SYSTEM \"file:///etc/passwd\"\u003e', '');\nconst doc = impl.createDocument(null, 'root', dt);\nconsole.log(new XMLSerializer().serializeToString(doc, { requireWellFormed: true }));\n// Observed (no throw):\n//   \u003c!DOCTYPE html PUBLIC \"valid pubid\"\n//   \"\u003e\u003c!ENTITY xxe SYSTEM \"file:///etc/passwd\"\u003e\u003e\u003croot/\u003e\n// Expected: InvalidStateError (publicId is not a valid PubidLiteral).\n// Control: a single-line invalid publicId (\"no-surrounding-quotes\u003c\u003e\") DOES throw InvalidStateError,\n// confirming the check is active and specifically bypassed by the line terminator.\n```\n\n## Impact\n\n- **Bypass of the GHSA-f6ww-3ggp-fr8h mitigation.** Applications that adopted `requireWellFormed:\n  true` to neutralize DocumentType injection remain exposed.\n- **XML structure injection into the DOCTYPE**, including injected markup / entity declarations after\n  the public or system identifier.\n\n## Fix Applied\n\nThe anchored `PubidLiteral`/`SystemLiteral` validators used by the `requireWellFormed`\nserializer no longer treat an interior line terminator as satisfying the `$` anchor, so a `publicId`\nor `systemId` containing any ECMAScript `LineTerminator` (U+000A, U+000D, U+2028, U+2029) is rejected\nwith `InvalidStateError`. Valid single-line identifiers serialize unchanged, and the default\nserialization path is unaffected.\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain vulnerable\n\u003e unless `{ requireWellFormed: true }` is explicitly passed. Applications that serialize untrusted DOM\n\u003e content should audit all `serializeToString()` call sites and add it.\n\n### Proof of Concept - fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\nconst impl = new DOMImplementation();\nconst dt = impl.createDocumentType('html', '\"valid pubid\"\\n\"\u003e\u003c!ENTITY xxe SYSTEM \"file:///etc/passwd\"\u003e', '');\nconst doc = impl.createDocument(null, 'root', dt);\n\n// Default path (requireWellFormed off) — unchanged, still emits verbatim:\nconsole.log(new XMLSerializer().serializeToString(doc));\n//   \u003c!DOCTYPE html PUBLIC \"valid pubid\"\n//   \"\u003e\u003c!ENTITY xxe SYSTEM \"file:///etc/passwd\"\u003e\u003e\u003croot/\u003e\n\n// Opt-in path — now throws instead of emitting the breakout:\nnew XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n//   InvalidStateError: DocumentType publicId is not a valid PubidLiteral\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing \"require well-formed\" flag defaults to false, and a browser `XMLSerializer` emits\nthe DOCTYPE verbatim. Unconditionally throwing on a malformed `publicId`/`systemId` would be an\nunjustified breaking change to the default path, so the fix tightens only the opt-in\n`requireWellFormed` validator, matching browser and spec defaults.\n\n### Residual limitation\n\nThe guarantee holds only for callers that pass `{ requireWellFormed: true }`; the default\nserialization path still emits `publicId`/`systemId` verbatim. `publicId` and `systemId` are not\nvalidated at creation (`createDocumentType`) or on direct property assignment\n(`documentType.publicId = …`) — the WHATWG DOM specification places no well-formedness constraint on\nthese fields at creation time, so the serializer is the spec-aligned enforcement point.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:02:25.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-vr34-hp96-76pp","https://nvd.nist.gov/vuln/detail/CVE-2026-83618","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/commit/7b2ec67e1750daadd0bb06c92e875e726544a362","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-vr34-hp96-76pp"],"source_kind":"github","identifiers":["GHSA-vr34-hp96-76pp","CVE-2026-83618"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.524Z","epss_percentage":0.0057,"epss_percentile":0.44767,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12cjM0LWhwOTYtNzZwcM4ABu82","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS12cjM0LWhwOTYtNzZwcM4ABu82","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.10, \u003c= 0.9.11"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12cjM0LWhwOTYtNzZwcM4ABu82/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02aDhyLXhyNDItZ3A1Oc4ABu81","url":"https://github.com/advisories/GHSA-6h8r-xr42-gp59","title":"xmldom: Parser silently accepts a not-well-formed end tag whose name is followed by a line break and trailing content","description":"## Summary\n\nxmldom's parser silently accepts a **not-well-formed end tag** whose valid name is followed by\ntrailing content — e.g. `\u003c/a⏎junk\u003e`. The element is closed, the trailing content is discarded, and no\nerror is reported, even though the XML end-tag production allows only optional whitespace after the\nname and both Chromium and Firefox reject such input as `application/xml`. An application that relies\non xmldom to reject not-well-formed input therefore receives a false \"valid\" result for a document the\nspecification and browsers consider malformed.\n\n## Details\n\nAcross every affected version, an end tag whose valid `Name` is followed by trailing content before\n`\u003e` is silently accepted: the element is closed, the residue is dropped, and no error is reported. How\nmuch leaks differs by line (see Affected Versions), but the observable weakness is the same.\n\nOn the current (`0.9.x`) line, the parser validates the end-tag name against the XML `ETag` production\nwith an anchored regular expression (`^ QName S? $`). That expression is compiled with the `m`\n(multiline) flag by a shared builder, so `$` matches at an interior line terminator: a valid name on\nthe first line satisfies the anchored production and any content after the line break escapes the\ncheck. On 0.9.x the whitespace-separated variant (`\u003c/a junk\u003e`) is already rejected; only the\nline-terminator variant leaks. Older lines have no anchored end-tag validator at all, so they accept\nboth the line-terminator and the whitespace variant.\n\nThis is **not** content injection — the trailing content is dropped, and the resulting DOM is a normal\nsingle-root document (`\u003ca/\u003e`). The security-relevant property is the silent acceptance of\nnot-well-formed input: xmldom's parse result disagrees with the specification and with browser XML\nparsers, so any control that treats \"xmldom parsed it without error\" as \"well-formed\" is bypassed.\n\n### Root Cause\n\nOn the `0.9.x` line, where the line-terminator variant specifically leaks:\n\n1. A shared regexp builder compiles anchored productions with the `m` flag.\n2. `^…$` under `m` are line anchors, not string anchors.\n3. The anchored end-tag production `^ QName S? $` is therefore satisfied by the first line alone, so\n   trailing content after a line terminator is neither matched nor rejected — the malformed end tag is\n   accepted and the residue silently discarded.\n\nThe triggering line terminators are the ECMAScript `LineTerminator` set: U+000A, U+000D, U+2028, U+2029.\nU+2028 and U+2029 are not XML whitespace, so they are non-conforming trailing content that nonetheless\nleaks because the JavaScript `$` anchor treats them as line boundaries under `m`.\n\n## Affected Versions\n\nBoth maintained versions are affected and fixed:\n\n- **`0.9.x`** (`\u003e= 0.9.0, \u003c= 0.9.11`) → **`0.9.12`**: the anchored end-tag validator's `m` flag leaks\n  the line-terminator variant. The whitespace variant (`\u003c/a junk\u003e`) is already rejected on this line.\n- **`0.8.x`** (`\u003e= 0.8.0, \u003c= 0.8.14`) → **`0.8.15`**: no anchored end-tag validator at all — both the\n  line-terminator and the whitespace variant are silently accepted; the fix adds a residue check.\n\n`release-0.7.x` (`\u003c= 0.7.13`) and the unscoped `xmldom` package (range `*`, last release 0.6.0) are\n**affected but will not be patched** — they are end-of-life / unmaintained. They share the older-line\nbehavior (both variants silently accepted, residue dropped).\n\n## Proof of Concept\n\n```js\nconst { DOMParser, XMLSerializer } = require('@xmldom/xmldom');\nconst doc = new DOMParser().parseFromString('\u003ca\u003e\u003c/a\\njunk\u003e', 'text/xml'); // no error\nconsole.log(new XMLSerializer().serializeToString(doc));\n// Observed: \u003ca/\u003e   — the malformed end tag is accepted, \"junk\" silently discarded, no error reported.\n// Expected (per XML spec / Chromium / Firefox): a parse error — the input is not well-formed.\n```\n\n## Impact\n\n- **Silent acceptance of not-well-formed XML**: a document the specification and browser XML parsers\n  reject is parsed without error.\n- **Bypass of a well-formedness / parse-before-trust gate**: an application relying on xmldom to\n  reject malformed input treats such a document as valid. Note this is an input-validation /\n  parser-differential issue, not content injection — the trailing content is discarded.\n\n## Fix Applied\n\nThe parser now reports a not-well-formed end tag whose valid name is followed by trailing content, on both `0.9.12` and `0.8.15` — previously it was accepted silently — and parsing recovers to the byte-identical DOM as before.\\\nOn `0.9.12` the anchored end-tag validator is corrected so a line break followed by trailing content no longer satisfies it, reported as a recoverable `error` when parsing as XML and a `warning` when parsing as HTML.\\\nOn `0.8.15`, which previously performed no end-tag residue validation, an equivalent residue check is added, reported as a recoverable `error` in both XML and HTML.\\\nWell-formed documents are unaffected.\n\nBecause the report is recoverable, the fix is non-breaking: no previously-parsed document begins to\nthrow and no serialized output changes. Consumers that want strict rejection can escalate the reported\n`error` to a fatal one via the parser's error handler (`onError` in `0.9.12`, `errorHandler` in\n`0.8.15`). The two versions also differ in the whitespace-separated variant (`\u003c/a junk\u003e`): `0.9.12`\nalready rejected it with a fatal error in XML and continues to, while `0.8.15` — which validated\nneither variant — now emits the same recoverable report for both the whitespace and line-break\nvariants.\n\n### Residual limitation\n\nBy default the parser still **recovers** (it does not reject the document); the reported condition is a\nrecoverable `error`/`warning`, not a fatal error, to avoid changing the parsed output in a patch\nrelease. Converting this and the other not-well-formed-acceptance cases to a consistent `fatalError` —\nincluding the broader end-tag leniency on the older versions — is deferred to the next breaking release,\ntracked at [xmldom/xmldom#1074](https://github.com/xmldom/xmldom/issues/1074).","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-08T21:02:13.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-6h8r-xr42-gp59","https://nvd.nist.gov/vuln/detail/CVE-2026-83611","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/4430189660b0d380ee9c9ee7550a1358688e8828","https://github.com/xmldom/xmldom/commit/7b2ec67e1750daadd0bb06c92e875e726544a362","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-6h8r-xr42-gp59"],"source_kind":"github","identifiers":["GHSA-6h8r-xr42-gp59","CVE-2026-83611"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.524Z","epss_percentage":0.00619,"epss_percentile":0.47554,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aDhyLXhyNDItZ3A1Oc4ABu81","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02aDhyLXhyNDItZ3A1Oc4ABu81","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aDhyLXhyNDItZ3A1Oc4ABu81/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS04MzQ0LTNqbXEtNTlyNs4ABu80","url":"https://github.com/advisories/GHSA-8344-3jmq-59r6","title":"xmldom: Quadratic-time attribute deduplication","description":"## Summary\n\nxmldom builds the attribute collection of every parsed element by inserting attributes one at a\ntime into a DOM `NamedNodeMap`. Each insertion first performs a **linear scan of all\nalready-inserted attributes** to enforce the DOM uniqueness rule (no two attributes with the same\nqualified name / namespace+local-name). Parsing an element that carries `M` distinct attributes\ntherefore costs `1 + 2 + … + M = O(M²)` comparisons.\n\nBecause the trigger is simply \"one element with many attributes\", the attack payload is a\n**fully well-formed XML document**. No malformed markup, no error recovery, and no non-default\nparser options are involved — parsing completes silently with zero `warning`/`error`/`fatalError`\nevents. An attacker who can submit a modest, highly compressible document (a single element with\ntens of thousands of attributes, ~340 KB uncompressed) can consume seconds of single-threaded CPU\nper request, enabling an unauthenticated denial of service.\n\nThis is distinct from the known quadratic-**memory** namespace-map issue: it burns **CPU** and it\ndoes not require any namespace declarations or nesting.\n\n## Details\n\nThe DOM content handler adds each attribute of a starting element by calling\n`el.setAttributeNode(attr)` in a loop:\n\n```js\n// DOMHandler.startElement\nfor (var i = 0; i \u003c len; i++) {\n\tvar namespaceURI = attrs.getURI(i);\n\tvar value = attrs.getValue(i);\n\tvar qName = attrs.getQName(i);\n\tvar attr = doc.createAttributeNS(namespaceURI, qName);\n\tattr.value = attr.nodeValue = value;\n\tel.setAttributeNode(attr);          // O(existing attrs) each — see below\n}\n```\n\nhttps://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom-parser.js#L370-L387\n\n`setAttributeNode` delegates to `NamedNodeMap.setNamedItem`, which calls `getNamedItemNS` to look\nfor an existing attribute with the same namespace URI and local name before appending:\n\n```js\nsetNamedItem: function (attr) {\n\tvar el = attr.ownerElement;\n\tif (el \u0026\u0026 el !== this._ownerElement) {\n\t\tthrow new DOMException(DOMException.INUSE_ATTRIBUTE_ERR);\n\t}\n\tvar oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);  // linear scan\n\tif (oldAttr === attr) {\n\t\treturn attr;\n\t}\n\t_addNamedNode(this._ownerElement, this, attr, oldAttr);\n\treturn oldAttr;\n},\n```\n\nhttps://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L612-L623\n\n`getNamedItemNS` walks the whole list on every call:\n\n```js\ngetNamedItemNS: function (namespaceURI, localName) {\n\tif (!namespaceURI) {\n\t\tnamespaceURI = null;\n\t}\n\tvar i = 0;\n\twhile (i \u003c this.length) {\n\t\tvar node = this[i];\n\t\tif (node.localName === localName \u0026\u0026 node.namespaceURI === namespaceURI) {\n\t\t\treturn node;\n\t\t}\n\t\ti++;\n\t}\n\treturn null;\n},\n```\n\nhttps://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L702-L715\n\nFor the i-th attribute the scan visits `i-1` entries, so inserting `M` distinct attributes performs\n`Θ(M²)` comparisons. There is no hash index or set keyed by name; the map is a plain\narray-backed structure.\n\nThe same structure exists on 0.8.x. There `setNamedItem` dedups via\n`getNamedItem(attr.nodeName)` instead of `getNamedItemNS`, but that method is likewise a full linear\nscan, so the complexity is identical:\n\n- `startElement` loop / `setAttributeNode`:\n  https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom-parser.js#L159-L176\n- `setNamedItem` → linear `getNamedItem`:\n  https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L286-L308\n\nThe linear-scan `NamedNodeMap` predates the `@xmldom/xmldom` fork and is present unchanged in the\nunscoped `xmldom` package back to its earliest published release. In `xmldom@0.1.0`, parsing already\ninserts each attribute one at a time (`DOMHandler.startElement` loops calling\n`setAttributeNS` → `setAttributeNode` → `NamedNodeMap.setNamedItem`), and `setNamedItem` dedups by\ncalling `getNamedItemNS`, which is a full linear `while (i--)` scan of the already-inserted\nattributes — the identical `O(M²)` structure. The whole unscoped line (`0.1.0` … `0.6.0`) is\ntherefore affected; the earliest published tag (`0.1.0`) was verified to contain the per-insert\nlinear dedup scan.\n\n## Proof of Concept\n\nA single well-formed element with `M` distinct attributes. No malformed markup and no options:\n\n```js\n'use strict';\nvar DOMParser = require('@xmldom/xmldom').DOMParser;\n\nfunction buildDoc(m) {\n\tvar parts = new Array(m);\n\tfor (var i = 0; i \u003c m; i++) parts[i] = 'a' + i + '=\"x\"';\n\treturn '\u003cr ' + parts.join(' ') + '/\u003e';   // \u003cr a0=\"x\" a1=\"x\" ... a{M-1}=\"x\"/\u003e\n}\n\nfor (var _i = 0, sizes = [2000, 4000, 8000, 16000, 32000]; _i \u003c sizes.length; _i++) {\n\tvar m = sizes[_i];\n\tvar xml = buildDoc(m);\n\tvar t0 = process.hrtime.bigint();\n\tvar doc = new DOMParser().parseFromString(xml, 'text/xml');  // silent: no error events\n\tvar ms = Number(process.hrtime.bigint() - t0) / 1e6;\n\tconsole.log(m + ' attrs, ' + xml.length + ' bytes -\u003e ' + ms.toFixed(1) + ' ms; parsed=' +\n\t\tdoc.documentElement.attributes.length);\n}\n```\n\nMeasured with Node.js v18.20.8 (wall-clock; absolute numbers vary by host, the **scaling** is the\nload-bearing fact):\n\n**`@xmldom/xmldom` 0.9.10:**\n\n| M (attributes) | input bytes | time (ms) | ratio vs prev |\n|---:|---:|---:|---:|\n| 2000  | 18,894  | 13.4   | —     |\n| 4000  | 38,894  | 38.7   | ×2.9  |\n| 8000  | 78,894  | 100.8  | ×2.6  |\n| 16000 | 164,894 | 406.2  | ×4.0  |\n| 32000 | 340,894 | 2149.5 | ×5.3  |\n\n**`@xmldom/xmldom` 0.8.13:**\n\n| M (attributes) | input bytes | time (ms) |\n|---:|---:|---:|\n| 2000  | 18,894  | 10.6   |\n| 4000  | 38,894  | 19.9   |\n| 8000  | 78,894  | 75.9   |\n| 16000 | 164,894 | 657.7  |\n| 32000 | 340,894 | 1643.2 |\n\n**`xmldom` (unscoped) 0.6.0:** 4000 → 28.2 ms, 8000 → 131.8 ms, 16000 → 545.2 ms (≈ ×4 per doubling).\n\nTime grows ≈ ×4 per doubling of `M` — quadratic. About **340 KB of well-formed input costs ~1.6–2.1 s\nof single-threaded CPU**, and it keeps scaling: doubling the attribute count quadruples the cost.\nThe document is trivially generated and compresses to a few kilobytes on the wire.\n\n## Impact\n\nUnauthenticated, remotely triggerable denial of service against any service that parses\nattacker-influenced XML/HTML with xmldom. A single request holds one event-loop thread for seconds;\na handful of concurrent requests can saturate CPU and stall the process. Because the payload is a\nplain well-formed document (one element, many attributes), it passes any \"must be well-formed\" gate\nand reaches the parser before any application-level validation (e.g. schema checks or signature\nverification) can run. The payload is highly compressible, so it is effective over compressed\ntransports.\n\n## Fix Applied\n\nReplaced the per-insert linear duplicate scan on the parse-time dedup path with a name-keyed\nindex, so de-duplicating an element's attributes during parse is O(M) instead of O(M²) — a\nwell-formed-but-hostile attribute list can no longer wedge the parse. Behavior-preserving: attribute\norder and duplicate resolution (last value wins, first position kept) are byte-identical. Non-breaking\nand independent of `requireWellFormed`; ships on both maintained versions.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:01:31.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-27p8-2357-5qqv","https://github.com/xmldom/xmldom/security/advisories/GHSA-8344-3jmq-59r6","https://nvd.nist.gov/vuln/detail/CVE-2026-83613","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/2c548f200cfec991cd5846627ef8f03542309213","https://github.com/xmldom/xmldom/commit/cfb09b5dbeb035fdfedc9f01e2bbaf226bf47cf3","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-8344-3jmq-59r6"],"source_kind":"github","identifiers":["GHSA-8344-3jmq-59r6","CVE-2026-83613"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.525Z","epss_percentage":0.00604,"epss_percentile":0.46571,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04MzQ0LTNqbXEtNTlyNs4ABu80","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS04MzQ0LTNqbXEtNTlyNs4ABu80","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04MzQ0LTNqbXEtNTlyNs4ABu80/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14NGZwLWo5NTQtcjJmNM4ABu8z","url":"https://github.com/advisories/GHSA-x4fp-j954-r2f4","title":"xmldom: End-tag Whitespace-Trim Regex ReDoS — quadratic backtracking in the 0.8.x end-tag parser","description":"## Summary\n\nOn the `@xmldom/xmldom` **`0.8.x`** line, parsing an XML end tag whose name is followed by a long run\nof whitespace and then a non-whitespace character triggers quadratic-time regular-expression\nbacktracking (ReDoS), so a single small crafted end tag stalls the Node.js event loop. It is reachable\nfrom `DOMParser.parseFromString` under **default options**, unauthenticated, before any validity\ncheck — an availability-only denial of service. The `0.9.x` line is **not** affected.\n\n## Details\n\n`lib/sax.js` (release-0.8.x, commit `e5c1480`) trims trailing whitespace from a captured end-tag name\nwith an unanchored global regex:\n\n- `lib/sax.js` line 120: https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/sax.js#L120\n\n```js\n/[ \\t\\n\\r]+$/g\n```\n\nApplied to a string shaped `whitespace-run + one non-whitespace char` (e.g. the content of an end tag\n`\u003c/   …   x\u003e`), the engine must, for every starting position, extend `[ws]+` to the end and then fail\nthe `$` anchor when the trailing non-whitespace char is present — classic O(n²) backtracking in the\nlength of the whitespace run. The trimmed substring is delimited only by `indexOf('\u003e')`, so the\nattacker controls its length directly.\n\n## Proof of Concept\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom'); // 0.8.x\nconst n = 64 * 1024;\nconst payload = '\u003cr\u003e\u003c/' + ' '.repeat(n) + 'x\u003e';\nconsole.time('parse');\nnew DOMParser().parseFromString(payload, 'text/xml');\nconsole.timeEnd('parse');\n```\n\nMeasured (Node 18) — time quadruples per doubling of the whitespace run (canonical O(n²)):\n\n| Whitespace run | Isolated regex | End-to-end `parseFromString` (0.8.13) |\n|---|---|---|\n|  4 KB | 5.6 ms   | 5.7 ms   |\n|  8 KB | 22.7 ms  | 22.5 ms  |\n| 16 KB | 88.6 ms  | 92 ms    |\n| 32 KB | 354 ms   | 361 ms   |\n| 64 KB | 1434 ms  | 1452 ms  |\n| 128 KB | 5761 ms | —        |\n\n## Impact\n\nAvailability only: a single parse of a small crafted document blocks the Node.js event loop for the\nduration of the quadratic scan (≈1.4 s at 64 KB; multi-second with larger inputs). No memory\nblow-up, no data exposure, no integrity impact. Because XML is routinely accepted from untrusted\nsources and parsed with default options, one request can stall a server.\n\n## Affected Versions\n\nAffected on the `0.7.x` and `0.8.x` lines (the trailing-whitespace trim was added in `0.7.0`, present\nthrough `0.8.14`); the fix targets the `0.8.x` LTS patch. The `0.9.x` line rewrote end-tag parsing to\nan anchored linear matcher and never had this regex, so it is **not** affected. No published unscoped\n`xmldom` is affected — the vulnerable code exists only in a `0.7.0` git tag that was never released to\nnpm (`npm view xmldom` → `latest` = 0.6.0).\n\n## Fix Applied\n\nAnchors the end-tag trailing-whitespace trim so it runs in linear time instead of\nbacktracking quadratically on a long whitespace run. Byte-identical output. Non-breaking; 0.8.x-only.\n\n## Severity note\n\nThe complexity is **quadratic**, not exponential, so a multi-second stall requires\ntens-to-hundreds of KB of input. `VA:H` reflects that xmldom applies **no input-size limit** and the\npath runs on default-options parsing, so a single unbounded parse can fully stall the event loop.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:01:09.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-x4fp-j954-r2f4","https://nvd.nist.gov/vuln/detail/CVE-2026-83619","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/3abb0934f5a8a84d83a1f9cde0f2bd04c08b2a09","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/advisories/GHSA-x4fp-j954-r2f4"],"source_kind":"github","identifiers":["GHSA-x4fp-j954-r2f4","CVE-2026-83619"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.526Z","epss_percentage":0.00524,"epss_percentile":0.42514,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14NGZwLWo5NTQtcjJmNM4ABu8z","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14NGZwLWo5NTQtcjJmNM4ABu8z","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14NGZwLWo5NTQtcjJmNM4ABu8z/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05NjV3LTc3NWYtbXI3Z84ABu8y","url":"https://github.com/advisories/GHSA-965w-775f-mr7g","title":"xmldom: Quadratic-memory consumption","description":"## Summary\n\nWhen an element declares a namespace prefix, xmldom copies the entire in-scope namespace map\ninto a fresh object and keeps that copy on the element while it is open on the parse stack. A\ncrafted document that nests N elements, each declaring one unique prefix, therefore drives the\nparser to hold on the order of N(N+1)/2 = **O(N²) namespace-map entries at its peak**, so a small,\nhighly compressible input exhausts the heap. Parsing runs under default options on untrusted,\nnetwork-delivered XML, so a sub-megabyte payload can OOM-crash the process before any\napplication-level validation runs — an unauthenticated denial of service.\n\n## Details\n\n`appendElement` performs the copy: `_copy` clones the current namespace map into a fresh object for\neach prefix-declaring element, and the copy is retained on that element's parse-stack entry:\n\n```js\nif (localNSMap == null) {\n    localNSMap = Object.create(null);\n    _copy(currentNSMap, (currentNSMap = Object.create(null)));   // full copy of all ancestor prefixes\n}\ncurrentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;\n...\nel.currentNSMap = currentNSMap;   // retained while the element is open on the parse stack\n```\n\nhttps://github.com/xmldom/xmldom/blob/08a22d78e4bc50f12ce9f5090b8d96ee6031ac7b/lib/sax.js#L467-L540\n\nThe copies stack: the element at depth `i` copies a map of size ~`i`, and every ancestor stays live\non the parse stack until it closes, so at the deepest point Σ`i` namespace entries are held at once.\nThat peak is transient — the completed DOM retains only O(N), one small namespace map per node — but\nit is reached during parsing, which is what OOM-crashes the process.\n\n## Proof of Concept\n\nA minimal document — N nested elements, each declaring one unique namespace prefix (no SAML wrapper\nneeded):\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom');\n\nfunction build(n) {\n  let open = '', close = '';\n  for (let i = 0; i \u003c n; i++) { open += `\u003ca xmlns:p${i}=\"urn:${i}\"\u003e`; close = '\u003c/a\u003e' + close; }\n  return `\u003cr\u003e${open}${close}\u003c/r\u003e`;   // \u003cr\u003e\u003ca xmlns:p0=\"urn:0\"\u003e...\u003ca xmlns:p{n-1}=\"urn:{n-1}\"\u003e...\u003c/a\u003e...\u003c/r\u003e\n}\n\nfor (const n of [2000, 4000, 8000, 16000]) {\n  const src = build(n);\n  new DOMParser().parseFromString(src, 'text/xml');   // peak memory ~ O(n^2)\n  console.log(n, (src.length / 1024).toFixed(0) + ' KB in', (process.resourceUsage().maxRSS / 1024).toFixed(0) + ' MB peak RSS');\n}\n```\n\nMeasured on Node.js v24 (peak RSS ~quadruples per doubling of depth; absolute numbers vary by host):\n\n| depth  | input   | peak RSS                        |\n| -----: | ------: | ------------------------------- |\n|  2,000 |  56 KB  | 266 MB                          |\n|  4,000 | 115 KB  | 622 MB                          |\n|  8,000 | 232 KB  | 1.9 GB                          |\n| 16,000 | ~470 KB | OOM crash (default ~4 GB heap)  |\n\nAbout 470 KB of trivially-generated, highly-compressible input crashes a default Node.js process;\nlarger depths scale as O(N²) into the tens of GB, crashing larger hosts (as first measured by the\nreporter with a SAML-shaped payload).\n\n## Impact\n\nUnauthenticated denial of service against any service that parses attacker-influenced XML with\nxmldom under default options. A single sub-megabyte request drives multi-gigabyte peak memory and\ncan OOM-crash the process before any application-level validation (e.g. schema checks or a SAML\nsignature verification) runs. The payload is a plain namespace-nesting document and highly\ncompressible, so it is effective over compressed transports (e.g. an HTTP-Redirect / DEFLATE\nbinding, not only POST bindings).\n\n## Severity note\n\nThe CVSS 4.0 vector scores availability only (`VC:N/VI:N/VA:H`): the flaw neither discloses nor\nalters data, it exhausts the heap. `VA:H` is justified because a single unauthenticated,\nnetwork-delivered request (`AV:N/PR:N/UI:N`) of trivial complexity (`AC:L/AT:N`) drives the parser\nto multi-gigabyte peak memory and OOM-crashes the process before any application-level logic runs —\na full loss of availability for the affected service.\n\n## Fix Applied\n\nInherit each element's in-scope namespace map through the prototype chain instead of copying it for every prefix-declaring element, so a deeply namespaced document holds O(N) namespace entries instead of O(N²) at peak. Behavior-preserving: serialized output is byte-identical, only the memory cost drops. Non-breaking and independent of `requireWellFormed`; ships on both maintained versions.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:00:52.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-965w-775f-mr7g","https://nvd.nist.gov/vuln/detail/CVE-2026-83615","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/954370f58c046223faf95ba77efcbc8ce014409d","https://github.com/xmldom/xmldom/commit/dabffe884e864eeecb1f515c716f875e1bc47ec1","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-965w-775f-mr7g"],"source_kind":"github","identifiers":["GHSA-965w-775f-mr7g","CVE-2026-83615"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.527Z","epss_percentage":0.0059,"epss_percentile":0.46506,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05NjV3LTc3NWYtbXI3Z84ABu8y","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05NjV3LTc3NWYtbXI3Z84ABu8y","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 0.1.5, \u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05NjV3LTc3NWYtbXI3Z84ABu8y/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05M3I1LWZoeDYtdm1nOc4ABu8x","url":"https://github.com/advisories/GHSA-93r5-fhx6-vmg9","title":"xmldom: Quadratic-time parsing via the malformed-input recovery path — `parseElementStartPart` re-scan and `normalize()` adjacent-text merge","description":"## Summary\n\n`xmldom`'s malformed-input **error-recovery path** has two quadratic-time (O(n²)) behaviors that a\nsingle crafted input triggers together, so a tiny, highly compressible document (tens of KB) stalls\nthe Node.js event loop for multiple seconds. It is reachable from `DOMParser.parseFromString` under\n**default options** — i.e. from unauthenticated, network-delivered XML — making this an unauthenticated\ndenial of service. One of the two behaviors, the `normalize()` adjacent-text merge, is **additionally\nreachable programmatically** — via a plain `normalize()` call on a DOM built with adjacent text nodes,\nindependent of the parser — so its fix must live in `normalize()`, not only in a parser bound.\n\n## Details\n\n### Finding A — `parseElementStartPart` quadratic re-scan\n\nA `\u003c` character is not a delimiter in any tag-parsing state, so `parseElementStartPart` scans\nforward character-by-character over any embedded `\u003c` until it reaches the next `\u003e` (or end of\ninput), then validates the accumulated slice as a tag name and throws `invalid tagName:` on failure.\nThe main loop catches this, reports an `error`, sets `end = -1`, and recovers by advancing a single\ncharacter (`appendText(Math.max(tagStart, start) + 1)`). With a long run of `\u003c` and a distant `\u003e`,\neach of the O(n) recovery retries performs an O(n) scan plus an O(n) anchored regex validation over\nthe growing candidate ⇒ **O(n²)**.\n\nCode (0.9.x, `bb7a085dc5ba1eea3212388509b97bb4b4af32b9`):\n\n- `parseElementStartPart` character scan — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L263-L461\n- tag-name validation (`setTagName` → throws `invalid tagName`) — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L886-L891\n- main-loop `catch` → `error` + `end = -1` — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L234-L242\n- single-character recovery fallback — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L247\n\nCode (0.8.x, `e5c14802592685bb872c042c54c3f73758875c85`):\n\n- `parseElementStartPart` — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/sax.js#L227\n- `catch` → `error` + `end = -1` — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/sax.js#L202-L208\n- recovery fallback — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/sax.js#L213\n- `setTagName` validation — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/sax.js#L616-L621\n\n### Finding B — `normalize()` adjacent-text O(K²) merge\n\n`endDocument()` calls `document.normalize()`. For a parent with K adjacent text nodes (produced by\nthe one-character recovery of Finding A), `normalize()` performs K−1 merges. Each merge does a\n`removeChild` — which re-indexes **all** child nodes of the parent (O(K)) — and an `appendData` —\nwhich rebuilds the accumulator string `this.data + text` (O(K)). Total: **O(K²)**.\n\nWell-formed XML cannot produce adjacent text-node siblings *through the parser* (each text run is one\nnode; comments, CDATA, PIs, and elements sit between runs), so the **parse-path** trigger for Finding B\nis the malformed-input recovery that emits single-character text nodes. The same O(K²) merge is,\nhowever, independently reachable via the public `normalize()` API on a programmatically built tree\n(see \"Finding B is additionally reachable programmatically\" below).\n\nCode (0.9.x, `bb7a085dc5ba1eea3212388509b97bb4b4af32b9`):\n\n- `endDocument` → `normalize()` — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom-parser.js#L418-L420\n- `normalize()` adjacent-text merge — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L1336-L1356\n- `removeChild` re-index-all branch — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L1788-L1798\n- `appendData` string rebuild — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/dom.js#L2786-L2790\n\nCode (0.8.x, `e5c14802592685bb872c042c54c3f73758875c85`):\n\n- `endDocument` → `normalize()` — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom-parser.js#L213-L214\n- `normalize()` merge — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L529-L549\n- `removeChild` re-index-all branch — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L756-L773\n- `appendData` string rebuild — https://github.com/xmldom/xmldom/blob/e5c14802592685bb872c042c54c3f73758875c85/lib/dom.js#L1533\n\n### Finding B is additionally reachable programmatically (no parser involved)\n\n`Node.prototype.normalize()` is public API on every `Document`/`Element`. A tree built entirely through\nthe ordinary DOM API — `new DOMImplementation().createDocument(...)`, then K× `createTextNode` +\n`appendChild` on one parent — reaches the **same** O(K²) merge when the application calls `normalize()`,\nwith **no** parsing and **no** error-recovery. The parser is only *one* of the two callers of the\nvulnerable merge:\n\n- the parser's automatic `endDocument()` → `document.normalize()` (the parse-path trigger above), and\n- any explicit application call to the public `normalize()` on a tree with adjacent text nodes.\n\n`XMLSerializer` does **not** call `normalize()`, so serializing an un-merged tree is O(total text), not\nO(K²); the O(K²) surface is exactly those two `normalize()` callers. Consequently a parser-side bound\nalone cannot remediate Finding B — the fix must live in `normalize()`.\n\n## Affected Versions\n\nBoth findings are present across the full published `@xmldom/xmldom` history — both\ncurrently-maintained versions (`0.8.x` and `0.9.x`) are affected — and across the retired unscoped\n`xmldom` line. Finding B's `normalize()` merge is additionally reachable **programmatically**: a\ndirect `normalize()` call on a DOM built with adjacent text nodes hits the same O(K²) merge,\nindependent of the parser — so, unlike Finding A, it does not require the malformed-input recovery\npath.\n\n## Proof of Concept\n\nDefault `DOMParser`, no options. The input is trivially compressible (`a\u003c` / `a\u003c\u003e` repeated) and\nnever throws — it is parsed via the recovery path.\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom');\n\n// Silence the expected `error`-level recovery reports (default handler logs\n// them to console.error without throwing; only fatalError throws).\nconsole.error = function () {};\n\nfunction timeParse(label, xml, mime) {\n  const t0 = process.hrtime.bigint();\n  new DOMParser().parseFromString(xml, mime); // completes; no exception\n  const ms = Number(process.hrtime.bigint() - t0) / 1e6;\n  console.log(label + '  bytes=' + Buffer.byteLength(xml) + '  time=' + ms.toFixed(1) + ' ms');\n}\n\nfor (const N of [4000, 8000, 16000, 32000]) {\n  // Finding A: long re-scans, O(n^2) during parse.\n  timeParse('A N=' + N, '\u003cr\u003e' + 'a\u003c'.repeat(N) + '\u003c/r\u003e', 'text/xml');\n  // Finding B: short re-scans (cheap parse) but K adjacent text nodes -\u003e O(K^2) in normalize().\n  timeParse('B N=' + N, '\u003cr\u003e' + 'a\u003c\u003e'.repeat(N) + '\u003c/r\u003e', 'text/html');\n  // Combined: ONE input hits both A and B under the default parser.\n  timeParse('C N=' + N, '\u003cr\u003e' + 'a\u003c'.repeat(N) + '\u003c/r\u003e', 'text/xml');\n}\n```\n\nMeasured on Node v18.20.8 (absolute ms vary by host; the load-bearing fact is that doubling the\ninput ~quadruples the time — canonical O(n²)):\n\nFinding A, isolated (`\"\u003cr\u003e\" + \"a\u003c\"×N + \"\u003c/r\u003e\"`, normalize disabled to isolate the re-scan):\n\n| N | input bytes | `@xmldom/xmldom` 0.9.10 | 0.8.13 |\n|--:|--:|--:|--:|\n| 2000 | 4007 | 43 ms | 37 ms |\n| 4000 | 8007 | 129 ms | 106 ms |\n| 8000 | 16007 | 434 ms | 424 ms |\n| 16000 | 32007 | 1629 ms | 1611 ms |\n\nFinding B, isolated (`\"\u003cr\u003e\" + \"a\u003c\u003e\"×N + \"\u003c/r\u003e\"`, time attributable to `normalize()`):\n\n| K (N) | input bytes | 0.9.10 | 0.8.13 |\n|--:|--:|--:|--:|\n| 4000 | 12007 | 120 ms | 165 ms |\n| 8000 | 24007 | 589 ms | 771 ms |\n| 16000 | 48007 | 3142 ms | 4448 ms |\n| 32000 | 96007 | 12127 ms | 12951 ms |\n\nCombined (default parser, both findings; `\"\u003cr\u003e\" + \"a\u003c\"×N + \"\u003c/r\u003e\"`):\n\n| N | input bytes | 0.9.10 | 0.8.13 |\n|--:|--:|--:|--:|\n| 4000 | 8007 | 341 ms | 397 ms |\n| 8000 | 16007 | 1894 ms | 1641 ms |\n| 16000 | 32007 | 4398 ms | 7661 ms |\n\n~32 KB of input → several seconds of single-threaded event-loop stall.\n\n### Finding B via the public `normalize()` API (no parser)\n\n```js\nconst { DOMImplementation } = require('@xmldom/xmldom');\n\nfunction timeNormalize(K) {\n  const doc = new DOMImplementation().createDocument(null, 'r', null);\n  const el = doc.documentElement;\n  for (let i = 0; i \u003c K; i++) el.appendChild(doc.createTextNode('x')); // K adjacent text nodes\n  const t0 = process.hrtime.bigint();\n  doc.normalize();                                    // O(K^2) merge — no parsing involved\n  const ms = Number(process.hrtime.bigint() - t0) / 1e6;\n  console.log('K=' + K + '  time=' + ms.toFixed(1) + ' ms');\n}\nfor (const K of [2000, 4000, 8000, 16000, 32000]) timeNormalize(K);\n```\n\nMeasured on Node v18.20.8 (doubling K ~quadruples the time — O(K²)):\n\n| K | 0.9.10 | 0.8.13 |\n|--:|--:|--:|\n| 2000 | 5.7 ms | 5.6 ms |\n| 32000 | 1263 ms | 1704 ms |\n\nThis path is reachable by any application that builds a DOM from attacker-influenced data and calls\n`normalize()`, entirely independent of `DOMParser`.\n\n## Impact\n\nAvailability only: a single parse of a small crafted document blocks the Node.js event loop for the\nduration of the quadratic work (multiple seconds at tens of KB; larger inputs scale as O(n²)). No\nmemory blow-up beyond transient strings, no data exposure, no integrity impact. Because XML is\nroutinely accepted from untrusted sources and parsed with default options, one request can stall a\nserver. The payloads are highly compressible, so any endpoint accepting compressed XML faces\nadditional amplification. Finding B is additionally reachable via an explicit `normalize()` call on a\nprogrammatically built DOM (see Proof of Concept), so applications that construct a document from attacker-influenced\ndata and normalize it are exposed even without parsing.\n\n## Severity note\n\nThe complexity is **quadratic**, not exponential, so a multi-second stall requires\ntens-to-hundreds of KB of input. `VA:H` reflects that xmldom applies **no** input-size limit and the\npath runs on default-options parsing, so a single unbounded parse can fully stall the event loop.\n\n## Fix Applied\n\nTwo independent, non-breaking fixes shipped together — each alone leaves the other's quadratic cost dominating the default parse.\nFinding A — terminate the malformed tag-name scan at an embedded `\u003c`, so error recovery is linear instead of O(n²). DOM output is unchanged; only the reported error-message text differs (error strings are not a semver contract).\nFinding B — merge adjacent text nodes in `normalize()` in O(K) instead of O(K²), which also closes the same slowdown reachable programmatically through a direct `normalize()` call. Both ship on both maintained versions.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T21:00:41.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-93r5-fhx6-vmg9","https://nvd.nist.gov/vuln/detail/CVE-2026-83614","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/0748720b620555f8c222782dcab575cf0cf403b4","https://github.com/xmldom/xmldom/commit/f40ccb861eee0acbf5ee4feb9a34932e87b329c9","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-93r5-fhx6-vmg9"],"source_kind":"github","identifiers":["GHSA-93r5-fhx6-vmg9","CVE-2026-83614"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T22:00:08.678Z","updated_at":"2026-10-09T10:01:54.527Z","epss_percentage":0.0059,"epss_percentile":0.46506,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05M3I1LWZoeDYtdm1nOc4ABu8x","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05M3I1LWZoeDYtdm1nOc4ABu8x","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 0.3.0, \u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05M3I1LWZoeDYtdm1nOc4ABu8x/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02bWozLXF3NGotaGdyd84ABu8w","url":"https://github.com/advisories/GHSA-6mj3-qw4j-hgrw","title":"xmldom: HTML raw-text closing-tag case mismatch causes output amplification","description":"## Summary\n\nIn HTML mode (`text/html`), a raw-text element (`script`, `style`, `textarea`, `title`) whose closing\ntag differs in case from its opening tag (e.g. `\u003c/ScRiPt\u003e` for `\u003cscript\u003e`) is mishandled by the\nparser, producing quadratic (O(n²)) output growth — a small crafted document parses and serializes\ninto output orders of magnitude larger, exhausting CPU and memory. A modest input of tens of KB can\ntherefore cause a denial of service in any service that parses untrusted HTML with xmldom. Only HTML\nmode is affected.\n\n## Details\n\nThe parser calls `parseHtmlSpecialContent` for each raw-text element in HTML mode, matched via\n`isHTMLRawTextElement` / `isHTMLEscapableRawTextElement` (so all four types — `script`, `style`,\n`textarea`, `title` — are in scope). It searches for the element's closing tag with\n`source.indexOf('\u003c/' + tagName + '\u003e', elStartEnd)`, a byte-for-byte case-sensitive match. A\nmixed-case closing tag never matches, so the search returns `-1`, and the following\n`source.substring(elStartEnd + 1, -1)` extracts text backwards from the start of the document\ninstead of the element's content. The function then returns `-1` to the parse loop, which cannot\nadvance normally and falls back to character-by-character reprocessing. Every raw-text element\nre-captures all source text preceding it, so output grows as O(n²) in the number of such elements.\n\n### Root Cause\n\n1. **Case-sensitive close-tag search** (`lib/sax.js:549`): `source.indexOf('\u003c/' + tagName + '\u003e',\n   elStartEnd)` does not fold case, contrary to the WHATWG HTML RAWTEXT end-tag-name rule.\n2. **Unguarded `-1`** (`lib/sax.js:550`): `source.substring(elStartEnd + 1, elEndStart)` runs even\n   when `elEndStart === -1`, extracting text backwards from position 0.\n3. **Unstable progression** (`lib/sax.js:556`): the function returns `elEndStart` (`-1`), driving\n   repeated character-by-character fallback in the parse loop.\n\n## Affected Versions\n\nOnly the `0.9.x` line is affected — the amplification was introduced in `0.9.0-beta.1` when\n`parseHtmlSpecialContent` was refactored, and remains through `0.9.11`. The `0.8.x` line is **not**\naffected: its older `parseHtmlSpecialContent` does not amplify, despite sharing the same\ncase-sensitive `indexOf`.\n\n## Proof of Concept\n\n```js\nconst { DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst n = 1000;\nconst payload = '\u003chtml\u003e\u003cbody\u003e' + '\u003cscript\u003ex\u003c/ScRiPt\u003e'.repeat(n) + '\u003c/body\u003e\u003c/html\u003e';\nconst doc = new DOMParser().parseFromString(payload, 'text/html');\nconst out = new XMLSerializer().serializeToString(doc);\nconsole.log(payload.length, out.length, (out.length / payload.length).toFixed(1) + 'x');\n// 18026 9037063 501.3x  — an 18 KB input yields ~9 MB of output\n```\n\nOutput size grows quadratically with the number of case-mismatched raw-text elements:\n\n```\nRepeats | Input len | Output len | Ratio\n1       | 44        | 109        | 2.5x\n100     | 1826      | 93763      | 51.3x\n500     | 9026      | 2268563    | 251.3x\n1000    | 18026     | 9037063    | 501.3x\n2000    | 36026     | 36074063   | 1001.3x\n```\n\nProof of Concept from @KarimTantawey (tested with `script`); the same amplification occurs for `style`,\n`textarea`, and `title`.\n\n## Impact\n\nSmall attacker payloads can force disproportionate CPU and memory usage in services that\nparse and serialize untrusted HTML via xmldom. The quadratic growth means a modest-sized input\n(tens of kilobytes) can produce output in the tens or hundreds of megabytes, potentially\nexhausting memory or causing timeouts.\n\nThe attack only requires HTML mode (`text/html` MIME type) and mixed-case closing tags for\nany of the four raw-text element types. No special configuration or error handler setup is needed.\n\n## Severity note\n\nThe CVSS 4.0 vector scores availability only (`VA:H`, with `VC:N/VI:N`): the flaw neither discloses\nnor corrupts data, but a small untrusted HTML input (tens of KB) can force output and memory in the\ntens to hundreds of MB, enough to exhaust a service's heap or stall its event loop. It is reachable\nwith no authentication, configuration, or error-handler setup — only that the application parses\nuntrusted `text/html` and serializes the result.\n\n## Fix Applied\n\nThe raw-text closing tag is now matched case-insensitively in HTML raw-text mode (per the WHATWG HTML\n[RAWTEXT end-tag rule](https://html.spec.whatwg.org/multipage/parsing.html#rawtext-end-tag-name-state)),\nand a missing closing tag is handled explicitly, removing the quadratic output amplification. Output\nfor well-formed input is unchanged. Non-breaking; 0.9.x-only.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T20:59:54.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-6mj3-qw4j-hgrw","https://nvd.nist.gov/vuln/detail/CVE-2026-83612","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/commit/7ced40c06c28d151e996a97045018c3559ae4707","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-6mj3-qw4j-hgrw"],"source_kind":"github","identifiers":["GHSA-6mj3-qw4j-hgrw","CVE-2026-83612"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T21:00:09.188Z","updated_at":"2026-10-09T10:01:54.528Z","epss_percentage":0.00524,"epss_percentile":0.42518,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02bWozLXF3NGotaGdyd84ABu8w","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02bWozLXF3NGotaGdyd84ABu8w","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0-beta.1, \u003c= 0.9.11"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02bWozLXF3NGotaGdyd84ABu8w/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1nNTNnLXc4cmotZm1nN84ABu8e","url":"https://github.com/advisories/GHSA-g53g-w8rj-fmg7","title":"xmldom PI grammar regex ReDoS: quadratic backtracking on unterminated processing instructions","description":"## Summary\n\n`@xmldom/xmldom`'s processing-instruction (PI) grammar regex exhibits quadratic-time backtracking\n(ReDoS) when parsing an **unterminated** processing instruction. A single small XML document\ncontaining `\u003c?` + a target + a long run of whitespace and no closing `?\u003e` forces the regular\nexpression engine into O(n²) work, stalling the Node.js event loop. The input is parsed with\n`DOMParser.parseFromString` under **default options**, so it is reachable from unauthenticated,\nnetwork-delivered XML (SOAP/SAML, webhooks, uploads, XML APIs).\n\n## Details\n\nThe PI production in `lib/grammar.js` compiles (flags `mu`) to:\n\n```\n^\u003c\\?(NameChars)(?:[\\x20\\x09\\x0D\\x0A]+([Char]*?))?\\?\u003e\n                     ^^^ S+ greedy       ^^^ Char*? lazy\n```\n\n- `lib/grammar.js` line 261: https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/grammar.js#L261\n\nIn the optional tail `(?:S+(Char*?))?`, both the greedy separator `S+` and the lazy data `Char*?`\nmatch XML whitespace. When the required trailing `?\u003e` is absent, the engine must ultimately fail —\nbut first it tries every partition of the whitespace run between `S+` and `Char*?`, which is O(n²)\nin the length of the trailing whitespace.\n\nThe regex is executed against the **entire remaining source string** in two places in `lib/sax.js`,\nso the whole whitespace tail is scanned:\n\n- `parsePI` — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L680-L691\n- `parseProcessingInstruction` — https://github.com/xmldom/xmldom/blob/bb7a085dc5ba1eea3212388509b97bb4b4af32b9/lib/sax.js#L862-L879\n\n## Affected Versions\n\nOnly the `0.9.x` line is affected. `lib/grammar.js` (and this PI regex) was introduced in\ncommit `726b471` (\"fix!: preserve DOCTYPE internal subset (#498)\"), first released in\n**0.9.0-beta.9**, and is unchanged through **0.9.10**.\n\nThe `0.8.x` line (≤ 0.8.13) and the unscoped `xmldom` package (≤ 0.6.0) parse PIs via a different\ncode path bounded by `indexOf('?\u003e')` — they do **not** contain this regex and are **not affected**\nby this issue. (They were not separately tested for a *different* PI ReDoS; the scope here is the\nspecific `grammar.js` regex.)\n\n| Line | PI code path | Affected? |\n|---|---|---|\n| `0.9.x` (0.9.0-beta.9 … 0.9.10) | `grammar.js` `PI` regex over full remaining source | **Yes** |\n| `0.8.x` (≤ 0.8.13) | `parseInstruction`, bounded by `indexOf('?\u003e')` | No |\n| unscoped `xmldom` (≤ 0.6.0) | older `indexOf('?\u003e')`-bounded parsing | No |\n\n## Proof of Concept\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom');\nconst n = 32 * 1024;\nconst payload = '\u003ca\u003e\u003c?p' + ' '.repeat(n); // unterminated PI, no `?\u003e`\nconsole.time('parse');\nnew DOMParser().parseFromString(payload, 'text/xml');\nconsole.timeEnd('parse');\n```\n\nMeasured (Node 18), trailing whitespace after `\u003c?p`, no `?\u003e` — time quadruples per doubling of\ninput length (canonical O(n²)):\n\n| Trailing whitespace | `g.PI.exec` | `parseFromString` |\n|---|---|---|\n| 2 KB  | 4.4 ms    | 5.1 ms   |\n| 4 KB  | 16.9 ms   | 17.0 ms  |\n| 8 KB  | 111.4 ms  | 66.3 ms  |\n| 16 KB | 263.8 ms  | 336.5 ms |\n| 32 KB | 1073.1 ms | —        |\n\n## Impact\n\nAvailability only: a single parse of a small crafted document blocks the Node.js event loop for the\nduration of the quadratic scan (≈1 s at 32 KB; multi-second with larger inputs). No memory blow-up,\nno data exposure, no integrity impact. Because XML is routinely accepted from untrusted sources and\nparsed with default options, one request can stall a server.\n\n## Fix Applied\n\nFixed in `@xmldom/xmldom` **0.9.11** (`0.9.x`-only; the `0.8.x` LTS line and the\nunscoped `xmldom` package use a different, bounded PI code path and are not affected).\n\nPR [#1039](https://github.com/xmldom/xmldom/pull/1039) inserts a fixed-width negative lookahead\n`(?!\\s)` immediately after the greedy `S+`, so the separator can no longer hand whitespace back to\nthe lazy data group:\n\n```\n- var PI = reg(/^\u003c\\?/, '(', Name, ')', regg(S, '(', Char, '*?)'), '?', /\\?\u003e/);\n+ var PI = reg(/^\u003c\\?/, '(', Name, ')', regg(S, '(?!', _SChar, ')(', Char, '*?)'), '?', /\\?\u003e/);\n```\n\nThe change is correct, minimal, and behavior-preserving: it produces identical `[target, data]`\ncaptures on all valid PIs tested (incl. whitespace-heavy, tab/newline, empty-data, and xml-decl\ncases) and removes the backtracking blow-up (linear, ~0.4 ms at 128 KB after the fix). The lookahead\nis fixed-width and cannot itself backtrack — a strict improvement with no new parsing risk.\n\n## Severity note\n\nThe complexity is **quadratic**, not exponential, so a multi-second stall requires\ntens-to-hundreds of KB of input. `VA:H` reflects that xmldom applies **no input-size limit** and the\npath runs on default-options parsing, so a single unbounded parse can fully stall the event loop.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T20:31:50.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-g53g-w8rj-fmg7","https://nvd.nist.gov/vuln/detail/CVE-2026-83606","https://github.com/xmldom/xmldom/pull/1039","https://github.com/xmldom/xmldom/commit/73df6b8bdbd86f904b9e8c3ab9c49aa54ef2802e","https://github.com/xmldom/xmldom/releases/tag/0.9.11","https://github.com/advisories/GHSA-g53g-w8rj-fmg7"],"source_kind":"github","identifiers":["GHSA-g53g-w8rj-fmg7","CVE-2026-83606"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T21:00:09.189Z","updated_at":"2026-10-09T10:01:57.578Z","epss_percentage":0.00524,"epss_percentile":0.42508,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNTNnLXc4cmotZm1nN84ABu8e","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1nNTNnLXc4cmotZm1nN84ABu8e","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.11","vulnerable_version_range":"\u003e= 0.9.0-beta.9, \u003c= 0.9.10"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNTNnLXc4cmotZm1nN84ABu8e/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS13MnJyLTM0ZzktcnZyas4ABu8d","url":"https://github.com/advisories/GHSA-w2rr-34g9-rvrj","title":"xmldom: Element name injection via createElement() bypasses requireWellFormed","description":"## Summary\n\n`Document.createElement()` in `@xmldom/xmldom` accepts arbitrary strings as the `tagName` parameter with zero validation. The serializer emits the tag name verbatim into XML/HTML output. Critically, the `requireWellFormed: true` serializer option — the recommended mitigation from CVE-2026-41672, CVE-2026-41674, and CVE-2026-34601 — did NOT catch this, making it a bypass of the existing security controls.\n\nAn attacker who controls the element name string can inject arbitrary attributes (including event handlers) into the serialized output, leading to XSS when the output is consumed by a browser or downstream parser.\n\n## Details\n\n`Document.createElement()` accepts any string as `tagName` and stores it directly on the element node without validation. When the document is later serialized via `XMLSerializer.serializeToString()`, the serializer emits the `tagName` verbatim into the output.\n\nThe XML specification requires element names to conform to the `Name` production. The existing `createAttributeNS()` and `createElementNS()` methods validate qualified names against an anchored name/`QName` pattern, but `createElement()` bypasses this entirely, and the `requireWellFormed: true` serializer path performed no element-name validation — rendering it ineffective against this vector.\n\n### Root Cause\n\n1. `createElement()` stores the raw `tagName` string without any validation.\n2. The serializer's `requireWellFormed` code path did not validate element names against the XML `Name`/`QName` production.\n3. The serializer emits `tagName` directly into angle brackets: `\u003c${tagName}...\u003e`.\n\n## Proof of Concept\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\nconst doc = impl.createDocument(null, 'root', null);\n\n// Inject an element whose \"name\" contains attributes with an XSS payload\nconst el = doc.createElement('img src=x onerror=\"alert(1)\"');\ndoc.documentElement.appendChild(el);\n\nconst output = serializer.serializeToString(doc, { requireWellFormed: true });\nconsole.log(output);\n// \u003croot\u003e\u003cimg src=x onerror=\"alert(1)\"/\u003e\u003c/root\u003e\n//\n// A browser parsing this HTML will execute alert(1).\n// requireWellFormed: true did NOT prevent the injection.\n```\n\n## Impact\n\nApplications that use `@xmldom/xmldom` to construct DOM trees and serialize them to XML/HTML are vulnerable to injection attacks if any part of an element name originates from user input. This includes:\n\n- **Cross-Site Scripting (XSS)**: Injecting event handler attributes (`onerror`, `onclick`, etc.) into HTML output consumed by browsers.\n- **XML injection**: Breaking XML document structure by injecting closing tags, new elements, or processing instructions through the element name.\n- **Security control bypass**: Applications that adopted `requireWellFormed: true` as a mitigation for CVE-2026-41672 / 41674 / 34601 remained vulnerable through this vector.\n\n`@xmldom/xmldom` can also be used inside browsers, where it mirrors the DOM API. Unlike the browser's `createElement()`, which rejects an invalid name with `InvalidCharacterError`, xmldom accepts it — developers may assume the same safety and skip validation.\n\n## Fix Applied\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\nWhen `{ requireWellFormed: true }` is passed, the serializer now validates each element's serialized qualified name against the XML `QName` production and throws `InvalidStateError` before emitting the start tag. This also covers the **namespace-prefix** sub-vector: an invalid prefix surfaces either in the element qualified name (`PREFIX:local`) or in a synthesized `xmlns:PREFIX` declaration, and both are QName-checked.\n\nFixed under `requireWellFormed: true` in `@xmldom/xmldom` **0.9.11** and **0.8.14**. Default serialization is unchanged.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\ndoc.documentElement.appendChild(doc.createElement('img src=x onerror=\"alert(1)\"'));\n\n// Default (unchanged): verbatim — injection present\nconsole.log(new XMLSerializer().serializeToString(doc));\n// \u003croot\u003e\u003cimg src=x onerror=\"alert(1)\"/\u003e\u003c/root\u003e\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n  new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name, e.message);\n  // InvalidStateError: The element name \"img src=x onerror=\"alert(1)\"\" is not a valid XML QName\n}\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the serializer emits element names verbatim, matching the `XMLSerializer` behavior of Chrome, Firefox, and Safari. Unconditionally throwing would be a behavioral breaking change with no spec justification; the opt-in `requireWellFormed: true` flag lets applications that require injection safety enable strict mode without breaking existing code.\n\n### Residual limitation\n\n`createElement(tagName)` does not validate `tagName` at creation time. Enforcing an `InvalidCharacterError` for invalid names unconditionally at creation time is a breaking change and is deferred to the next breaking release. When the default serialization path is used (without `requireWellFormed: true`), invalid element names are still emitted verbatim; applications that do not pass `requireWellFormed: true` remain exposed.\n\nCreation-time validation is tracked in a public issue on the next breaking-release milestone (filed at publication — issue link to be added), targeting the next breaking release.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T20:31:08.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-w2rr-34g9-rvrj","https://nvd.nist.gov/vuln/detail/CVE-2026-83607","https://github.com/xmldom/xmldom/pull/1043","https://github.com/xmldom/xmldom/pull/1050","https://github.com/xmldom/xmldom/commit/cba1321218b069182695813fa7565653708e172e","https://github.com/xmldom/xmldom/commit/d8212e632507eaf1d9f609657dd4c56abeb12d44","https://github.com/xmldom/xmldom/releases/tag/0.8.14","https://github.com/xmldom/xmldom/releases/tag/0.9.11","https://github.com/advisories/GHSA-w2rr-34g9-rvrj"],"source_kind":"github","identifiers":["GHSA-w2rr-34g9-rvrj","CVE-2026-83607"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T21:00:09.189Z","updated_at":"2026-10-09T10:01:57.579Z","epss_percentage":0.00612,"epss_percentile":0.47568,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13MnJyLTM0ZzktcnZyas4ABu8d","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS13MnJyLTM0ZzktcnZyas4ABu8d","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.8.14","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.13"},{"first_patched_version":"0.9.11","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.10"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13MnJyLTM0ZzktcnZyas4ABu8d/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00dzN3LTJycDUtZzhqbc4ABu8c","url":"https://github.com/advisories/GHSA-4w3w-2rp5-g8jm","title":"xmldom: Attribute name injection via setAttribute() bypasses requireWellFormed","description":"## Summary\n\n`Element.setAttribute()` in `@xmldom/xmldom` bypasses attribute name validation by calling the private `_createAttribute(name)` method, which performs no validation. The public `createAttribute()` method correctly validates names against an anchored `QName` pattern, but `setAttribute()` never uses it. The serializer escapes attribute *values* but trusts attribute *names*, allowing an attacker to inject additional attributes (including event handlers) into serialized output. The `requireWellFormed: true` option did not catch this.\n\n## Details\n\n`Element.setAttribute(name, value)` creates attribute nodes by calling the private `_createAttribute(name)` method, which performs no validation on the `name` parameter. In contrast, the public `Document.createAttribute(name)` method validates the name against the `QName` production before creating the attribute node.\n\nThe result is a two-tier validation system where the most commonly used API (`setAttribute`) takes the unvalidated path:\n\n- `doc.createAttribute(\"bad name\")` — throws `INVALID_CHARACTER_ERR` (correct).\n- `el.setAttribute(\"bad name\", \"value\")` — succeeds silently (vulnerable).\n\nThe serializer emits attribute names verbatim into the output. Because attribute values ARE escaped (quotes, ampersands, etc.), the injection must occur through the name. An attacker can terminate the current attribute and inject new ones by including quote and space characters in the attribute name.\n\n### Root Cause\n\n1. `setAttribute()` calls `_createAttribute()` (private, no validation) instead of `createAttribute()` (public, validates against `QName`).\n2. The serializer trusts attribute names and emits them unescaped.\n3. The serializer's `requireWellFormed` code path did not validate attribute names during serialization.\n\n## Proof of Concept\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst serializer = new XMLSerializer();\nconst doc = impl.createDocument(null, 'root', null);\n\n// The attribute name contains a closing quote, a space, and a new attribute\ndoc.documentElement.setAttribute('class=\"safe\" onclick', 'alert(1)');\n\nconst output = serializer.serializeToString(doc, { requireWellFormed: true });\nconsole.log(output);\n// \u003croot class=\"safe\" onclick=\"alert(1)\"/\u003e\n//\n// The single setAttribute() call produced TWO attributes:\n//   1. class=\"safe\"\n//   2. onclick=\"alert(1)\"\n//\n// requireWellFormed: true did NOT prevent the injection.\n```\n\n### Demonstrating the validation gap\n\n```js\n// Public createAttribute correctly rejects invalid names:\ntry {\n  doc.createAttribute('class=\"safe\" onclick');\n} catch (e) {\n  console.log('createAttribute rejects:', e.message);\n}\n\n// But setAttribute (which uses _createAttribute) accepts the same input:\ndoc.documentElement.setAttribute('class=\"safe\" onclick', 'alert(1)');\n// No error thrown\n```\n\n## Impact\n\nApplications that use `setAttribute()` with any user-controlled portion of the attribute name are vulnerable to attribute injection attacks. This includes:\n\n- **Cross-Site Scripting (XSS)**: Injecting event handler attributes into HTML output consumed by browsers.\n- **Security attribute override**: Overriding security-relevant attributes such as `integrity`, `nonce`, `sandbox`, or `Content-Security-Policy` meta attributes.\n- **Validation bypass**: The public `createAttribute()` API validates while `setAttribute()` does not, creating an inconsistent security boundary that developers cannot rely on.\n- **requireWellFormed bypass**: Applications that adopted `requireWellFormed: true` as a mitigation for prior CVEs remained vulnerable.\n\n`@xmldom/xmldom` can also be used inside browsers, where it mirrors the DOM API. Unlike the browser's `setAttribute()`, which rejects an invalid attribute name with `InvalidCharacterError`, xmldom accepts it — developers may assume the same safety and skip validation.\n\n## Fix Applied\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\nWhen `{ requireWellFormed: true }` is passed, the serializer now validates each serialized attribute's qualified name against the XML `QName` production and throws `InvalidStateError` before emitting it. This covers ordinary attribute names **and** synthesized `xmlns:PREFIX` namespace declarations (the namespace-prefix sub-vector).\n\nFixed under `requireWellFormed: true` in `@xmldom/xmldom` **0.9.11** and **0.8.14**. Default serialization is unchanged.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\ndoc.documentElement.setAttribute('class=\"safe\" onclick', 'alert(1)');\n\n// Default (unchanged): verbatim — injection present\nconsole.log(new XMLSerializer().serializeToString(doc));\n// \u003croot class=\"safe\" onclick=\"alert(1)\"/\u003e\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n  new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name, e.message);\n  // InvalidStateError: The attribute name \"class=\"safe\" onclick\" is not a valid XML QName\n}\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the serializer emits attribute names verbatim, matching the `XMLSerializer` behavior of Chrome, Firefox, and Safari. Unconditionally throwing would be a behavioral breaking change with no spec justification; the opt-in `requireWellFormed: true` flag lets applications that require injection safety enable strict mode without breaking existing code.\n\n### Residual limitation\n\n`setAttribute(name, value)` does not validate `name` at creation time (unlike the public `createAttribute()`, which already does). Making `setAttribute()` reject invalid names unconditionally is a breaking change and is deferred to the next breaking release. When the default serialization path is used (without `requireWellFormed: true`), attribute names set via `setAttribute()` are still emitted verbatim; applications that do not pass `requireWellFormed: true` remain exposed.\n\nCreation-time validation is tracked in a public issue on the next breaking-release milestone (filed at publication — issue link to be added), targeting the next breaking release.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-08T20:30:51.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-4w3w-2rp5-g8jm","https://nvd.nist.gov/vuln/detail/CVE-2026-83605","https://github.com/xmldom/xmldom/pull/1043","https://github.com/xmldom/xmldom/pull/1050","https://github.com/xmldom/xmldom/commit/cba1321218b069182695813fa7565653708e172e","https://github.com/xmldom/xmldom/commit/d8212e632507eaf1d9f609657dd4c56abeb12d44","https://github.com/xmldom/xmldom/releases/tag/0.8.14","https://github.com/xmldom/xmldom/releases/tag/0.9.11","https://github.com/advisories/GHSA-4w3w-2rp5-g8jm"],"source_kind":"github","identifiers":["GHSA-4w3w-2rp5-g8jm","CVE-2026-83605"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T21:00:09.189Z","updated_at":"2026-10-09T10:01:57.580Z","epss_percentage":0.00612,"epss_percentile":0.47569,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00dzN3LTJycDUtZzhqbc4ABu8c","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00dzN3LTJycDUtZzhqbc4ABu8c","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.8.14","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.13"},{"first_patched_version":"0.9.11","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.10"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00dzN3LTJycDUtZzhqbc4ABu8c/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02Z21xLTh2cDgtZ2NtNs4ABodd","url":"https://github.com/advisories/GHSA-6gmq-8vp8-gcm6","title":"xmldom: XML fragment injection via invalid EntityReference.nodeName during requireWellFormed serialization","description":"## Summary\n\nAn `EntityReference` node can be created with an invalid, attacker-controlled name through `Document.createEntityReference(name)`. When this node is serialized directly with:\n\n```js\nserializer.serializeToString(ref, { requireWellFormed: true })\n```\n\nthe invalid `nodeName` is emitted into the serialized XML fragment without validation or escaping.\n\nThis can produce real XML markup in the serialized output. In the proof of concept below, the serialized fragment contains `\u003cinjected/\u003e`, and reparsing the fragment creates a real `injected` element.\n\n---\n\n## Details\n\nThe issue appears to be in the serialization path for `ENTITY_REFERENCE_NODE`.\n\nFor several other node types, `requireWellFormed: true` performs specific validation checks before serialization. For example, comments, processing instructions, document types, and some character data cases are checked before being emitted.\n\nHowever, for `ENTITY_REFERENCE_NODE`, the serializer appears to emit the node name directly in entity reference form:\n\n```js\ncase ENTITY_REFERENCE_NODE:\n  buf.push('\u0026', n.nodeName, ';');\n  return null;\n```\n\nAs a result, if `nodeName` contains characters that break out of the intended `\u0026name;` structure, the serializer can emit additional XML markup.\n\nFor example, an entity reference created with the name:\n\n```text\nsafe; \u003cinjected/\u003e \u0026x\n```\n\nis serialized as:\n\n```xml\n\u0026safe; \u003cinjected/\u003e \u0026x;\n```\n\nWhen this fragment is later parsed in an XML context, `\u003cinjected/\u003e` becomes a real element.\n\nThis is especially surprising when `{ requireWellFormed: true }` is used, because applications may reasonably treat this mode as the stricter or safer XML serialization mode.\n\n---\n\n## Proof of Concept\n\nTested with:\n\n```text\n@xmldom/xmldom@0.9.10\nNode.js v24.18.0\nWindows 10 / PowerShell\n```\n\n```js\n'use strict';\n\nconst { DOMImplementation, XMLSerializer, DOMParser } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst doc = impl.createDocument(null, 'root', null);\nconst serializer = new XMLSerializer();\n\nfunction countInjected(fragment) {\n  try {\n    const parsed = new DOMParser().parseFromString(`\u003croot\u003e${fragment}\u003c/root\u003e`, 'application/xml');\n    return parsed.getElementsByTagName('injected').length;\n  } catch (e) {\n    return `PARSE_THROW ${e.name}: ${e.message}`;\n  }\n}\n\nfor (const name of [\n  'safe',\n  'safe; \u003cinjected/\u003e \u0026x',\n  'x\u003cinjected',\n  'x y'\n]) {\n  try {\n    const ref = doc.createEntityReference(name);\n    const xml = serializer.serializeToString(ref, { requireWellFormed: true });\n\n    console.log(`[SERIALIZED] ${JSON.stringify(name)}: ${xml}`);\n    console.log(`[INJECTED_COUNT] ${JSON.stringify(name)}: ${countInjected(xml)}`);\n  } catch (e) {\n    console.log(`[THROW] ${JSON.stringify(name)}: ${e.name}: ${e.message}`);\n  }\n}\n```\n\nObserved output:\n\n```text\n[SERIALIZED] \"safe\": \u0026safe;\n[INJECTED_COUNT] \"safe\": 0\n\n[SERIALIZED] \"safe; \u003cinjected/\u003e \u0026x\": \u0026safe; \u003cinjected/\u003e \u0026x;\n[INJECTED_COUNT] \"safe; \u003cinjected/\u003e \u0026x\": 1\n\n[SERIALIZED] \"x\u003cinjected\": \u0026x\u003cinjected;\n[INJECTED_COUNT] \"x\u003cinjected\": 0\n\n[SERIALIZED] \"x y\": \u0026x y;\n[INJECTED_COUNT] \"x y\": 0\n```\n\n---\n\n## Impact\n\nAn application that creates an `EntityReference` from attacker-controlled input and then serializes that node or XML fragment with `requireWellFormed: true` may produce XML containing attacker-controlled markup.\n\nThe impact is limited by two observations:\n\n1. The parser does not create `EntityReference` nodes from ordinary XML entity references.\n2. Appending an `EntityReference` node as an element child is rejected with a `HierarchyRequestError`.\n\nThe main affected scenario is applications that directly use `createEntityReference(name)` and then serialize the resulting node or fragment.\n\n## Fix Applied\n\nTwo complementary, non-breaking fixes.\n(1) `document.createEntityReference(name)` rejects an invalid `Name` at creation, closing the reachable creation vector by default — the opt-in serializer check alone cannot, since a later `nodeName` mutation would bypass a creation-only guard.\n(2) Under `requireWellFormed`, the serializer validates the `EntityReference` `nodeName` as a well-formed XML `Name` and throws `InvalidStateError` when it is not; a valid reference still serializes as `\u0026name;`. Both ship on both maintained versions. The `EntityReference` / `createEntityReference` docs note that under `requireWellFormed` the `nodeName` is validated as an XML `Name`, and that xmldom does not expand entities. See the [XML `Name` production](https://www.w3.org/TR/xml/#NT-Name).\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that\n\u003e serialize untrusted DOM content should audit all `serializeToString()` call sites and add it.\n\n### Proof of Concept - fixed path\n\n```js\n'use strict';\n\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst doc = impl.createDocument(null, 'root', null);\nconst serializer = new XMLSerializer();\n\n// Creation-time anchor (applied by default): an invalid XML Name is rejected at creation.\ntry {\n  doc.createEntityReference('safe; \u003cinjected/\u003e \u0026x');\n} catch (e) {\n  console.log(`${e.name}`); // rejected at creation\n}\n\n// Default path (requireWellFormed omitted): because creation now rejects an ill-formed name,\n// an ill-formed nodeName is only reachable via a post-creation mutation — and is emitted verbatim.\nconst ref = doc.createEntityReference('safe');\nref.nodeName = 'safe; \u003cinjected/\u003e \u0026x';\nconsole.log(serializer.serializeToString(ref));\n// -\u003e \u0026safe; \u003cinjected/\u003e \u0026x;   (injection present on the default path)\n\n// Opt-in path: throws on the invalid nodeName.\ntry {\n  serializer.serializeToString(ref, { requireWellFormed: true });\n} catch (e) {\n  console.log(`${e.name}`); // InvalidStateError\n}\n\n// A valid name still serializes as \u0026name; under requireWellFormed.\nconst ok = doc.createEntityReference('valid');\nconsole.log(serializer.serializeToString(ok, { requireWellFormed: true }));\n// -\u003e \u0026valid;\n```\n\n### Why the default stays verbatim\n\nThe creation-time anchor is applied by default, because it is classified non-breaking. The serializer check, by contrast, stays gated behind `{ requireWellFormed: true }`: W3C DOM Parsing's require-well-formed flag defaults to `false`, and the browser `XMLSerializer` emits the `nodeName` verbatim in that default mode, so unconditionally throwing for an ill-formed `EntityReference.nodeName` would be an unjustified breaking change — which is why the default serialization path stays verbatim.\n\n### Residual limitation\n\nThe creation vector is closed by default — the non-breaking creation-time anchor — with no further deferred work. The residual is at serialization: the default path still emits an ill-formed `nodeName` verbatim, because the serializer check is opt-in via `{ requireWellFormed: true }`.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-02T15:18:20.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-6gmq-8vp8-gcm6","https://nvd.nist.gov/vuln/detail/CVE-2026-83610","https://github.com/xmldom/xmldom/pull/1071","https://github.com/xmldom/xmldom/pull/1072","https://github.com/xmldom/xmldom/commit/4664386e4f4d99d17b416a151dbe8323e245284b","https://github.com/xmldom/xmldom/commit/6c3fb5ffeafe7901ec928ce9010988dd716c94a0","https://github.com/xmldom/xmldom/releases/tag/0.8.15","https://github.com/xmldom/xmldom/releases/tag/0.9.12","https://github.com/advisories/GHSA-6gmq-8vp8-gcm6"],"source_kind":"github","identifiers":["GHSA-6gmq-8vp8-gcm6","CVE-2026-83610"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-02T16:00:09.328Z","updated_at":"2026-10-09T10:02:56.221Z","epss_percentage":0.0059,"epss_percentile":0.46505,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02Z21xLTh2cDgtZ2NtNs4ABodd","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02Z21xLTh2cDgtZ2NtNs4ABodd","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.12","vulnerable_version_range":"\u003e= 0.9.0, \u003c= 0.9.11"},{"first_patched_version":"0.8.15","vulnerable_version_range":"\u003e= 0.7.0, \u003c= 0.8.14"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02Z21xLTh2cDgtZ2NtNs4ABodd/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0ydjM1LXc2aHEtNm1md84ABVpz","url":"https://github.com/advisories/GHSA-2v35-w6hq-6mfw","title":"xmldom: Uncontrolled recursion in XML serialization leads to DoS","description":"## Summary\n\nSeven recursive traversals in `lib/dom.js` operate without a depth limit. A sufficiently deeply\nnested DOM tree causes a `RangeError: Maximum call stack size exceeded`, crashing the application.\n\n**Reported operations:**\n- `Node.prototype.normalize()` — reported by @praveen-kv (email 2026-04-05) and @KarimTantawey (GHSA-fwmp-8wwc-qhv6, via `DOMParser.parseFromString()`)\n- `XMLSerializer.serializeToString()` — reported by @Jvr2022 (GHSA-2v35-w6hq-6mfw) and @KarimTantawey (GHSA-j2hf-fqwf-rrjf)\n\n**Additionally, discovered in research:**\n- `Element.getElementsByTagName()` / `getElementsByTagNameNS()` / `getElementsByClassName()` / `getElementById()`\n- `Node.cloneNode(true)`\n- `Document.importNode(node, true)`\n- `node.textContent` (getter)\n- `Node.isEqualNode(other)`\n\nAll seven share the same root cause: pure-JavaScript recursive tree traversal with no depth guard.\nA single deeply nested document (parsed successfully) triggers any or all of these operations.\n\n---\n\n## Details\n\n### Root cause\n\n`lib/dom.js` implements DOM tree traversals as depth-first recursive functions. Each level of\nelement nesting adds one JavaScript call frame. The JS engine's call stack is finite; once\nexhausted, a `RangeError: Maximum call stack size exceeded` is thrown. This error may not be\ncaught reliably at stack-exhaustion depths because the catch handler itself requires stack\nframes to execute — especially in async scenarios, where an uncaught `RangeError` inside a\ncallback or promise chain can crash the entire Node.js process.\n\nParsing a deeply nested document **succeeds** — the SAX parser in `lib/sax.js` is iterative.\nThe crash occurs during subsequent operations on the parsed DOM.\n\n### `Node.prototype.normalize()` — reported by @praveen-kv\n\n[`lib/dom.js:1296–1308`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1296-L1308) (main):\n\n```js\nnormalize: function () {\n    var child = this.firstChild;\n    while (child) {\n        var next = child.nextSibling;\n        if (next \u0026\u0026 next.nodeType == TEXT_NODE \u0026\u0026 child.nodeType == TEXT_NODE) {\n            this.removeChild(next);\n            child.appendData(next.data);\n        } else {\n            child.normalize();   // recursive call — no depth guard\n            child = next;\n        }\n    }\n},\n```\n\nCrash threshold (Node.js 18, default stack): ~10,000 levels.\n\n### `XMLSerializer.serializeToString()` — reported by @Jvr2022\n\n[`lib/dom.js:2790–2974`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L2790-L2974) (main):\nThe internal `serializeToString` worker recurses into child nodes at four call sites, each\npassing a `visibleNamespaces.slice()` copy. The per-frame allocation causes earlier stack\nexhaustion than `normalize()`.\n\nCrash threshold (Node.js 18, default stack): ~5,000 levels.\n\n### Additional recursive entry points\n\nAll five crash at ~10,000 levels on Node.js 18.\n\n| Function                    | Definition                                                                                                           | Public API entry point(s)                                                                            | Crash depth (Node.js 18) |\n|-----------------------------|----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------|\n| `_visitNode`                | [`lib/dom.js:1529`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1529) | `getElementsByTagName()`, `getElementsByTagNameNS()`, `getElementsByClassName()`, `getElementById()` | ~10,000 levels           |\n| `cloneNode` (module fn)     | [`lib/dom.js:3037`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L3037) | `Node.prototype.cloneNode(true)`                                                                     | ~10,000 levels           |\n| `importNode` (module fn)    | [`lib/dom.js:2975`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L2975) | `Document.prototype.importNode(node, true)`                                                          | ~10,000 levels           |\n| `getTextContent` (inner fn) | [`lib/dom.js:3130`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L3130) | `node.textContent` (getter)                                                                          | ~10,000 levels           |\n| `isEqualNode`               | [`lib/dom.js:1120`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1120) | `Node.prototype.isEqualNode(other)`                                                                  | ~10,000 levels           |\n\nBoth active branches (`main` and `release-0.8.x`) are identically affected. The unscoped `xmldom`\npackage (≤ 0.6.0) carries the same recursive patterns from its initial commit.\n\n### Browser behavior\n\nTested with Chromium 147 (Playwright headless). Chromium's native C++ implementations of all\nseven DOM methods are **iterative** — they traverse the DOM without consuming JS call stack frames.\nAll seven succeed at depths up to 20,000 without any crash.\n\nWhen `@xmldom/xmldom` is bundled and run in a browser context the same recursive JS code executes\nunder the browser's V8 stack limit (~12,000–13,000 frames). The crash thresholds are similar to\nthose observed on Node.js 18 (~5,000 for `serializeToString`, ~10,000 for the remaining six).\n\nThe vulnerability is specific to xmldom's pure-JavaScript recursive implementation, not an\ninherent property of the DOM operations.\n\n---\n\n## PoC\n\n### `normalize()` (from @praveen-kv report, 2026-04-05)\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom');\n\nfunction generateNestedXML(depth) {\n    return '\u003croot\u003e' + '\u003ca\u003e'.repeat(depth) + 'text' + '\u003c/a\u003e'.repeat(depth) + '\u003c/root\u003e';\n}\n\nconst doc = new DOMParser().parseFromString(generateNestedXML(10000), 'text/xml');\ndoc.documentElement.normalize();\n// RangeError: Maximum call stack size exceeded\n```\n\n### `XMLSerializer.serializeToString()` (from GHSA-2v35-w6hq-6mfw)\n\n```js\nconst { DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst depth = 5000;\nconst xml = '\u003ca\u003e'.repeat(depth) + '\u003c/a\u003e'.repeat(depth);\nconst doc = new DOMParser().parseFromString(xml, 'text/xml');\nnew XMLSerializer().serializeToString(doc);\n// RangeError: Maximum call stack size exceeded\n```\n\nThe other methods have been verified using similar pocs.\n\n---\n\n## Impact\n\nAny service that accepts attacker-controlled XML and subsequently calls any of the seven affected\nDOM operations can be forced into a reliable denial of service with a single crafted payload.\n\nThe immediate result is an uncaught `RangeError` and failed request processing. In deployments\nwhere uncaught exceptions terminate the worker or process, the impact can extend beyond a single\nrequest and disrupt service availability more broadly.\n\nNo authentication, special options, or invalid XML is required. A valid, deeply nested XML\ndocument is enough.\n\n---\n\n## Disclosure\n\nThe `normalize()` vector was publicly disclosed at 2026-04-06T11:25:07Z via\n[xmldom/xmldom#987](https://github.com/xmldom/xmldom/pull/987) (closed without merge).\n`serializeToString()` and the five additional recursive entry points were not mentioned in that PR.\n\n---\n\n## Fix Applied\n\nAll seven affected traversals have been converted from recursive to iterative implementations, eliminating call-stack consumption on deep trees.\n\n### `walkDOM` utility\n\nA new `walkDOM(node, context, callbacks)` utility is introduced. It traverses the subtree rooted at `node` in depth-first order using an explicit JavaScript array as a stack, consuming heap memory instead of call-stack frames. `context` is an arbitrary value threaded through the walk — each `callbacks.enter(node, context)` call returns the context to pass to that node's children, enabling per-branch state (e.g. namespace snapshots in the serializer). `callbacks.exit(node, context)` (optional) is called in post-order after all children have been visited.\n\nThe following six operations are re-implemented on top of `walkDOM`:\n\n| Operation | Public entry point(s) |\n|---|---|\n| `_visitNode` helper | `getElementsByTagName()`, `getElementsByTagNameNS()`, `getElementsByClassName()`, `getElementById()` |\n| `getTextContent` inner function | `node.textContent` getter |\n| `cloneNode` module function | `Node.prototype.cloneNode(true)` |\n| `importNode` module function | `Document.prototype.importNode(node, true)` |\n| `serializeToString` worker | `XMLSerializer.prototype.serializeToString()`, `Node.prototype.toString()`, `NodeList.prototype.toString()` |\n| `normalize` | `Node.prototype.normalize()` |\n\n`normalize` uses `walkDOM` with a `null` context and an `enter` callback that merges adjacent Text children of the current node before `walkDOM` reads and queues those children — so the surviving post-merge children are what the walker descends into.\n\n### Custom iterative loop for `isEqualNode`\n\nOne function cannot use `walkDOM`:\n\n**`Node.prototype.isEqualNode(other)`** (0.9.x only; absent from 0.8.x) compares two trees in parallel. It maintains an explicit stack of `{node, other}` node pairs — one node from each tree — which cannot be expressed with `walkDOM`'s single-tree visitor.\n\n### After the fix\n\nAll seven entry points succeed on trees of arbitrary depth without throwing `RangeError`. The original PoCs still demonstrate the vulnerability on unpatched versions and confirm the fix on patched versions.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-04-22T20:23:57.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-2v35-w6hq-6mfw","https://github.com/xmldom/xmldom/commit/17678a2a73ecbd1a2da90f3d47dc23da9cef81aa","https://github.com/xmldom/xmldom/commit/291257493cb0eb6980eda83b162a9c4e6d7d2597","https://github.com/xmldom/xmldom/commit/2d6d6916ed8a4c223db1f6d7560ab4544c465b0f","https://github.com/xmldom/xmldom/commit/430357c7b6333108856e917bf2367afe5ceb6f8a","https://github.com/xmldom/xmldom/commit/4845ef109221df0890825de2822fbe77afba3afe","https://github.com/xmldom/xmldom/commit/8834218c85ac2a4d757b9587c9028e67c2f7b6c3","https://github.com/xmldom/xmldom/commit/8b7cfd1491314abdc347261921d7334ff15f7112","https://github.com/xmldom/xmldom/commit/b0620383abc1df067f3ce1014c43ae1bc1161eeb","https://github.com/xmldom/xmldom/commit/e6edcab6bef5bcdba0b220bb35442aa72f452b84","https://github.com/xmldom/xmldom/releases/tag/0.8.13","https://github.com/xmldom/xmldom/releases/tag/0.9.10","https://nvd.nist.gov/vuln/detail/CVE-2026-41673","https://github.com/advisories/GHSA-2v35-w6hq-6mfw"],"source_kind":"github","identifiers":["GHSA-2v35-w6hq-6mfw","CVE-2026-41673"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-22T21:00:09.478Z","updated_at":"2026-10-09T10:07:52.442Z","epss_percentage":0.00882,"epss_percentile":0.57506,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0ydjM1LXc2aHEtNm1md84ABVpz","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0ydjM1LXc2aHEtNm1md84ABVpz","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.10","vulnerable_version_range":"\u003e= 0.9.0, \u003c 0.9.10"},{"first_patched_version":"0.8.13","vulnerable_version_range":"\u003c 0.8.13"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0ydjM1LXc2aHEtNm1md84ABVpz/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mNnd3LTNnZ3AtZnI4aM4ABVpy","url":"https://github.com/advisories/GHSA-f6ww-3ggp-fr8h","title":"xmldom has XML injection through unvalidated DocumentType serialization","description":"## Summary\n\nThe package serializes `DocumentType` node fields (`internalSubset`, `publicId`, `systemId`) verbatim\nwithout any escaping or validation. When these fields are set programmatically to attacker-controlled\nstrings, `XMLSerializer.serializeToString` can produce output where the DOCTYPE declaration is\nterminated early and arbitrary markup appears outside it.\n\n---\n\n## Details\n\n`DOMImplementation.createDocumentType(qualifiedName, publicId, systemId, internalSubset)` validates\nonly `qualifiedName` against the XML QName production. The remaining three arguments are stored\nas-is with no validation.\n\nThe XMLSerializer emits `DocumentType` nodes as:\n\n```\n\u003c!DOCTYPE name[ PUBLIC pubid][ SYSTEM sysid][ [internalSubset]]\u003e\n```\n\nAll fields are pushed into the output buffer verbatim — no escaping, no quoting added.\n\n**`internalSubset` injection:** The serializer wraps `internalSubset` with ` [` and `]`. A value\ncontaining `]\u003e` closes the internal subset and the DOCTYPE declaration at the injection point.\nAny content after `]\u003e` in `internalSubset` appears outside the DOCTYPE in the serialized output as\nraw XML markup. Reported by @TharVid (GHSA-f6ww-3ggp-fr8h). Affected: `@xmldom/xmldom` ≥ 0.9.0\nvia `createDocumentType` API; 0.8.x only via direct property write.\n\n**`publicId` injection:** The serializer emits `publicId` verbatim after `PUBLIC` with no\nquoting added. A value containing an injected system identifier (e.g.,\n`\"pubid\" SYSTEM \"evil\"`) breaks the intended quoting context, injecting a fake SYSTEM entry\ninto the serialized DOCTYPE declaration. Identified during internal security research. Affected:\nboth branches, all versions back to 0.1.0.\n\n**`systemId` injection:** The serializer emits `systemId` verbatim. A value containing `\u003e`\nterminates the DOCTYPE declaration early; content after `\u003e` appears as raw XML markup outside\nthe DOCTYPE context. Identified during internal security research. Affected: both branches, all\nversions back to 0.1.0.\n\nThe parse path is safe: the SAX parser enforces the `PubidLiteral` and `SystemLiteral` grammar\nproductions, which exclude the relevant characters, and the internal subset parser only accepts a\nsubset it can structurally validate. The vulnerability is reachable only through programmatic\n`createDocumentType` calls with attacker-controlled arguments.\n\n---\n\n## Affected code\n\n**`lib/dom.js` — `createDocumentType` (lines 898–910):**\n\n```js\ncreateDocumentType: function (qualifiedName, publicId, systemId, internalSubset) {\n    validateQualifiedName(qualifiedName);          // only qualifiedName is validated\n    var node = new DocumentType(PDC);\n    node.name = qualifiedName;\n    node.nodeName = qualifiedName;\n    node.publicId = publicId || '';               // stored verbatim\n    node.systemId = systemId || '';               // stored verbatim\n    node.internalSubset = internalSubset || '';   // stored verbatim\n    node.childNodes = new NodeList();\n    return node;\n},\n```\n\n**`lib/dom.js` — serializer DOCTYPE case (lines 2948–2964):**\n\n```js\ncase DOCUMENT_TYPE_NODE:\n    var pubid = node.publicId;\n    var sysid = node.systemId;\n    buf.push(g.DOCTYPE_DECL_START, ' ', node.name);\n    if (pubid) {\n        buf.push(' ', g.PUBLIC, ' ', pubid);\n        if (sysid \u0026\u0026 sysid !== '.') {\n            buf.push(' ', sysid);\n        }\n    } else if (sysid \u0026\u0026 sysid !== '.') {\n        buf.push(' ', g.SYSTEM, ' ', sysid);\n    }\n    if (node.internalSubset) {\n        buf.push(' [', node.internalSubset, ']');  // internalSubset emitted verbatim\n    }\n    buf.push('\u003e');\n    return;\n```\n\n---\n\n## PoC\n\n### internalSubset injection\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst doctype = impl.createDocumentType(\n    'root',\n    '',\n    '',\n    ']\u003e\u003cinjected/\u003e\u003c![CDATA['\n);\nconst doc = impl.createDocument(null, 'root', doctype);\nconst xml = new XMLSerializer().serializeToString(doc);\nconsole.log(xml);\n// \u003c!DOCTYPE root []\u003e\u003cinjected/\u003e\u003c![CDATA[]\u003e\u003croot/\u003e\n//                   ^^^^^^^^^^  injected element outside DOCTYPE\n```\n\n### publicId quoting context break\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst doctype = impl.createDocumentType(\n    'root',\n    '\"injected PUBLIC_ID\" SYSTEM \"evil\"',\n    '',\n    ''\n);\nconst doc = impl.createDocument(null, 'root', doctype);\nconsole.log(new XMLSerializer().serializeToString(doc));\n// \u003c!DOCTYPE root PUBLIC \"injected PUBLIC_ID\" SYSTEM \"evil\"\u003e\u003croot/\u003e\n// quoting context broken — SYSTEM entry injected\n```\n\n### systemId injection\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst impl = new DOMImplementation();\nconst doctype = impl.createDocumentType(\n    'root',\n    '',\n    '\"sysid\"\u003e\u003cinjected attr=\"pwn\"/\u003e',\n    ''\n);\nconst doc = impl.createDocument(null, 'root', doctype);\nconsole.log(new XMLSerializer().serializeToString(doc));\n// \u003c!DOCTYPE root SYSTEM \"sysid\"\u003e\u003cinjected attr=\"pwn\"/\u003e\u003e\u003croot/\u003e\n// \u003e in sysid closes DOCTYPE early; \u003cinjected/\u003e appears as sibling element\n```\n\n---\n\n## Impact\n\nAn application that programmatically constructs `DocumentType` nodes from user-controlled data and\nthen serializes the document can emit a DOCTYPE declaration where the internal subset is closed\nearly or where injected SYSTEM entities or other declarations appear in the serialized output.\n\nDownstream XML parsers that re-parse the serialized output and expand entities from the injected\nDOCTYPE declarations may be susceptible to XXE-class attacks if they enable entity expansion.\n\n---\n\n## Fix Applied\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that pass\n\u003e untrusted data to `createDocumentType()` or write untrusted values directly to a\n\u003e `DocumentType` node's `publicId`, `systemId`, or `internalSubset` properties should audit\n\u003e all `serializeToString()` call sites and add the option.\n\n`XMLSerializer.serializeToString()` now accepts an options object as a second argument. When `{ requireWellFormed: true }` is passed, the serializer validates the `DocumentType` node's `publicId`, `systemId`, and `internalSubset` fields before emitting the DOCTYPE declaration and throws `InvalidStateError` if any field contains an injection sequence:\n\n- **`publicId`**: throws if non-empty and does not match the XML `PubidLiteral` production (XML 1.0 [12])\n- **`systemId`**: throws if non-empty and does not match the XML `SystemLiteral` production (XML 1.0 [11])\n- **`internalSubset`**: throws if it contains `]\u003e` (which closes the internal subset and DOCTYPE declaration early)\n\nAll three checks apply regardless of how the invalid value entered the node — whether via `createDocumentType` arguments or a subsequent direct property write.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\nconst impl = new DOMImplementation();\n\n// internalSubset injection\nconst dt1 = impl.createDocumentType('root', '', '', ']\u003e\u003cinjected/\u003e\u003c![CDATA[');\nconst doc1 = impl.createDocument(null, 'root', dt1);\n\n// Default (unchanged): verbatim — injection present\nconsole.log(new XMLSerializer().serializeToString(doc1));\n// \u003c!DOCTYPE root []\u003e\u003cinjected/\u003e\u003c![CDATA[]\u003e\u003croot/\u003e\n\n// Opt-in guard: throws InvalidStateError\ntry {\n  new XMLSerializer().serializeToString(doc1, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name, e.message);\n  // InvalidStateError: DocumentType internalSubset contains \"]\u003e\"\n}\n```\n\nThe guard also covers post-creation property writes:\n\n```js\nconst dt2 = impl.createDocumentType('root', '', '');\ndt2.systemId = '\"sysid\"\u003e\u003cinjected attr=\"pwn\"/\u003e';\nconst doc2 = impl.createDocument(null, 'root', dt2);\nnew XMLSerializer().serializeToString(doc2, { requireWellFormed: true });\n// InvalidStateError: DocumentType systemId is not a valid SystemLiteral\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec §3.2.1.3 defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the spec permits verbatim serialization of DOCTYPE fields. Unconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in `requireWellFormed: true` flag allows applications that require injection safety to enable strict mode without breaking existing deployments.\n\n### Residual limitation\n\n`createDocumentType(qualifiedName, publicId, systemId[, internalSubset])` does not validate `publicId`, `systemId`, or `internalSubset` at creation time. This creation-time validation is a breaking change and is deferred to a future breaking release.\n\nWhen the default serialization path is used (without `requireWellFormed: true`), all three fields are still emitted verbatim. Applications that do not pass `requireWellFormed: true` remain exposed.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-04-22T20:19:12.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-f6ww-3ggp-fr8h","https://github.com/xmldom/xmldom/commit/372008f9ae0e20fd69f761c7b79e202598267314","https://github.com/xmldom/xmldom/releases/tag/0.8.13","https://github.com/xmldom/xmldom/releases/tag/0.9.10","https://nvd.nist.gov/vuln/detail/CVE-2026-41674","https://github.com/advisories/GHSA-f6ww-3ggp-fr8h"],"source_kind":"github","identifiers":["GHSA-f6ww-3ggp-fr8h","CVE-2026-41674"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-22T21:00:09.478Z","updated_at":"2026-10-09T10:07:52.443Z","epss_percentage":0.0065,"epss_percentile":0.49569,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mNnd3LTNnZ3AtZnI4aM4ABVpy","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mNnd3LTNnZ3AtZnI4aM4ABVpy","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.10","vulnerable_version_range":"\u003e= 0.9.0, \u003c 0.9.10"},{"first_patched_version":"0.8.13","vulnerable_version_range":"\u003c 0.8.13"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mNnd3LTNnZ3AtZnI4aM4ABVpy/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14NndmLWYzcHgtd2NxeM4ABVpx","url":"https://github.com/advisories/GHSA-x6wf-f3px-wcqx","title":"xmldom has XML node injection through unvalidated processing instruction serialization","description":"## Summary\n\nThe package allows attacker-controlled processing instruction data to be serialized into XML without validating or neutralizing the PI-closing sequence `?\u003e`. As a result, an attacker can terminate the processing instruction early and inject arbitrary XML nodes into the serialized output.\n\n---\n\n## Details\n\nThe issue is in the DOM construction and serialization flow for processing instruction nodes.\n\nWhen `createProcessingInstruction(target, data)` is called, the supplied `data` string is stored directly on the node without validation. Later, when the document is serialized, the serializer writes PI nodes by concatenating `\u003c?`, the target, a space, `node.data`, and `?\u003e` directly.\n\nThat behavior is unsafe because processing instructions are a syntax-sensitive context. The closing delimiter `?\u003e` terminates the PI. If attacker-controlled input contains `?\u003e`, the serializer does not preserve it as literal PI content. Instead, it emits output where the remainder of the payload is treated as live XML markup.\n\nThe same class of vulnerability was previously addressed for CDATA sections (GHSA-wh4c-j3r5-mjhp / CVE-2026-34601), where `]]\u003e` in CDATA data was handled by splitting. The serializer applies no equivalent protection to processing instruction data.\n\n---\n\n## Affected code\n\n**`lib/dom.js` — `createProcessingInstruction` (lines 2240–2246):**\n\n```js\ncreateProcessingInstruction: function (target, data) {\n    var node = new ProcessingInstruction(PDC);\n    node.ownerDocument = this;\n    node.childNodes = new NodeList();\n    node.nodeName = node.target = target;\n    node.nodeValue = node.data = data;\n    return node;\n},\n```\n\nNo validation is performed on `data`. Any string including `?\u003e` is stored as-is.\n\n**`lib/dom.js` — serializer PI case (line 2966):**\n\n```js\ncase PROCESSING_INSTRUCTION_NODE:\n    return buf.push('\u003c?', node.target, ' ', node.data, '?\u003e');\n```\n\n`node.data` is emitted verbatim. If it contains `?\u003e`, that sequence terminates the PI in the output\nstream and the remainder appears as active XML markup.\n\n**Contrast — CDATA (line 2945, patched):**\n\n```js\ncase CDATA_SECTION_NODE:\n    return buf.push(g.CDATA_START, node.data.replace(/]]\u003e/g, ']]]]\u003e\u003c![CDATA[\u003e'), g.CDATA_END);\n```\n\n---\n\n## PoC\n\n### Minimal (from @tlsbollei report, 2026-04-01)\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'r', null);\ndoc.documentElement.appendChild(\n    doc.createProcessingInstruction('a', '?\u003e\u003cz/\u003e\u003c?q ')\n);\nconsole.log(new XMLSerializer().serializeToString(doc));\n// \u003cr\u003e\u003c?a ?\u003e\u003cz/\u003e\u003c?q ?\u003e\u003c/r\u003e\n//          ^^^^ injected \u003cz/\u003e element is active markup\n```\n\n### With re-parse verification (from @tlsbollei report)\n\n```js\nconst assert = require('assert');\nconst { DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMParser().parseFromString('\u003cr/\u003e', 'application/xml');\ndoc.documentElement.appendChild(doc.createProcessingInstruction('a', '?\u003e\u003cz/\u003e\u003c?q '));\nconst xml = new XMLSerializer().serializeToString(doc);\nassert.strictEqual(new DOMParser().parseFromString(xml, 'application/xml')\n    .getElementsByTagName('z').length, 1); // passes — z is a real element\n```\n\n---\n\n## Impact\n\nAn application that uses the package to build XML from untrusted input can be made to emit attacker-controlled elements outside the intended PI boundary. That allows the attacker to alter the meaning and structure of generated XML documents.\n\nIn practice, this can affect any workflow that generates XML and then stores it, forwards it, signs it, or hands it to another parser. Realistic targets include XML-based configuration, policy documents, and message formats where downstream consumers trust the serialized structure.\n\nAs noted by @tlsbollei: this is the same delimiter-driven XML injection bug class previously addressed by GHSA-wh4c-j3r5-mjhp for `createCDATASection()`. Fixing CDATA while leaving PI creation and PI serialization unguarded leaves the same standards-constrained issue open for another node type.\n\n---\n\n## Disclosure\n\nThis vulnerability was publicly disclosed at 2026-04-06T11:25:07Z via\n[xmldom/xmldom#987](https://github.com/xmldom/xmldom/pull/987), which was subsequently closed\nwithout being merged.\n\n---\n\n## Fix Applied\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that pass\n\u003e untrusted data to `createProcessingInstruction()` or mutate PI nodes with untrusted input\n\u003e (via `.data =` or `CharacterData` mutation methods) should audit all `serializeToString()`\n\u003e call sites and add the option.\n\n`XMLSerializer.serializeToString()` now accepts an options object as a second argument. When `{ requireWellFormed: true }` is passed, the serializer throws `InvalidStateError` before emitting any ProcessingInstruction node whose `.data` contains `?\u003e`. This check applies regardless of how `?\u003e` entered the node — whether via `createProcessingInstruction` directly or a subsequent mutation (`.data =`, `CharacterData` methods).\n\nOn `@xmldom/xmldom` ≥ 0.9.10, the serializer additionally applies the full W3C DOM Parsing §3.2.1.7 checks when `requireWellFormed: true`:\n\n1. **Target check**: throws `InvalidStateError` if the PI target contains a `:` character or is an ASCII case-insensitive match for `\"xml\"`.\n2. **Data Char check**: throws `InvalidStateError` if the PI data contains characters outside the XML Char production.\n3. **Data sequence check**: throws `InvalidStateError` if the PI data contains `?\u003e`.\n\nOn `@xmldom/xmldom` ≥ 0.8.13 (LTS), only the `?\u003e` data check (check 3) is applied. The target and XML Char checks are not included in the LTS fix.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'r', null);\ndoc.documentElement.appendChild(doc.createProcessingInstruction('a', '?\u003e\u003cz/\u003e\u003c?q '));\n\n// Default (unchanged): verbatim — injection present\nconst unsafe = new XMLSerializer().serializeToString(doc);\nconsole.log(unsafe);\n// \u003cr\u003e\u003c?a ?\u003e\u003cz/\u003e\u003c?q ?\u003e\u003c/r\u003e\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n  new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name, e.message);\n  // InvalidStateError: The ProcessingInstruction data contains \"?\u003e\"\n}\n```\n\nThe guard catches `?\u003e` regardless of when it was introduced:\n\n```js\n// Post-creation mutation: also caught at serialization time\nconst pi = doc.createProcessingInstruction('target', 'safe data');\ndoc.documentElement.appendChild(pi);\npi.data = 'safe?\u003e\u003cinjected/\u003e';\nnew XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n// InvalidStateError: The ProcessingInstruction data contains \"?\u003e\"\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec §3.2.1.3 defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the spec explicitly permits serializing PI data verbatim. This matches browser behavior: Chrome, Firefox, and Safari all emit `?\u003e` in PI data verbatim by default without error.\n\nUnconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in `requireWellFormed: true` flag allows applications that require injection safety to enable strict mode without breaking existing code.\n\n### Residual limitation\n\n`createProcessingInstruction(target, data)` does not validate `data` at creation time. The WHATWG DOM spec (§4.5 step 2) mandates an `InvalidCharacterError` when `data` contains `?\u003e`; enforcing this check unconditionally at creation time is a breaking change and is deferred to a future breaking release.\n\nWhen the default serialization path is used (without `requireWellFormed: true`), PI data containing `?\u003e` is still emitted verbatim. Applications that do not pass `requireWellFormed: true` remain exposed.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-04-22T20:17:58.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-x6wf-f3px-wcqx","https://github.com/xmldom/xmldom/commit/7207a4b0e0bcc228868075ed991665ef9f73b1c2","https://github.com/xmldom/xmldom/releases/tag/0.8.13","https://github.com/xmldom/xmldom/releases/tag/0.9.10","https://nvd.nist.gov/vuln/detail/CVE-2026-41675","https://github.com/advisories/GHSA-x6wf-f3px-wcqx"],"source_kind":"github","identifiers":["GHSA-x6wf-f3px-wcqx","CVE-2026-41675"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-22T21:00:09.478Z","updated_at":"2026-10-09T10:07:52.443Z","epss_percentage":0.00633,"epss_percentile":0.48539,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14NndmLWYzcHgtd2NxeM4ABVpx","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14NndmLWYzcHgtd2NxeM4ABVpx","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.10","vulnerable_version_range":"\u003e= 0.9.0, \u003c 0.9.10"},{"first_patched_version":"0.8.13","vulnerable_version_range":"\u003c 0.8.13"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14NndmLWYzcHgtd2NxeM4ABVpx/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1qNzU5LWo0NHctN2ZyOM4ABVpw","url":"https://github.com/advisories/GHSA-j759-j44w-7fr8","title":"xmldom has XML node injection through unvalidated comment serialization","description":"## Summary\n\nThe package allows attacker-controlled comment content to be serialized into XML without validating or neutralizing comment breaking sequences. As a result, an attacker can terminate the comment early and inject arbitrary XML nodes into the serialized output.\n\n---\n\n## Details\n\nThe issue is in the DOM construction and serialization flow for comment nodes.\n\nWhen `createComment(data)` is called, the supplied string is stored as comment data through the generic character-data handling path. That content is kept as-is. Later, when the document is serialized, the serializer writes comment nodes by concatenating the XML comment delimiters with the stored `node.data` value directly.\n\nThat behavior is unsafe because XML comments are a syntax-sensitive context. If attacker-controlled input contains a sequence that closes the comment, the serializer does not preserve it as literal comment text. Instead, it emits output where the remainder of the payload is treated as live XML markup.\n\nThis is a real injection bug, not a formatting issue. The serializer already applies context-aware handling in other places, such as escaping text nodes and rewriting unsafe CDATA terminators. Comment content does not receive equivalent treatment. Because of that gap, untrusted data can break out of the comment boundary and modify the structure of the final XML document.\n\n---\n\n## PoC\n\n```js\nconst { DOMImplementation, DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\n\ndoc.documentElement.appendChild(\n  doc.createComment('--\u003e\u003cinjected attr=\"1\"/\u003e\u003c!--')\n);\n\nconst xml = new XMLSerializer().serializeToString(doc);\nconsole.log(xml);\n// \u003croot\u003e\u003c!----\u003e\u003cinjected attr=\"1\"/\u003e\u003c!----\u003e\u003c/root\u003e\n\nconst reparsed = new DOMParser().parseFromString(xml, 'text/xml');\nconsole.log(reparsed.documentElement.childNodes.item(1).nodeName);\n// injected\n```\n\n---\n\n## Impact\n\nAn application that uses the package to build XML from untrusted input can be made to emit attacker-controlled elements outside the intended comment boundary. That allows the attacker to alter the meaning and structure of generated XML documents.\n\nIn practice, this can affect any workflow that generates XML and then stores it, forwards it, signs it, or hands it to another parser. Realistic targets include XML-based configuration, policy documents, and message formats where downstream consumers trust the serialized structure.\n\n---\n\n## Disclosure\n\nThis vulnerability was publicly disclosed at 2026-04-06T11:25:07Z via [xmldom/xmldom#987](https://github.com/xmldom/xmldom/pull/987), which was subsequently closed without being merged.\n\n---\n\n## Fix Applied\n\n\u003e **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that pass\n\u003e untrusted data to `createComment()` or mutate comment nodes with untrusted input (via\n\u003e `appendData`, `insertData`, `replaceData`, `.data =`, or `.textContent =`) should audit all\n\u003e `serializeToString()` call sites and add the option.\n\n`XMLSerializer.serializeToString()` now accepts an options object as a second argument. When `{ requireWellFormed: true }` is passed, the serializer throws `InvalidStateError` before emitting a Comment node whose `.data` would produce malformed XML.\n\nOn `@xmldom/xmldom` ≥ 0.9.10, the full W3C DOM Parsing §3.2.1.4 check is applied: throws if `.data` contains `--` anywhere, ends with `-`, or contains characters outside the XML Char production.\n\nOn `@xmldom/xmldom` ≥ 0.8.13 (LTS), only the `--\u003e` injection sequence is checked. The `0.8.x` SAX parser accepts comments containing `--` (without `\u003e`), so throwing on bare `--` would break a previously-working round-trip on that branch. The `--\u003e` check is sufficient to prevent injection.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\ndoc.documentElement.appendChild(doc.createComment('--\u003e\u003cinjected attr=\"1\"/\u003e\u003c!--'));\n\n// Default (unchanged): verbatim — injection present\nconst unsafe = new XMLSerializer().serializeToString(doc);\nconsole.log(unsafe);\n// \u003croot\u003e\u003c!----\u003e\u003cinjected attr=\"1\"/\u003e\u003c!----\u003e\u003c/root\u003e\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n  new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n  console.log(e.name, e.message);\n  // InvalidStateError: The comment node data contains \"--\" or ends with \"-\"  (0.9.x)\n  // InvalidStateError: The comment node data contains \"--\u003e\"  (0.8.x — only --\u003e is checked)\n}\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec §3.2.1.4 defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the spec explicitly permits serializing ill-formed comment content verbatim — this is also the behavior of browser implementations (Chrome, Firefox, Safari): `new XMLSerializer().serializeToString(doc)` produces the injection sequence without error in all major browsers.\n\nUnconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in `requireWellFormed: true` flag allows applications that require injection safety to enable strict mode without breaking existing deployments.\n\n### Residual limitation\n\nThe fix operates at serialization time only. There is no creation-time check in `createComment` — the spec does not require one for comment data. Any path that leads to a Comment node with `--` in its data (`createComment`, `appendData`, `.data =`, etc.) produces a node that serializes safely only when `{ requireWellFormed: true }` is passed to `serializeToString`.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-04-22T20:16:07.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-j759-j44w-7fr8","https://github.com/xmldom/xmldom/pull/987","https://github.com/xmldom/xmldom/commit/b397540889086da868c30c366ad5c220d1a750c7","https://github.com/xmldom/xmldom/commit/fda7cc313de30243fea35cada64e0bb12099c2a1","https://github.com/xmldom/xmldom/releases/tag/0.8.13","https://github.com/xmldom/xmldom/releases/tag/0.9.10","https://nvd.nist.gov/vuln/detail/CVE-2026-41672","https://github.com/advisories/GHSA-j759-j44w-7fr8"],"source_kind":"github","identifiers":["GHSA-j759-j44w-7fr8","CVE-2026-41672"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-22T21:00:09.478Z","updated_at":"2026-10-09T10:07:52.443Z","epss_percentage":0.0065,"epss_percentile":0.49569,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qNzU5LWo0NHctN2ZyOM4ABVpw","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qNzU5LWo0NHctN2ZyOM4ABVpw","packages":[{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"},{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.10","vulnerable_version_range":"\u003e= 0.9.0, \u003c 0.9.10"},{"first_patched_version":"0.8.13","vulnerable_version_range":"\u003c 0.8.13"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qNzU5LWo0NHctN2ZyOM4ABVpw/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS13aDRjLWozcjUtbWpocM4ABUh5","url":"https://github.com/advisories/GHSA-wh4c-j3r5-mjhp","title":"xmldom: XML injection via unsafe CDATA serialization allows attacker-controlled markup insertion","description":"## Summary\n\n`@xmldom/xmldom` allows attacker-controlled strings containing the CDATA terminator `]]\u003e` to be inserted into a `CDATASection` node. During serialization, `XMLSerializer` emitted the CDATA content verbatim without rejecting or safely splitting the terminator. As a result, data intended to remain text-only became **active XML markup** in the serialized output, enabling XML structure\ninjection and downstream business-logic manipulation.\n\nThe sequence `]]\u003e` is not allowed inside CDATA content and must be rejected or safely handled during serialization. ([MDN Web Docs](https://developer.mozilla.org/))\n\n### Attack surface\n\n`Document.createCDATASection(data)` is the most direct entry point, but it is not the only one. The WHATWG DOM spec intentionally does not validate `]]\u003e` in mutation methods — only `createCDATASection` carries that guard. The following paths therefore also allow `]]\u003e` to enter a CDATASection node and reach the serializer:\n\n- `CharacterData.appendData()`\n- `CharacterData.replaceData()`\n- `CharacterData.insertData()`\n- Direct assignment to `.data`\n- Direct assignment to `.textContent`\n\n(Note: assigning to `.nodeValue` does **not** update `.data` in this implementation — the serializer reads `.data` directly — so `.nodeValue` is not an exploitable path.)\n\n### Parse path\n\nParsing XML that contains a CDATA section is **not** affected. The SAX parser's non-greedy `CDSect` regex stops at the first `]]\u003e`, so parsed CDATA data never contains the terminator.\n\n---\n\n## Impact\n\nIf an application uses `xmldom` to generate \"trusted\" XML documents that embed **untrusted user input** inside CDATA (a common pattern in exports, feeds, SOAP/XML integrations, etc.), an attacker can inject additional XML elements/attributes into the generated document.\n\nThis can lead to:\n\n- Integrity violation of generated XML documents.\n- Business-logic injection in downstream consumers (e.g., injecting `\u003capproved\u003etrue\u003c/approved\u003e`,  `\u003crole\u003eadmin\u003c/role\u003e`, workflow flags, or other security-relevant elements).\n- Unexpected privilege/workflow decisions if downstream logic assumes injected nodes cannot appear.\n\nThis issue does **not** require malformed parsers or browser behavior; it is caused by serialization producing attacker-influenced XML markup.\n\n---\n\n## Root Cause (with file + line numbers)\n\n**File:** `lib/dom.js`\n\n### 1. No validation in `createCDATASection`\n\n`createCDATASection: function (data)` accepts any string and appends it directly.\n\n- **Lines 2216–2221** (0.9.8)\n\n### 2. Unsafe CDATA serialization\n\nSerializer prints CDATA sections as:\n\n```\n\u003c![CDATA[ + node.data + ]]\u003e\n```\n\nwithout handling `]]\u003e` in the data.\n\n- **Lines 2919–2920** (0.9.8)\n\nBecause CDATA content is emitted verbatim, an embedded `]]\u003e` closes the CDATA section early and the remainder of the attacker-controlled payload is interpreted as markup in the serialized XML.\n\n---\n\n## Proof of Concept — Fix A: `createCDATASection` now throws\n\nOn patched versions, passing `]]\u003e` directly to `createCDATASection` throws `InvalidCharacterError` instead of silently accepting the payload:\n\n```js\nconst { DOMImplementation } = require('./lib');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\ntry {\n  doc.createCDATASection('SAFE]]\u003e\u003cinjected attr=\"pwn\"/\u003e');\n  console.log('VULNERABLE — no error thrown');\n} catch (e) {\n  console.log('FIXED — threw:', e.name); // InvalidCharacterError\n}\n```\n\nExpected output on patched versions:\n\n```\nFIXED — threw: InvalidCharacterError\n```\n\n---\n\n## Proof of Concept — Fix B: mutation vector now safe\n\nOn patched versions, injecting `]]\u003e` via a mutation method (`appendData`, `replaceData`, `.data =`, `.textContent =`) no longer produces injectable output. The serializer splits the terminator so the result round-trips as safe text:\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('./lib');\nconst { DOMParser } = require('./lib');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\n\n// Start with safe data, then mutate to include the terminator\nconst cdata = doc.createCDATASection('safe');\ndoc.documentElement.appendChild(cdata);\ncdata.appendData(']]\u003e\u003cinjected attr=\"pwn\"/\u003e\u003cmore\u003eTEXT\u003c/more\u003e\u003c![CDATA[');\n\nconst out = new XMLSerializer().serializeToString(doc);\nconsole.log('Serialized:', out);\n\nconst reparsed = new DOMParser().parseFromString(out, 'text/xml');\nconst injected = reparsed.getElementsByTagName('injected').length \u003e 0;\nconsole.log('Injected element found in reparsed doc:', injected);\n// VULNERABLE: true  |  FIXED: false\n```\n\nExpected output on patched versions:\n\n```\nSerialized: \u003croot\u003e\u003c![CDATA[safe]]]]\u003e\u003c![CDATA[\u003e\u003cinjected attr=\"pwn\"/\u003e\u003cmore\u003eTEXT\u003c/more\u003e\u003c![CDATA[]]\u003e\u003c/root\u003e\nInjected element found in reparsed doc: false\n```\n\n---\n\n## Fix Applied\n\nBoth mitigations were implemented:\n\n### Option A — Strict/spec-aligned: reject `]]\u003e` in `createCDATASection()`\n\n`Document.createCDATASection(data)` now throws `InvalidCharacterError` (per the [WHATWG DOM spec](https://dom.spec.whatwg.org/#dom-document-createcdatasection)) when `data` contains `]]\u003e`. This closes the direct entry point.\n\nCode that previously passed a string containing `]]\u003e` to `createCDATASection` and relied on the silent/unsafe behaviour will now receive `InvalidCharacterError`. Use a mutation method such as `appendData` if you intentionally need `]]\u003e` in a CDATASection node's data (the serializer split in Option B will keep the output safe).\n\n### Option B — Defensive serialization: split the terminator during serialization\n\n`XMLSerializer` now replaces every occurrence of `]]\u003e` in CDATA section data with the split sequence `]]]]\u003e\u003c![CDATA[\u003e` before emitting. This closes all mutation-vector paths that Option A alone cannot guard, and means the serialized output is always well-formed XML regardless of how `]]\u003e` entered the node.\n\n## Update — 2026-04-xx (0.9.10 / 0.8.13)\n\n### `splitCDATASections` is deprecated\n\nThe CDATA split behavior introduced as Option B of this fix (replacing `]]\u003e` with`]]]]\u003e\u003c![CDATA[\u003e` during serialization) is **deprecated** as of 0.9.10 / 0.8.13.\n\nThis release introduces a `requireWellFormed` option on `XMLSerializer.serializeToString()`. When `{ requireWellFormed: true }` is passed as the second argument, the serializer throws `InvalidStateError` if CDATA section data contains `]]\u003e` — this is the spec-aligned behavior (W3C DOM Parsing and Serialization, `require well-formed` flag) and the recommended migration path going forward.\nThe split behavior is now controlled by an explicit `splitCDATASections` option (default `true`, preserving the current behavior). The three serialization behaviors are:\n| `requireWellFormed` | `splitCDATASections` | Behavior ||---|---|---|| `false` (default) | `true` (default) | Split `]]\u003e` → `]]]]\u003e\u003c![CDATA[\u003e` (current behavior, deprecated) || `true` | — (ignored) | Throw `InvalidStateError` — spec-aligned, recommended |\\ `false` | `false` | Emit verbatim — same as pre-0.9.9 behavior |\n\n`requireWellFormed: true` takes precedence: the split path is unreachable when it is set.\n\n### Migration\nReplace any reliance on the default split behavior with an explicit opt-in:\n```js// Before (implicit split, deprecated): const xml = new XMLSerializer().serializeToString(doc);\n\n// After (explicit guard, spec-aligned): const xml = new XMLSerializer().serializeToString(doc, { requireWellFormed: true }); // Throws InvalidStateError if any CDATASection contains ']]\u003e' ```\n\n### Removal timeline\nBoth the `splitCDATASections` option and the underlying `]]\u003e` → `]]]]\u003e\u003c![CDATA[\u003e` split mechanics will be removed in the next breaking (`0.10.0`) release. After removal, the only behaviors will be verbatim (default) and `requireWellFormed: true` (throws).\n\nRemoval is tracked in [xmldom/xmldom#999](https://github.com/xmldom/xmldom/issues/999).","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-04-01T00:19:06.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-wh4c-j3r5-mjhp","https://github.com/xmldom/xmldom/commit/2b852e836ab86dbbd6cbaf0537f584dd0b5ac184","https://github.com/xmldom/xmldom/releases/tag/0.8.12","https://github.com/xmldom/xmldom/releases/tag/0.9.9","https://nvd.nist.gov/vuln/detail/CVE-2026-34601","https://github.com/advisories/GHSA-wh4c-j3r5-mjhp"],"source_kind":"github","identifiers":["GHSA-wh4c-j3r5-mjhp","CVE-2026-34601"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-01T01:00:11.361Z","updated_at":"2026-10-09T10:08:34.803Z","epss_percentage":0.00536,"epss_percentile":0.42722,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13aDRjLWozcjUtbWpocM4ABUh5","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS13aDRjLWozcjUtbWpocM4ABUh5","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.9","vulnerable_version_range":"\u003e= 0.9.0, \u003c 0.9.9"},{"first_patched_version":"0.8.12","vulnerable_version_range":"\u003c 0.8.12"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"},{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13aDRjLWozcjUtbWpocM4ABUh5/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1jcmg2LWZwNjctNjg4M84AAvn0","url":"https://github.com/advisories/GHSA-crh6-fp67-6883","title":"xmldom allows multiple root nodes in a DOM","description":"### Impact\nxmldom parses XML that is not well-formed because it contains multiple top level elements, and adds all root nodes to the `childNodes` collection of the `Document`, without reporting any error or throwing.\nThis breaks the assumption that there is only a single root node in the tree, which led to https://nvd.nist.gov/vuln/detail/CVE-2022-39299 and is a potential issue for dependents.\n\n### Patches\nUpdate to `@xmldom/xmldom@~0.7.7`, `@xmldom/xmldom@~0.8.4` (dist-tag `latest`) or `@xmldom/xmldom@\u003e=0.9.0-beta.4` (dist-tag `next`).\n\n### Workarounds\nOne of the following approaches might help, depending on your use case:\n- Instead of searching for elements in the whole DOM, only search in the `documentElement`.\n- Reject a document with a document that has more then 1 `childNode`.\n\n### References\n- https://nvd.nist.gov/vuln/detail/CVE-2022-39299\n- https://github.com/jindw/xmldom/issues/150\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Email us at security@xmldom.org\n","origin":"UNSPECIFIED","severity":"CRITICAL","published_at":"2022-11-01T17:29:11.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":9.8,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-crh6-fp67-6883","https://github.com/xmldom/xmldom/releases/tag/0.7.7","https://github.com/xmldom/xmldom/releases/tag/0.8.4","https://github.com/xmldom/xmldom/releases/tag/0.9.0-beta.4","https://nvd.nist.gov/vuln/detail/CVE-2022-39353","https://github.com/jindw/xmldom/issues/150","https://lists.debian.org/debian-lts-announce/2023/01/msg00000.html","https://github.com/xmldom/xmldom/commit/52a708360c35aa160fcca8621720d71fd0f95f1a","https://github.com/xmldom/xmldom/commit/7ff7c10ab2961703ac1752e95b4ff60ee4ee6643","https://github.com/xmldom/xmldom/commit/c02f786216bed70825f9a351c65e61500f51e931","https://github.com/advisories/GHSA-crh6-fp67-6883"],"source_kind":"github","identifiers":["GHSA-crh6-fp67-6883","CVE-2022-39353"],"repository_url":"https://github.com/xmldom/xmldom","blast_radius":0.0,"created_at":"2022-12-21T16:11:54.095Z","updated_at":"2026-10-09T10:22:05.930Z","epss_percentage":0.01279,"epss_percentile":0.69123,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jcmg2LWZwNjctNjg4M84AAvn0","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jcmg2LWZwNjctNjg4M84AAvn0","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.9.0-beta.4","vulnerable_version_range":"\u003e= 0.9.0-beta.1, \u003c 0.9.0-beta.4"},{"first_patched_version":"0.8.4","vulnerable_version_range":"\u003e= 0.8.0, \u003c 0.8.4"},{"first_patched_version":"0.7.7","vulnerable_version_range":"\u003c 0.7.7"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"},{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jcmg2LWZwNjctNjg4M84AAvn0/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05cGdoLXFxcGYtN3dxas4AAvPc","url":"https://github.com/advisories/GHSA-9pgh-qqpf-7wqj","title":"Withdrawn: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') in @xmldom/xmldom and xmldom","description":"## Withdrawn\n\nThis advisory has been withdrawn because the maintainers of `@xmldom/xmldom` and multiple third parties disputed the validity of the issue. Attempts to create or replicate a proof of concept have been unsuccessful.\n\n## Original Description\n\n### Impact\nA prototype pollution vulnerability exists in the function copy in dom.js in the xmldom (published as @xmldom/xmldom) package.\n\n### Patches\nUpdate to `@xmldom/xmldom@~0.7.6`, `@xmldom/xmldom@~0.8.3` (dist-tag `latest`) or `@xmldom/xmldom@\u003e=0.9.0-beta.2` (dist-tag `next`).\n\n### Workarounds\nNone\n\n### References\nhttps://github.com/xmldom/xmldom/pull/437\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Email us at security@xmldom.org\n* Add information to https://github.com/xmldom/xmldom/issues/436\n","origin":"UNSPECIFIED","severity":"CRITICAL","published_at":"2022-10-11T20:42:57.000Z","withdrawn_at":"2022-11-08T19:35:06.000Z","classification":"GENERAL","cvss_score":9.8,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-9pgh-qqpf-7wqj","https://nvd.nist.gov/vuln/detail/CVE-2022-37616","https://github.com/xmldom/xmldom/issues/436","https://github.com/xmldom/xmldom/pull/437","https://github.com/xmldom/xmldom/blob/bc36efddf9948aba15618f85dc1addfc2ac9d7b2/lib/dom.js#L1","https://github.com/xmldom/xmldom/blob/bc36efddf9948aba15618f85dc1addfc2ac9d7b2/lib/dom.js#L3","https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md#076","https://lists.debian.org/debian-lts-announce/2022/10/msg00023.html","https://github.com/xmldom/xmldom/issues/436#issuecomment-1319412826","https://github.com/xmldom/xmldom/issues/436#issuecomment-1327776560","https://dl.acm.org/doi/abs/10.1145/3488932.3497769","https://dl.acm.org/doi/pdf/10.1145/3488932.3497769","http://users.encs.concordia.ca/~mmannan/publications/JS-vulnerability-aisaccs2022.pdf","https://github.com/advisories/GHSA-9pgh-qqpf-7wqj"],"source_kind":"github","identifiers":["GHSA-9pgh-qqpf-7wqj","CVE-2022-37616"],"repository_url":"https://github.com/xmldom/xmldom","blast_radius":0.0,"created_at":"2022-12-21T16:11:55.452Z","updated_at":"2026-10-09T10:22:10.475Z","epss_percentage":0.02119,"epss_percentile":0.81298,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05cGdoLXFxcGYtN3dxas4AAvPc","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05cGdoLXFxcGYtN3dxas4AAvPc","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.7.6","vulnerable_version_range":"\u003c 0.7.6"},{"first_patched_version":"0.8.3","vulnerable_version_range":"\u003e= 0.8.0, \u003c 0.8.3"},{"first_patched_version":"0.9.0-beta.2","vulnerable_version_range":"= 0.9.0-beta.1"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"},{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05cGdoLXFxcGYtN3dxas4AAvPc/related_packages","related_advisories":[]},{"uuid":"MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTVmZzgtMjU0Ny1tcjhx","url":"https://github.com/advisories/GHSA-5fg8-2547-mr8q","title":"Misinterpretation of malicious XML input","description":"### Impact\nxmldom versions 0.6.0 and older do not correctly escape special characters when serializing elements removed from their ancestor. This may lead to unexpected syntactic changes during XML processing in some downstream applications.\n\n### Patches\nUpdate to one of the fixed versions of `@xmldom/xmldom` (`\u003e=0.7.0`)\n\nSee issue #271 for the status of publishing `xmldom` to npm or join #270 for Q\u0026A/discussion until it's resolved.\n\n### Workarounds\n\nDownstream applications can validate the input and reject the maliciously crafted documents.\n\n### References\n\nSimilar to this one reported on the Go standard library:\n\n- https://mattermost.com/blog/coordinated-disclosure-go-xml-vulnerabilities/\n- https://mattermost.com/blog/securing-xml-implementations-across-the-web/\n\n### For more information\n\nIf you have any questions or comments about this advisory:\n\n* Open an issue in [`xmldom/xmldom`](https://github.com/xmldom/xmldom)\n* Email us: send an email to **all** addresses that are shown by `npm owner ls @xmldom/xmldom`\n","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2021-08-03T16:57:05.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N","references":["https://github.com/xmldom/xmldom/security/advisories/GHSA-5fg8-2547-mr8q","https://nvd.nist.gov/vuln/detail/CVE-2021-32796","https://github.com/xmldom/xmldom/commit/7b4b743917a892d407356e055b296dcd6d107e8b","https://www.npmjs.com/package/@xmldom/xmldom","https://mattermost.com/blog/coordinated-disclosure-go-xml-vulnerabilities","https://mattermost.com/blog/securing-xml-implementations-across-the-web","https://github.com/advisories/GHSA-5fg8-2547-mr8q"],"source_kind":"github","identifiers":["GHSA-5fg8-2547-mr8q","CVE-2021-32796"],"repository_url":"https://github.com/xmldom/xmldom","blast_radius":0.0,"created_at":"2022-12-21T16:12:40.151Z","updated_at":"2026-10-09T10:16:55.479Z","epss_percentage":0.01358,"epss_percentile":0.7051,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTVmZzgtMjU0Ny1tcjhx","html_url":"https://advisories.ecosyste.ms/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTVmZzgtMjU0Ny1tcjhx","packages":[{"ecosystem":"npm","package_name":"@xmldom/xmldom","versions":[{"first_patched_version":"0.7.0","vulnerable_version_range":"\u003c 0.7.0"}],"purl":"pkg:npm/%40xmldom%2Fxmldom"},{"ecosystem":"npm","package_name":"xmldom","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c= 0.6.0"}],"purl":"pkg:npm/xmldom"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTVmZzgtMjU0Ny1tcjhx/related_packages","related_advisories":[]}],"docker_usage_url":"https://docker.ecosyste.ms/usage/npm/@xmldom/xmldom","docker_dependents_count":1627,"docker_downloads_count":1138889338,"usage_url":"https://repos.ecosyste.ms/usage/npm/@xmldom/xmldom","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/npm/@xmldom/xmldom/dependencies","status":null,"funding_links":[],"critical":true,"issue_metadata":{"last_synced_at":"2026-10-06T06:17:19.517Z","issues_count":108,"pull_requests_count":784,"avg_time_to_close_issue":26307870.207792208,"avg_time_to_close_pull_request":1166702.7604017216,"issues_closed_count":77,"pull_requests_closed_count":697,"pull_request_authors_count":36,"issue_authors_count":75,"avg_comments_per_issue":3.9537037037037037,"avg_comments_per_pull_request":1.468112244897959,"merged_pull_requests_count":640,"bot_issues_count":2,"bot_pull_requests_count":628,"past_year_issues_count":16,"past_year_pull_requests_count":82,"past_year_avg_time_to_close_issue":9277265.333333334,"past_year_avg_time_to_close_pull_request":1966723.8235294118,"past_year_issues_closed_count":3,"past_year_pull_requests_closed_count":51,"past_year_pull_request_authors_count":8,"past_year_issue_authors_count":8,"past_year_avg_comments_per_issue":0.5625,"past_year_avg_comments_per_pull_request":1.353658536585366,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":65,"past_year_merged_pull_requests_count":42,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmldom%2Fxmldom/issues","maintainers":[{"login":"karfau","count":104,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/karfau"},{"login":"shunkica","count":14,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/shunkica"},{"login":"Ponynjaa","count":8,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Ponynjaa"},{"login":"brodybits","count":7,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/brodybits"},{"login":"brodycj","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/brodycj"}],"active_maintainers":[{"login":"karfau","count":17,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/karfau"}]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@xmldom%2Fxmldom/codemeta","maintainers":[{"uuid":"karfau","login":"karfau","name":null,"email":"coder@karfau.de","url":null,"packages_count":3,"html_url":"https://www.npmjs.com/~karfau","role":null,"created_at":"2022-11-20T08:47:08.924Z","updated_at":"2022-11-20T08:47:08.924Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/karfau/packages"}]}