diff --git a/core/modules/filter/src/Entity/FilterFormat.php b/core/modules/filter/src/Entity/FilterFormat.php
index 944d5c7cd311b748c519290552b7a4408bfa9140..6f2be4de250a3acd10c5ae015df035d5860b2d43 100644
--- a/core/modules/filter/src/Entity/FilterFormat.php
+++ b/core/modules/filter/src/Entity/FilterFormat.php
@@ -97,7 +97,7 @@ class FilterFormat extends ConfigEntityBase implements FilterFormatInterface, En
    *
    * An associative array of filters assigned to the text format, keyed by the
    * instance ID of each filter and using the properties:
-   * - plugin_id: The plugin ID of the filter plugin instance.
+   * - id: The plugin ID of the filter plugin instance.
    * - module: The name of the module providing the filter.
    * - status: (optional) A Boolean indicating whether the filter is
    *   enabled in the text format. Defaults to FALSE.
@@ -193,9 +193,6 @@ public function preSave(EntityStorageInterface $storage) {
     parent::preSave($storage);
 
     $this->name = trim($this->label());
-
-    // @todo Do not save disabled filters whose properties are identical to
-    //   all default properties.
   }
 
   /**
diff --git a/core/modules/filter/src/FilterBag.php b/core/modules/filter/src/FilterBag.php
index 970e7e8267f8e01d0b8d09d9f85156e16d0ed0ee..f509847f29d1f1c05b9464fca1ddc1e7c4b6d0c1 100644
--- a/core/modules/filter/src/FilterBag.php
+++ b/core/modules/filter/src/FilterBag.php
@@ -107,4 +107,26 @@ public function sortHelper($aID, $bID) {
     return parent::sortHelper($aID, $bID);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfiguration() {
+    $configuration = parent::getConfiguration();
+    // Remove configuration if it matches the defaults. In self::getAll(), we
+    // load all available filters, in addition to the enabled filters stored in
+    // configuration. In order to prevent those from bleeding through to the
+    // stored configuration, remove all filters that match the default values.
+    // Because filters are disabled by default, this will never remove the
+    // configuration of an enabled filter.
+    foreach ($configuration as $instance_id => $instance_config) {
+      $default_config = array();
+      $default_config['id'] = $instance_id;
+      $default_config += $this->get($instance_id)->defaultConfiguration();
+      if ($default_config === $instance_config) {
+        unset($configuration[$instance_id]);
+      }
+    }
+    return $configuration;
+  }
+
 }
diff --git a/core/modules/filter/src/Plugin/FilterBase.php b/core/modules/filter/src/Plugin/FilterBase.php
index cfed8acfa2c59c079b265b88a381107e72fec364..5314ad7655a178987fb1e3f547057f1d4598a9dd 100644
--- a/core/modules/filter/src/Plugin/FilterBase.php
+++ b/core/modules/filter/src/Plugin/FilterBase.php
@@ -107,7 +107,12 @@ public function getConfiguration() {
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
-    return array();
+    return array(
+      'provider' => $this->pluginDefinition['provider'],
+      'status' => FALSE,
+      'weight' => $this->pluginDefinition['weight'] ?: 0,
+      'settings' => $this->pluginDefinition['settings'],
+    );
   }
 
   /**
diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php
index 9e524203240e8bbd1063e51d1d9e670c46f2821a..f575ec3161c007b99784077518f17b36984a88c5 100644
--- a/core/modules/filter/src/Tests/FilterAPITest.php
+++ b/core/modules/filter/src/Tests/FilterAPITest.php
@@ -328,6 +328,50 @@ function testTypedDataAPI() {
     $this->assertEqual($allowed_options, $expected_allowed_options);
   }
 
+  /**
+   * Tests that FilterFormat::preSave() only saves customized plugins.
+   */
+  public function testFilterFormatPreSave() {
+    /** @var \Drupal\filter\FilterFormatInterface $crazy_format */
+    $crazy_format = entity_create('filter_format', array(
+      'format' => 'crazy',
+      'name' => 'Crazy',
+      'weight' => 1,
+      'filters' => array(
+        'filter_html_escape' => array(
+          'weight' => 10,
+          'status' => 1,
+        ),
+        'filter_html' => array(
+          'weight' => -10,
+          'status' => 1,
+          'settings' => array(
+            'allowed_html' => '<p>',
+          ),
+        ),
+      )
+    ));
+    $crazy_format->save();
+    // Use config to directly load the configuration and check that only enabled
+    // or customized plugins are saved to configuration.
+    $filters = \Drupal::config('filter.format.crazy')->get('filters');
+    $this->assertEqual(array('filter_html_escape', 'filter_html'), array_keys($filters));
+
+    // Disable a plugin to ensure that disabled plugins with custom settings are
+    // stored in configuration.
+    $crazy_format->setFilterConfig('filter_html_escape', array('status' => FALSE));
+    $crazy_format->save();
+    $filters = \Drupal::config('filter.format.crazy')->get('filters');
+    $this->assertEqual(array('filter_html_escape', 'filter_html'), array_keys($filters));
+
+    // Set the settings as per default to ensure that disable plugins in this
+    // state are not stored in configuration.
+    $crazy_format->setFilterConfig('filter_html_escape', array('weight' => -10));
+    $crazy_format->save();
+    $filters = \Drupal::config('filter.format.crazy')->get('filters');
+    $this->assertEqual(array('filter_html'), array_keys($filters));
+  }
+
   /**
    * Checks if an expected violation exists in the given violations.
    *
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateFilterFormatTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateFilterFormatTest.php
index c1529b8b6bfb7cecc5b5ddddc8a0c028b82e83d1..807e4f56ca2b621185a51f49c821a9415a63eec3 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateFilterFormatTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateFilterFormatTest.php
@@ -50,9 +50,9 @@ public function testFilterFormat() {
     $this->assertTrue($filters['filter_html']['status']);
 
     // These should be false by default.
-    $this->assertFalse($filters['filter_html_escape']['status']);
-    $this->assertFalse($filters['filter_caption']['status']);
-    $this->assertFalse($filters['filter_html_image_secure']['status']);
+    $this->assertFalse(isset($filters['filter_html_escape']));
+    $this->assertFalse(isset($filters['filter_caption']));
+    $this->assertFalse(isset($filters['filter_html_image_secure']));
 
     // Check variables migrated into filter.
     $this->assertIdentical($filters['filter_html']['settings']['allowed_html'], '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>');
diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install
index 30656be298362153b3c63f726623c7dc16015631..f588cd3e7deccc4274b838f355f269d2d570f914 100644
--- a/core/profiles/standard/standard.install
+++ b/core/profiles/standard/standard.install
@@ -78,11 +78,4 @@ function standard_install() {
 
   // Enable the admin theme.
   \Drupal::config('node.settings')->set('use_admin_theme', '1')->save();
-
-  // @todo Remove in https://www.drupal.org/node/2295129.
-  // Resave the plain_text formatter so that default filter plugins and
-  // dependencies are calculated correctly. This resolves an issue caused by the
-  // fact that filter is installed before editor but the standard profile also
-  // enables the file module.
-  entity_load('filter_format', 'plain_text')->save();
 }