diff --git a/composer/Plugin/VendorHardening/FileSecurity.php b/composer/Plugin/VendorHardening/FileSecurity.php
new file mode 100644
index 000000000000..c8bcd6d328da
--- /dev/null
+++ b/composer/Plugin/VendorHardening/FileSecurity.php
@@ -0,0 +1,164 @@
+
+ # Override the handler again if we're run later in the evaluation list.
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+
+
+# If we know how to do it safely, disable the PHP engine entirely.
+
+ php_flag engine off
+
+
+ php_flag engine off
+
+EOF;
+ }
+
+ /**
+ * Returns htaccess directives to block all access to a given directory.
+ *
+ * @return string
+ * Apache htaccess directives to block access to a location.
+ */
+ protected static function denyPublicAccess() {
+ return <<
+ Require all denied
+
+
+# Deny all requests from Apache 2.0-2.2.
+
+ Deny from all
+
+EOF;
+ }
+
+ /**
+ * Writes a web.config file in the given directory, if it doesn't exist.
+ *
+ * @param string $directory
+ * The directory.
+ * @param bool $force
+ * (optional) Set to TRUE to force overwrite an existing file.
+ *
+ * @return bool
+ * TRUE if the file already exists or was created. FALSE otherwise.
+ */
+ public static function writeWebConfig($directory, $force = FALSE) {
+ return self::writeFile($directory, '/web.config', self::webConfigLines(), $force);
+ }
+
+ /**
+ * Returns the standard web.config lines for security.
+ *
+ * @return string
+ * The contents of the web.config file.
+ */
+ public static function webConfigLines() {
+ return <<
+
+
+
+
+
+
+EOT;
+ }
+
+ /**
+ * Writes the contents to the file in the given directory.
+ *
+ * @param string $directory
+ * The directory to write to.
+ * @param string $filename
+ * The file name.
+ * @param string $contents
+ * The file contents.
+ * @param bool $force
+ * TRUE if we should force the write over an existing file.
+ *
+ * @return bool
+ * TRUE if writing the file was successful.
+ */
+ protected static function writeFile($directory, $filename, $contents, $force) {
+ $file_path = $directory . DIRECTORY_SEPARATOR . $filename;
+ // Don't overwrite if the file exists unless forced.
+ if (file_exists($file_path) && !$force) {
+ return TRUE;
+ }
+ if (file_exists($directory) && is_writable($directory) && file_put_contents($file_path, $contents)) {
+ return @chmod($file_path, 0444);
+ }
+ return FALSE;
+ }
+
+}
diff --git a/composer/Plugin/VendorHardening/VendorHardeningPlugin.php b/composer/Plugin/VendorHardening/VendorHardeningPlugin.php
index cf049003669f..7e36e0e9e184 100644
--- a/composer/Plugin/VendorHardening/VendorHardeningPlugin.php
+++ b/composer/Plugin/VendorHardening/VendorHardeningPlugin.php
@@ -11,7 +11,6 @@ use Composer\Script\ScriptEvents;
use Composer\Util\Filesystem;
use Composer\Script\Event;
use Composer\Installer\PackageEvents;
-use Drupal\Component\FileSecurity\FileSecurity;
/**
* A Composer plugin to clean out your project's vendor directory.
diff --git a/composer/Plugin/VendorHardening/composer.json b/composer/Plugin/VendorHardening/composer.json
index 3bafc9a7858d..da71b12a1f3f 100644
--- a/composer/Plugin/VendorHardening/composer.json
+++ b/composer/Plugin/VendorHardening/composer.json
@@ -15,7 +15,6 @@
},
"require": {
"php": ">=7.0.8",
- "composer-plugin-api": "^1.1",
- "drupal/core-file-security": "^8.8"
+ "composer-plugin-api": "^1.1"
}
}
diff --git a/core/lib/Drupal/Component/FileSecurity/FileSecurity.php b/core/lib/Drupal/Component/FileSecurity/FileSecurity.php
index efe1119c2707..8673d3c2ab29 100644
--- a/core/lib/Drupal/Component/FileSecurity/FileSecurity.php
+++ b/core/lib/Drupal/Component/FileSecurity/FileSecurity.php
@@ -4,6 +4,10 @@ namespace Drupal\Component\FileSecurity;
/**
* Provides file security functions.
+ *
+ * IMPORTANT: This file is duplicated at /composer/Plugin/VendorHardening.
+ * If any change is made here, the same change should be made in the duplicate.
+ * See https://www.drupal.org/project/drupal/issues/3079481
*/
class FileSecurity {