Commit 31f0c37 for mammothjs
commit 31f0c370be4b95ac4fa285fea3be970606735f16
Author: Michael Williamson <mike@zwobble.org>
Date: Fri Aug 28 14:39:48 2026 +0100
Avoid prototype pollution when reading styles
diff --git a/NEWS b/NEWS
index 5f954c3..1206dac 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+# 1.12.2
+
+* Avoid prototype pollution when reading the styles defined in a document. This
+ avoids an issue where a maliciously crafted document could be used to set
+ externalFileAccess to true.
+
# 1.12.1
* Fix: on Windows, when an image's content type includes a backslash in the
diff --git a/lib/docx/styles-reader.js b/lib/docx/styles-reader.js
index 28c809b..276a668 100644
--- a/lib/docx/styles-reader.js
+++ b/lib/docx/styles-reader.js
@@ -27,16 +27,27 @@ function readStylesXml(root) {
var tableStyles = {};
var numberingStyles = {};
- var styles = {
- "paragraph": paragraphStyles,
- "character": characterStyles,
- "table": tableStyles,
- "numbering": numberingStyles
- };
-
root.getElementsByTagName("w:style").forEach(function(styleElement) {
var style = readStyleElement(styleElement);
- var styleSet = styles[style.type];
+ var styleSet;
+
+ switch (style.type) {
+ case "paragraph":
+ styleSet = paragraphStyles;
+ break;
+
+ case "character":
+ styleSet = characterStyles;
+ break;
+
+ case "table":
+ styleSet = tableStyles;
+ break;
+
+ case "numbering":
+ styleSet = numberingStyles;
+ break;
+ }
// Per 17.7.4.17 style (Style Definition) of ECMA-376 4th edition Part 1:
//
diff --git a/test/docx/styles-reader.tests.js b/test/docx/styles-reader.tests.js
index b63bb6a..8f964c1 100644
--- a/test/docx/styles-reader.tests.js
+++ b/test/docx/styles-reader.tests.js
@@ -120,6 +120,18 @@ test('when multiple style elements have same style ID then only first element is
assert.equal(styles.findTableStyleById("TableNormal").name, "Normal Table");
});
+test('w:type of __proto__ does not cause prototype pollution', function() {
+ readStylesXml(
+ new XmlElement("w:styles", {}, [
+ new XmlElement("w:style", {"w:type": "__proto__", "w:styleId": "List1"}, [
+ new XmlElement("w:name", {"w:val": "List 1"}, [])
+ ])
+ ])
+ );
+
+ assert.equal({}["List1"], undefined);
+});
+
function paragraphStyleElement(id, name) {
return styleElement("paragraph", id, name);
}