summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2025-09-10 15:55:27 +0100
committerMichael Williamson <mike@zwobble.org>2025-09-10 15:55:27 +0100
commit1494d3c3a6283a00701ac452b8a9a5f8f2f4e9dd (patch)
tree4e4467490b883fe075094a25ba28f05e62d21393
parent162324eb530d781aa59acce597997646ee59d1eb (diff)
Support disabling external file access
-rw-r--r--NEWS2
-rw-r--r--README.md15
-rw-r--r--lib/docx/docx-reader.js4
-rw-r--r--lib/docx/files.js9
-rw-r--r--lib/index.d.ts1
-rw-r--r--lib/index.js2
-rw-r--r--lib/options-reader.js1
-rw-r--r--test/docx/files.tests.js21
-rw-r--r--test/mammoth.tests.js9
9 files changed, 58 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index f2ce8bb..9fd5547 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@
* Ignore style definitions using a style ID that has already been used.
+* Support disabling external file accesses using the externalFileAccess option.
+
# 1.10.0
* Add "Heading" and "Body" styles, as found in documents created by Apple Pages,
diff --git a/README.md b/README.md
index b0d6d49..79a49b3 100644
--- a/README.md
+++ b/README.md
@@ -230,6 +230,18 @@ var options = {
};
```
+#### External file access
+
+Source documents may reference files outside of the source document.
+To disable access to any such external files during the conversion process,
+set `options.externalFileAccess` to `false`:
+
+```javascript
+var options = {
+ externalFileAccess: false
+};
+```
+
#### Custom image handlers
By default, images are converted to `<img>` elements with the source included inline in the `src` attribute.
@@ -536,6 +548,9 @@ For instance:
and embed the HTML into your website,
this may allow arbitrary files on the server to be read and exfiltrated.
+ To disable access to any such external files during the conversion process,
+ set `options.externalFileAccess` to `false`.
+
### Document transforms
**The API for document transforms should be considered unstable,
diff --git a/lib/docx/docx-reader.js b/lib/docx/docx-reader.js
index 342ec46..f343dae 100644
--- a/lib/docx/docx-reader.js
+++ b/lib/docx/docx-reader.js
@@ -18,10 +18,12 @@ var commentsReader = require("./comments-reader");
var Files = require("./files").Files;
-function read(docxFile, input) {
+function read(docxFile, input, options) {
input = input || {};
+ options = options || {};
var files = new Files({
+ externalFileAccess: options.externalFileAccess,
relativeToFile: input.path
});
diff --git a/lib/docx/files.js b/lib/docx/files.js
index 4b09b69..cb8655c 100644
--- a/lib/docx/files.js
+++ b/lib/docx/files.js
@@ -13,6 +13,15 @@ exports.uriToPath = uriToPath;
function Files(options) {
+ options = options || {};
+ if (!options.externalFileAccess) {
+ return {
+ read: function(uri) {
+ return promises.reject(new Error("could not read external image '" + uri + "', external file access is disabled"));
+ }
+ };
+ }
+
var base = options.relativeToFile ? dirname(options.relativeToFile) : null;
function read(uri, encoding) {
diff --git a/lib/index.d.ts b/lib/index.d.ts
index 465c8f9..1f9af9e 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -33,6 +33,7 @@ interface Options {
convertImage?: ImageConverter;
ignoreEmptyParagraphs?: boolean;
idPrefix?: string;
+ externalFileAccess?: boolean;
transformDocument?: (element: any) => any;
}
diff --git a/lib/index.js b/lib/index.js
index 03302c2..48dfb91 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -39,7 +39,7 @@ function convert(input, options) {
});
})
.then(function(docxFile) {
- return docxReader.read(docxFile, input)
+ return docxReader.read(docxFile, input, options)
.then(function(documentResult) {
return documentResult.map(options.transformDocument);
})
diff --git a/lib/options-reader.js b/lib/options-reader.js
index e16e472..4768159 100644
--- a/lib/options-reader.js
+++ b/lib/options-reader.js
@@ -63,6 +63,7 @@ var defaultStyleMap = exports._defaultStyleMap = [
];
var standardOptions = exports._standardOptions = {
+ externalFileAccess: true,
transformDocument: identity,
includeDefaultStyleMap: true,
includeEmbeddedStyleMap: true
diff --git a/test/docx/files.tests.js b/test/docx/files.tests.js
index 9a39acb..5ddda4a 100644
--- a/test/docx/files.tests.js
+++ b/test/docx/files.tests.js
@@ -13,9 +13,16 @@ var readFile = promises.promisify(fs.readFile.bind(fs));
test("Files", {
+ "when external file access is disabled then reading file raises error": function() {
+ var files = new Files({externalFileAccess: false});
+ return assertError(files.read("/tmp/image.png", "base64"), function(err) {
+ assert.strictEqual(err.message, "could not read external image '/tmp/image.png', external file access is disabled");
+ });
+ },
+
"can open files with file URI": function() {
var filePath = path.resolve(testing.testPath("tiny-picture.png"));
- var files = new Files({});
+ var files = new Files({externalFileAccess: true});
return files.read("file:///" + filePath.replace(/^\//, ""), "base64").then(function(contents) {
return readFile(filePath, "base64").then(function(expectedContents) {
assert.deepEqual(contents, expectedContents);
@@ -25,7 +32,10 @@ test("Files", {
"can open files with relative URI": function() {
var filePath = path.resolve(testing.testPath("tiny-picture.png"));
- var files = new Files({relativeToFile: testing.testPath("./document.docx")});
+ var files = new Files({
+ externalFileAccess: true,
+ relativeToFile: testing.testPath("./document.docx")
+ });
return files.read("tiny-picture.png", "base64").then(function(contents) {
return readFile(filePath, "base64").then(function(expectedContents) {
assert.deepEqual(contents, expectedContents);
@@ -34,14 +44,17 @@ test("Files", {
},
"given base is not set when opening relative uri then error is raised": function() {
- var files = new Files({});
+ var files = new Files({externalFileAccess: true});
return assertError(files.read("not-a-real-file.png", "base64"), function(err) {
assert.equal(err.message, "could not find external image 'not-a-real-file.png', path of input document is unknown");
});
},
"error if relative uri cannot be opened": function() {
- var files = new Files({relativeToFile: "/tmp/document.docx"});
+ var files = new Files({
+ externalFileAccess: true,
+ relativeToFile: "/tmp/document.docx"
+ });
return assertError(files.read("not-a-real-file.png", "base64"), function(err) {
assertRegex(err.message, /could not open external image: 'not-a-real-file.png' \(document directory: '\/tmp'\)\nENOENT.*\/tmp\/not-a-real-file.png.*/);
});
diff --git a/test/mammoth.tests.js b/test/mammoth.tests.js
index 93a4f16..06cf62f 100644
--- a/test/mammoth.tests.js
+++ b/test/mammoth.tests.js
@@ -327,6 +327,15 @@ test('error if images stored outside of document are specified when passing file
});
});
+test('error if images stored outside of document are specified when external file access is disabled', function() {
+ var docxPath = path.join(__dirname, "test-data/external-picture.docx");
+ return mammoth.convertToHtml({path: docxPath}, {externalFileAccess: false}).then(function(result) {
+ assert.equal(result.value, '');
+ assert.equal(result.messages[0].message, "could not read external image 'tiny-picture.png', external file access is disabled");
+ assert.equal(result.messages[0].type, "error");
+ });
+});
+
test('simple list is converted to list elements', function() {
var docxPath = path.join(__dirname, "test-data/simple-list.docx");
return mammoth.convertToHtml({path: docxPath}).then(function(result) {