diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 6c54fae..60cbd2f 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -1245,6 +1245,14 @@ function filter_filter_info() {
     ),
     'tips callback' => '_filter_url_tips',
   );
+  $filters['filter_html_image_secure'] = array(
+    'title' => t('Restrict images to this site'),
+    'description' => t('Disallows usage of &lt;img&gt; tag sources that are not hosted on this site by replacing them with a placeholder image.'),
+    'process callback' => '_filter_html_image_secure_process',
+    'tips callback' => '_filter_html_image_secure_tips',
+    // Supposed to run after other filters and before HTML corrector by default.
+    'weight' => 9,
+  );
   $filters['filter_htmlcorrector'] = array(
     'title' =>  t('Correct faulty and chopped off HTML'),
     'process callback' => '_filter_htmlcorrector',
@@ -1765,6 +1773,60 @@ function _filter_html_escape_tips($filter, $format, $long = FALSE) {
 }
 
 /**
+ * Process callback for local image filter.
+ */
+function _filter_html_image_secure_process($text) {
+  // Find the path (e.g. '/') to Drupal root.
+  $base_path = base_path();
+  $base_path_length = strlen($base_path);
+
+  // Find the directory on the server where index.php resides.
+  $local_dir = DRUPAL_ROOT . '/';
+
+  $alt_text = t('Image removed.');
+  $title_text = t('This image has been removed. For security reasons, only images from the local domain are allowed.');
+
+  $html_dom = filter_dom_load($text);
+  $images = $html_dom->getElementsByTagName('img');
+  foreach ($images as $image) {
+    $src = $image->getAttribute('src');
+    // Remove absolute URLs pointed to the local domain, in order to prevent
+    // mixed content errors.
+    $image->setAttribute('src', preg_replace('|^https?://' . $_SERVER['HTTP_HOST'] . '|', '', $src));
+
+    // Verify $src starts with $base_path. This also ensures that external
+    // images can't be referenced because $base_path always starts with a
+    // slash. Another insurance against that will be prefixing the image
+    // source with the Drupal root before running getimagesize() on it.
+    $src = $image->getAttribute('src');
+    if (substr($src, 0, $base_path_length) == $base_path) {
+      // Remove the base path() to get the path relative to the Drupal root.
+      // Also, make sure we're dealing with a real image here.
+      $local_image_path = $local_dir . substr($src, $base_path_length);
+      if (@getimagesize($local_image_path)) {
+        // The image has the right path, nothing to do. Erroneous images
+        // are dealt with below.
+        continue;
+      }
+    }
+    // Replace invalid images with an error indicator.
+    $image->setAttribute('src', $base_path . 'core/misc/message-16-error.png');
+    $image->setAttribute('alt', $alt_text);
+    $image->setAttribute('title', $title_text);
+  }
+  $text = filter_dom_serialize($html_dom);
+
+  return $text;
+}
+
+/**
+ * Filter tips callback for secure HTML image filter.
+ */
+function _filter_html_image_secure_tips($filter, $format, $long = FALSE) {
+  return t('Only images hosted on this site may be used in &lt;img&gt; tags. Others are replaced with an error icon.');
+}
+
+/**
  * @} End of "defgroup standard_filters".
  */
 
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php
new file mode 100644
index 0000000..62fc83c
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\filter\Tests\FilterHtmlImageSecureTest.
+ */
+
+namespace Drupal\filter\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests restriction of IMG tags in HTML input.
+ */
+class FilterHtmlImageSecureTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('filter', 'node', 'comment');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Local image input filter',
+      'description' => 'Tests restriction of IMG tags in HTML input.',
+      'group' => 'Filter',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Setup Filtered HTML text format.
+    $filtered_html_format = array(
+      'format' => 'filtered_html',
+      'name' => 'Filtered HTML',
+      'filters' => array(
+        'filter_html' => array(
+          'status' => 1,
+          'settings' => array(
+            'allowed_html' => '<img> <a>',
+          ),
+        ),
+        'filter_autop' => array(
+          'status' => 1,
+        ),
+        'filter_html_image_secure' => array(
+          'status' => 1,
+        ),
+      ),
+    );
+    $filtered_html_format = (object) $filtered_html_format;
+    filter_format_save($filtered_html_format);
+
+    // Setup users.
+    $this->checkPermissions(array(), TRUE);
+    $this->web_user = $this->drupalCreateUser(array(
+      'access content',
+      'access comments',
+      'post comments',
+      'skip comment approval',
+      filter_permission_name($filtered_html_format),
+    ));
+
+    // Setup a node to comment and test on.
+    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+    $this->node = $this->drupalCreateNode();
+  }
+
+  /**
+   * Tests removal of images having a non-local source.
+   */
+  function testImageSource() {
+    global $base_url;
+
+    $this->drupalLogin($this->web_user);
+
+    $public_files_path = variable_get('file_public_path', conf_path() . '/files');
+
+    $http_base_url = preg_replace('/^https?/', 'http', $base_url);
+    $https_base_url = preg_replace('/^https?/', 'https', $base_url);
+    $files_path = base_path() . $public_files_path;
+    $csrf_path = $public_files_path . '/' . implode('/', array_fill(0, substr_count($public_files_path, '/') + 1, '..'));
+
+    $druplicon = 'core/misc/druplicon.png';
+    $red_x_image = base_path() . 'core/misc/message-16-error.png';
+    $alt_text = t('Image removed.');
+    $title_text = t('This image has been removed. For security reasons, only images from the local domain are allowed.');
+
+    // Put a test image in the files directory.
+    $test_images = $this->drupalGetTestFiles('image');
+    $test_image = $test_images[0]->filename;
+
+    // keys become the value of img src, value is what the filter should convert them to.
+    $images = array(
+      $http_base_url . '/' . $druplicon => base_path() . $druplicon,
+      $https_base_url . '/' . $druplicon => base_path() . $druplicon,
+      base_path() . $druplicon => base_path() . $druplicon,
+      $files_path . '/' . $test_image => $files_path . '/' . $test_image,
+      $http_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
+      $https_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
+      $files_path . '/example.png' => $red_x_image,
+      'http://example.com/' . $druplicon => $red_x_image,
+      'https://example.com/' . $druplicon => $red_x_image,
+      'javascript:druplicon.png' => $red_x_image,
+      $csrf_path . '/logout' => $red_x_image,
+    );
+    $comment = array();
+    foreach ($images as $image => $converted) {
+      // Include the image source for debugging.
+      $comment[] = $image;
+      // Hash image for the test attribute because it might contain characters
+      // confusing xpath.
+      $comment[] = '<img src="' . $image . '" testattribute="' . md5($image) . '" />';
+    }
+    $edit = array(
+      'comment_body[und][0][value]' => implode("\n", $comment),
+    );
+    $this->drupalPost('node/' . $this->node->nid, $edit, t('Save'));
+    foreach ($images as $image => $converted) {
+      $found = FALSE;
+      foreach ($this->xpath('//img[@testattribute="' . md5($image) . '"]') as $element) {
+        $found = TRUE;
+        if ($converted == $red_x_image) {
+          $this->assertEqual((string) $element['src'], $red_x_image);
+          $this->assertEqual((string) $element['alt'], $alt_text);
+          $this->assertEqual((string) $element['title'], $title_text);
+        }
+        else {
+          $this->assertEqual((string) $element['src'], $converted);
+        }
+      }
+      $this->assertTrue($found, t('@image was found.', array('@image' => $image)));
+    }
+  }
+}
