@brickhouse-tech/xml2js
v1.1.8
Published
Simple XML to JavaScript object converter.
Downloads
197
Readme
@brickhouse-tech/xml2js
Security-Patched Fork — Prototype Pollution Vulnerability Fixed
The original xml2js package is abandoned. Despite 29+ million weekly downloads, it remains unpatched for a critical prototype pollution vulnerability (CVE-2023-0842) that can compromise application security.
@brickhouse-tech/xml2js is a drop-in replacement with the security fix applied, comprehensive regression tests added, and ongoing maintenance.
🚨 The Problem
Original Package Status
- 29.1M weekly downloads (as of March 2025)
- Last meaningful commit: Years ago
- Maintainer status: Inactive/abandoned
- Critical CVE: CVE-2023-0842 — Prototype pollution via
__proto__andconstructorkeys in parsed XML - Risk exposure: Millions of production applications vulnerable to object injection attacks
The Vulnerability
Malicious XML containing __proto__ or constructor element names can pollute JavaScript's Object prototype chain, potentially leading to:
- Remote code execution (RCE) in certain contexts
- Authentication bypass
- Data exfiltration
- Denial of service (DoS)
- Arbitrary property injection across all objects
Example attack vector:
<root>
<__proto__>
<isAdmin>true</isAdmin>
</__proto__>
</root>When parsed by vulnerable versions, this XML can inject properties into Object.prototype, affecting all objects in the application.
✅ The Solution
@brickhouse-tech/xml2js is a community-maintained fork that:
- Fixes CVE-2023-0842 with hardened property assignment using
Object.defineProperty() - Adds comprehensive regression tests (3 new test cases covering attack vectors)
- Maintains 100% API compatibility (drop-in replacement)
- Provides ongoing security maintenance and dependency updates
- Stays current with Node.js LTS releases
What We Fixed
Before (Vulnerable)
// Direct property assignment - vulnerable to prototype pollution
obj[key] = value;After (Secure)
function defineProperty(obj, key, value) {
// Create a clean descriptor to prevent prototype pollution
const descriptor = Object.create(null);
descriptor.value = value;
descriptor.writable = true;
descriptor.enumerable = true;
descriptor.configurable = true;
Object.defineProperty(obj, key, descriptor);
}This approach:
- Uses
Object.create(null)to prevent descriptor pollution - Employs
Object.defineProperty()for controlled property creation - Blocks
__proto__,constructor, andprototypeinjection vectors
Test Coverage
We added three comprehensive regression tests to verify the fix:
__proto__element pollution testconst maliciousXML = '<root><__proto__><polluted>POLLUTED</polluted></__proto__></root>'; // Verifies Object.prototype.polluted remains undefinedconstructorelement pollution testconst maliciousXML = '<root><constructor><polluted>POLLUTED</polluted></constructor></root>'; // Verifies constructor pollution is blocked__proto__attribute pollution testconst maliciousXML = '<root><__proto__ polluted="POLLUTED"/></root>'; // Verifies attribute-based pollution vectors are blocked
All tests verify that Object.prototype.polluted and ({}).polluted remain undefined after parsing malicious XML.
🔄 Migration Guide
One-Line Installation
npm uninstall xml2js
npm install @brickhouse-tech/xml2jsCode Changes Required
None. This is a 100% drop-in replacement with identical API surface.
// Original
const xml2js = require('xml2js');
// Replacement (same code, secure implementation)
const xml2js = require('@brickhouse-tech/xml2js');For TypeScript Users
// Original
import * as xml2js from 'xml2js';
// Replacement (identical import)
import * as xml2js from '@brickhouse-tech/xml2js';Verification
After installation, run your test suite. No code changes should be required. If you encounter any compatibility issues, please open an issue.
📊 Package Details
- Current Version: 1.1.4
- License: MIT (same as original)
- Node.js: >=18.0.0 (ESM support)
- Repository: github.com/brickhouse-tech/node-xml2js
- NPM: @brickhouse-tech/xml2js
🏢 Enterprise Support
For organizations requiring guaranteed SLA response times, dedicated security advisories, or priority patch delivery:
Enterprise Support Tiers Available
- 🥉 Bronze: 5-day response, email support
- 🥈 Silver: 48-hour response, security advisory access
- 🥇 Gold: 24-hour response, dedicated Slack channel, custom patches
📧 Contact: brickhouse-tech.lemonsqueezy.com
💚 Support This Work
This fork is maintained by Brickhouse Tech as a community service. If your organization benefits from this security patch, consider sponsoring ongoing maintenance:
Sponsorship funds:
- Security research and proactive CVE monitoring
- Dependency updates and compatibility testing
- Long-term maintenance and Node.js LTS support
- Community issue triage and documentation
📚 Documentation
The API documentation remains unchanged from the original xml2js package. For complete usage examples, see:
Usage
Quick Start
const xml2js = require('@brickhouse-tech/xml2js');
const xml = "<root>Hello xml2js!</root>";
xml2js.parseString(xml, function (err, result) {
console.dir(result);
});With Parser Instance
const xml2js = require('@brickhouse-tech/xml2js');
const parser = new xml2js.Parser();
parser.parseString(xml, function (err, result) {
console.dir(result);
});Promise-Based
const xml2js = require('@brickhouse-tech/xml2js');
const xml = '<foo>bar</foo>';
xml2js.parseStringPromise(xml)
.then(result => console.dir(result))
.catch(err => console.error(err));Building XML from Objects
const xml2js = require('@brickhouse-tech/xml2js');
const builder = new xml2js.Builder();
const obj = {name: "Super", Surname: "Man", age: 23};
const xml = builder.buildObject(obj);Options
Parser Options
Specify options via new Parser({optionName: value}):
attrkey(default:$) — Prefix for accessing attributescharkey(default:_) — Prefix for accessing character contentexplicitCharkey(default:false) — Use charkey even for elements with no attributestrim(default:false) — Trim whitespace at start/end of text nodesnormalizeTags(default:false) — Lowercase all tag namesnormalize(default:false) — Trim whitespace inside text nodesexplicitRoot(default:true) — Include root node in resultemptyTag(default:'') — Value for empty nodes (use factory function for objects)explicitArray(default:true) — Always use arrays for child nodesignoreAttrs(default:false) — Ignore all attributesmergeAttrs(default:false) — Merge attributes as properties of parentvalidator(default:null) — Custom validation functionxmlns(default:false) — Include namespace informationexplicitChildren(default:false) — Separate property for child elementschildkey(default:$$) — Prefix for child elementspreserveChildrenOrder(default:false) — Ordered children arraycharsAsChildren(default:false) — Treat text as childrenincludeWhiteChars(default:false) — Include whitespace-only text nodesasync(default:false) — Use async callbacksstrict(default:true) — Strict XML parsing (highly recommended)attrNameProcessors(default:null) — Attribute name processing functionsattrValueProcessors(default:null) — Attribute value processing functionstagNameProcessors(default:null) — Tag name processing functionsvalueProcessors(default:null) — Element value processing functions
Builder Options
Specify options via new Builder({optionName: value}):
attrkey(default:$) — Prefix for attributescharkey(default:_) — Prefix for character contentrootName(default:root) — Root element namerenderOpts— Rendering options for xmlbuilder-jspretty(default:true) — Prettify outputindent(default:' ') — Indentation stringnewline(default:'\n') — Newline character
xmldec— XML declaration attributesversion(default:'1.0')encoding(default:'UTF-8')standalone(default:true)
doctype(default:null) — Optional DTDheadless(default:false) — Omit XML headerallowSurrogateChars(default:false) — Allow Unicode surrogate blockscdata(default:false) — Wrap text in CDATA when necessary
Processing Attribute, Tag Names and Values
You can provide custom processing functions to transform names and values during parsing:
function nameToUpperCase(name) {
return name.toUpperCase();
}
xml2js.parseString(xml, {
tagNameProcessors: [nameToUpperCase],
attrNameProcessors: [nameToUpperCase],
valueProcessors: [nameToUpperCase],
attrValueProcessors: [nameToUpperCase]
}, function (err, result) {
// All names and values transformed to uppercase
});Built-in Processors
Available in lib/processors.js:
normalize— Transform to lowercasefirstCharLowerCase— Lowercase first character onlystripPrefix— Remove XML namespace prefix (preservesxmlns)parseNumbers— Parse numeric strings to numbersparseBooleans— Parse boolean strings to booleans
Running Tests
npm test # Run test suite
npm run coverage # Run with coverage report
npm run lint # Run ESLintContributing
Contributions welcome! Please:
- Write tests for new features or bug fixes
- Follow existing code style (ESLint enforced)
- Update documentation as needed
- Open an issue before major changes
This project uses:
- ESM (ECMAScript modules)
- Node.js >=18
- Mocha for testing
- ESLint for code quality
Security
Reporting vulnerabilities: Please email security issues to the maintainers rather than opening public issues. We'll coordinate disclosure and patches.
Security policy: We monitor CVE databases and dependency advisories. Critical patches are released within 48 hours of disclosure.
License
MIT License — same as the original xml2js package.
Copyright (c) 2010-2024 Marek Kubica and contributors
Security patches and ongoing maintenance by Brickhouse Tech.
Credits
Original package by Marek Kubica and the xml2js contributors.
Security fork maintained by:
- Brickhouse Tech — github.com/brickhouse-tech
- Lead Maintainer: Nick McCready
Special thanks to the security research community for identifying and documenting CVE-2023-0842.
FAQ
Why fork instead of contributing upstream?
The original maintainer has not responded to issues or pull requests in years. With 29M+ weekly downloads at risk, the community needed an immediate, maintained solution.
Is this a permanent fork?
We're committed to maintaining this fork as long as the original remains inactive. If upstream development resumes, we'll evaluate reunification.
Will you add new features?
Our primary focus is security and stability. We accept bug fixes and security patches readily. New features are evaluated case-by-case to maintain compatibility.
How do I verify the security fix?
Run the test suite (npm test) and inspect the three CVE-2023-0842 regression tests in test/parser.test.js. The fix implementation is in lib/parser.js (the defineProperty function).
What if I find a security issue?
Email the maintainers immediately (see Security section). Do not open public issues for vulnerabilities.
Protect your supply chain. Migrate to @brickhouse-tech/xml2js today.
