diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index d6fa16c..fe19bd1 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -16,6 +16,8 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\filter\FilterFormatInterface;
 use Drupal\filter\Plugin\FilterInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\file\FileInterface;
 
 /**
  * Implements hook_help().
@@ -468,6 +470,60 @@ function _editor_delete_file_usage(array $uuids, EntityInterface $entity, $count
 }
 
 /**
+ * Implements hook_file_download().
+ *
+ * @see file_file_download()
+ * @see file_get_file_references()
+ */
+function editor_file_download($uri) {
+  // Get the file record based on the URI. If not in the database just return.
+  /** @var \Drupal\file\FileInterface[] $files */
+  $files = \Drupal::entityTypeManager()
+    ->getStorage('file')
+    ->loadByProperties(['uri' => $uri]);
+  if (count($files)) {
+    foreach ($files as $item) {
+      // Since some database servers sometimes use a case-insensitive comparison
+      // by default, double check that the filename is an exact match.
+      if ($item->getFileUri() === $uri) {
+        $file = $item;
+        break;
+      }
+    }
+  }
+  if (!isset($file)) {
+    return;
+  }
+
+  // Temporary files are handled by file_file_download(), so nothing to do here
+  // about them.
+  // @see file_file_download()
+
+  // Find out if any editor-backed field contains the file.
+  $usage_list = \Drupal::service('file.usage')->listUsage($file);
+
+  // Stop processing if there are no references in order to avoid returning
+  // headers for files controlled by other modules. Make an exception for
+  // temporary files where the host entity has not yet been saved (for example,
+  // an image preview on a node creation form) in which case, allow download by
+  // the file's owner.
+  if (empty($usage_list['editor']) && ($file->isPermanent() || $file->getOwnerId() != \Drupal::currentUser()->id())) {
+    return;
+  }
+
+  // Editor.module MUST NOT call $file->access() here (like file_file_download()
+  // does) as checking the 'download' access to a file entity would end up in
+  // FileAccessControlHandler->checkAccess() and ->getFileReferences(), which
+  // calls file_get_file_references(). This latter one would allow downloading
+  // files only handled by the file.module, which is exactly not the case right
+  // here.
+
+  // Access is granted.
+  $headers = file_get_content_headers($file);
+  return $headers;
+}
+
+/**
  * Finds all files referenced (data-entity-uuid) by formatted text fields.
  *
  * @param EntityInterface $entity
diff --git a/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php b/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php
new file mode 100644
index 0000000..3fe05ee
--- /dev/null
+++ b/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Drupal\editor\Tests;
+
+use Drupal\file\Entity\File;
+use Drupal\file\FileInterface;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests Editor module's file reference filter with private files.
+ *
+ * @group editor
+ */
+class EditorPrivateFileReferenceFilterTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    // Needed for the config: this is the only module in core that utilizes the
+    // functionality in editor.module to be tested, and depends on that.
+    'ckeditor',
+    // Depends on filter.module (indirectly).
+    'node',
+    // Pulls in the config we're using during testing which create a text format
+    // - with the filter_html_image_secure filter DISABLED,
+    // - with the editor set to CKEditor,
+    // - with drupalimage.image_upload.scheme set to 'private',
+    // - with drupalimage.image_upload.directory set to ''.
+    'editor_private_test',
+  ];
+
+  /**
+   * Tests the editor file reference filter with private files.
+   */
+  function testEditorPrivateFileReferenceFilter() {
+    // Create a content type with a body field.
+    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
+
+    // Create a file in the 'private:// ' stream.
+    $filename = 'test.png';
+    $src = '/system/files/' . $filename;
+    /** @var FileInterface $file */
+    $file = File::create([
+      'uri' => 'private://' . $filename,
+      'status' => FILE_STATUS_PERMANENT,
+    ]);
+    // Create the file itself.
+    file_put_contents($file->getFileUri(), $this->randomString());
+    $file->save();
+
+    // Create a node with its body field properly pointing to the just-created
+    // file.
+    $node = $this->drupalCreateNode([
+      'type' => 'page',
+      'body' => [
+        'value' => '<img alt="alt" data-entity-type="file" data-entity-uuid="' . $file->uuid() . '" src="' . $src . '" />',
+        'format' => 'private_images',
+      ],
+    ]);
+    $this->drupalGet('/node/' . $node->id());
+
+    // Do the actual test. The image should be visible for anonymous.
+    $this->drupalGet($src);
+    $this->assertResponse(200, 'Image is downloadable as anonymous.');
+  }
+
+}
diff --git a/core/modules/editor/tests/editor_private_test/config/install/editor.editor.private_images.yml b/core/modules/editor/tests/editor_private_test/config/install/editor.editor.private_images.yml
new file mode 100644
index 0000000..2de126a
--- /dev/null
+++ b/core/modules/editor/tests/editor_private_test/config/install/editor.editor.private_images.yml
@@ -0,0 +1,34 @@
+format: private_images
+status: true
+langcode: en
+editor: ckeditor
+settings:
+  toolbar:
+    rows:
+      -
+        -
+          name: Media
+          items:
+            - DrupalImage
+        -
+          name: Tools
+          items:
+            - Source
+  plugins:
+    language:
+      language_list: un
+    stylescombo:
+      styles: ''
+image_upload:
+  status: true
+  scheme: private
+  directory: ''
+  max_size: ''
+  max_dimensions:
+    width: null
+    height: null
+dependencies:
+  config:
+    - filter.format.private_images
+  module:
+    - ckeditor
diff --git a/core/modules/editor/tests/editor_private_test/config/install/filter.format.private_images.yml b/core/modules/editor/tests/editor_private_test/config/install/filter.format.private_images.yml
new file mode 100644
index 0000000..261bd90
--- /dev/null
+++ b/core/modules/editor/tests/editor_private_test/config/install/filter.format.private_images.yml
@@ -0,0 +1,23 @@
+format: private_images
+name: 'Private images'
+status: true
+langcode: en
+filters:
+  editor_file_reference:
+    id: editor_file_reference
+    provider: editor
+    status: true
+    weight: 0
+    settings: {  }
+  filter_html:
+    id: filter_html
+    provider: filter
+    status: false
+    weight: -10
+    settings:
+      allowed_html: '<img src alt data-entity-type data-entity-uuid>'
+      filter_html_help: true
+      filter_html_nofollow: false
+dependencies:
+  module:
+    - editor
diff --git a/core/modules/editor/tests/editor_private_test/editor_private_test.info.yml b/core/modules/editor/tests/editor_private_test/editor_private_test.info.yml
new file mode 100644
index 0000000..474fda6
--- /dev/null
+++ b/core/modules/editor/tests/editor_private_test/editor_private_test.info.yml
@@ -0,0 +1,9 @@
+name: 'Text Editor Private test'
+type: module
+description: 'Support module for the Text Editor Private module tests.'
+core: 8.x
+package: Testing
+version: VERSION
+dependencies:
+  - filter
+  - ckeditor
