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);
 }