diff options
| author | Michael Williamson <mike@zwobble.org> | 2025-09-10 15:55:27 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2025-09-10 15:55:27 +0100 |
| commit | 1494d3c3a6283a00701ac452b8a9a5f8f2f4e9dd (patch) | |
| tree | 4e4467490b883fe075094a25ba28f05e62d21393 | |
| parent | 162324eb530d781aa59acce597997646ee59d1eb (diff) | |
Support disabling external file access
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | README.md | 15 | ||||
| -rw-r--r-- | lib/docx/docx-reader.js | 4 | ||||
| -rw-r--r-- | lib/docx/files.js | 9 | ||||
| -rw-r--r-- | lib/index.d.ts | 1 | ||||
| -rw-r--r-- | lib/index.js | 2 | ||||
| -rw-r--r-- | lib/options-reader.js | 1 | ||||
| -rw-r--r-- | test/docx/files.tests.js | 21 | ||||
| -rw-r--r-- | test/mammoth.tests.js | 9 |
9 files changed, 58 insertions, 6 deletions
@@ -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, @@ -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) { |
