diff --git a/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php b/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php
new file mode 100644
index 0000000..eca6054
--- /dev/null
+++ b/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\System\SitesDirectoryHardeningTest.
+ */
+
+namespace Drupal\system\Tests\System;
+
+use Drupal\Core\Site\Settings;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests Drupal permissions hardening of /sites subdirectories.
+ *
+ * @group system
+ */
+class SitesDirectoryHardeningTest extends WebTestBase {
+  use StringTranslationTrait;
+
+
+  /**
+   * Test that the default behavior to restrict permissions on the current
+   * sites directory and on settings.php is enforced.
+   */
+  public function testSitesDirectoryHardening() {
+    $site_path = $this->kernel->getSitePath();
+    $settings_file = $this->settingsFile($site_path);
+
+    // First, we check based on what the initial install has set.
+    $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), $this->t('Verified permissions for @file.', array('@file' => $site_path)));
+
+    // We intentionally don't check for settings.local.php as that file is
+    // not created by Drupal.
+    $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE), $this->t('Verified permissions for @file.', array('@file' => $settings_file)));
+
+    $this->makeWritable($site_path);
+    $this->checkSystemRequirements();
+
+    $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), $this->t('Verified permissions for @file after manual permissions change.', array('@file' => $site_path)));
+    $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE), $this->t('Verified permissions for @file after manual permissions change.', array('@file' => $settings_file)));
+  }
+
+  /**
+   * Test that when when directory hardening is disabled that a writable file
+   * remains writable.
+   */
+  public function testSitesDirectoryHardeningConfig() {
+    $site_path = $this->kernel->getSitePath();
+    $settings_file = $this->settingsFile($site_path);
+
+    // Disable permissions enforcement.
+    $settings = Settings::getAll();
+    $settings['skip_permissions_hardening'] = TRUE;
+    new Settings($settings);
+    $this->assertTrue(Settings::get('skip_permissions_hardening'), $this->t('Able to set hardening to true'));
+    $this->makeWritable($site_path);
+
+    // Manually trigger the requirements check.
+    $requirements = $this->checkSystemRequirements();
+    $this->assertEqual(REQUIREMENT_WARNING, $requirements['configuration_files']['severity'], $this->t('Warning severity is properly set.'));
+    $this->assertEqual($this->t('Protection disabled'), (string) $requirements['configuration_files']['description']['#context']['configuration_error_list']['#items'][0], $this->t('Description is properly set.'));
+
+    $this->assertTrue(is_writable($site_path), $this->t('Site directory remains writable when automatically fixing permissions is disabled.'));
+    $this->assertTrue(is_writable($settings_file), $this->t('settings.php remains writable when automatically fixing permissions is disabled.'));
+
+    // Re-enable permissions enforcement.
+    $settings = Settings::getAll();
+    $settings['skip_permissions_hardening'] = FALSE;
+    new Settings($settings);
+
+    // Manually trigger the requirements check.
+    $this->checkSystemRequirements();
+
+    $this->assertFalse(is_writable($site_path), $this->t('Site directory is protected when automatically fixing permissions is enabled.'));
+    $this->assertFalse(is_writable($settings_file), $this->t('settings.php is protected when automatically fixing permissions is enabled.'));
+  }
+
+  /**
+   * Check system runtime requirements.
+   *
+   * @return array
+   *   An array of system requirements.
+   */
+  protected function checkSystemRequirements() {
+    module_load_install('system');
+    return system_requirements('runtime');
+  }
+
+  /**
+   * Make the given path and settings file writable.
+   *
+   * @param string $site_path
+   *   The sites directory path, such as 'sites/default'.
+   */
+  protected function makeWritable($site_path) {
+    chmod($site_path, 0755);
+    chmod($this->settingsFile($site_path), 0644);
+  }
+
+  /**
+   * Return the path to settings.php
+   *
+   * @param string $site_path
+   *   The sites subdirectory path.
+   *
+   * @return string
+   *   The path to settings.php.
+   */
+  protected function settingsFile($site_path) {
+    $settings_file = $site_path . '/settings.php';
+    return $settings_file;
+  }
+}
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index c9e8175..db07e31 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -365,13 +365,22 @@ function system_requirements($phase) {
     else {
       $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
     }
-    if (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {
+    // Allow system administrators to ignore permissions hardening for the site
+    // directory. This allows additional files in the site directory to be
+    // updated when they are managed in a version control system.
+    if (Settings::get('skip_permissions_hardening')) {
+      $conf_errors[] = t('Protection disabled');
+      $severity = REQUIREMENT_WARNING;
+    }
+    elseif (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {
       $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $site_path));
+      $severity = REQUIREMENT_ERROR;
     }
     foreach (array('settings.php', 'settings.local.php', 'services.yml') as $conf_file) {
       $full_path = $site_path . '/' . $conf_file;
-      if (file_exists($full_path) && !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE)) {
+      if (file_exists($full_path) && (Settings::get('skip_permissions_hardening') || !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE))) {
         $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array('%file' => $full_path));
+        $severity = min($severity, REQUIREMENT_ERROR);
       }
     }
     if (!empty($conf_errors)) {
@@ -393,7 +402,7 @@ function system_requirements($phase) {
       }
       $requirements['configuration_files'] = array(
         'value' => t('Not protected'),
-        'severity' => REQUIREMENT_ERROR,
+        'severity' => $severity,
         'description' => $description,
       );
     }
diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php
index a5d50f2..0626967 100644
--- a/sites/example.settings.local.php
+++ b/sites/example.settings.local.php
@@ -90,3 +90,17 @@
  * using these parameters in a request to rebuild.php.
  */
 $settings['rebuild_access'] = TRUE;
+
+/**
+ * Skip file system permissions hardening.
+ *
+ * The system module will periodically check the permissions of your site's
+ * site directory to ensure that it is not writable by the website user. For
+ * sites that are managed with a version control system, this can cause problems
+ * when files in that directory (such as a "settings.inc" containing additional
+ * configuration) are updated, because the user pulling in the changes won't
+ * have permissions to modify files in the directory.
+ *
+ * Remove the leading hash sign to disable permissions hardening.
+ */
+$settings['skip_permissions_hardening'] = TRUE;
