Browse Source

Add htaccess-protect option for disabling the creation of .htaccess files

Wil Hall 7 years ago
parent
commit
f0924fb878

+ 6 - 0
doc/06-config.md

@@ -265,4 +265,10 @@ Example:
 }
 ```
 
+## htaccess-protect
+
+Defaults to `true`. If set to `false`, Composer will not create `.htaccess` files in the composer home, cache, and data directories.
+
+Previously, Composer unconditionally created these files to mitigate the potential for someone to expose these directories under their Apache document root. The default value of this option preserves the previous behavior.
+
 ← [Repositories](05-repositories.md)  |  [Community](07-community.md) →

+ 4 - 0
res/composer-schema.json

@@ -274,6 +274,10 @@
                 "archive-dir": {
                     "type": "string",
                     "description": "The default archive path when not provided on cli, defaults to \".\"."
+                },
+                "htaccess-protect": {
+                    "type": "boolean",
+                    "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
                 }
             }
         },

+ 2 - 0
src/Composer/Config.php

@@ -60,6 +60,7 @@ class Config
         'platform' => array(),
         'archive-format' => 'tar',
         'archive-dir' => '.',
+        'htaccess-protect' => true,
         // valid keys without defaults (auth config stuff):
         // bitbucket-oauth
         // github-oauth
@@ -215,6 +216,7 @@ class Config
             case 'cache-vcs-dir':
             case 'cafile':
             case 'capath':
+            case 'htaccess-protect':
                 // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
                 $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
 

+ 12 - 9
src/Composer/Factory.php

@@ -164,16 +164,19 @@ class Factory
             'data-dir' => self::getDataDir($home),
         )));
 
-        // Protect directory against web access. Since HOME could be
-        // the www-data's user home and be web-accessible it is a
-        // potential security risk
-        $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
-        foreach ($dirs as $dir) {
-            if (!file_exists($dir . '/.htaccess')) {
-                if (!is_dir($dir)) {
-                    Silencer::call('mkdir', $dir, 0777, true);
+        $htaccessProtect = (bool) $config->get('htaccess-protect');
+        if ($htaccessProtect) {
+            // Protect directory against web access. Since HOME could be
+            // the www-data's user home and be web-accessible it is a
+            // potential security risk
+            $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
+            foreach ($dirs as $dir) {
+                if (!file_exists($dir . '/.htaccess')) {
+                    if (!is_dir($dir)) {
+                        Silencer::call('mkdir', $dir, 0777, true);
+                    }
+                    Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
                 }
-                Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
             }
         }
 

+ 8 - 0
tests/Composer/Test/ConfigTest.php

@@ -310,4 +310,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(0, $config->get('process-timeout'));
         putenv('COMPOSER_PROCESS_TIMEOUT');
     }
+
+    public function testHtaccessProtect()
+    {
+        putenv('COMPOSER_HTACCESS_PROTECT=0');
+        $config = new Config(true);
+        $this->assertEquals(0, $config->get('htaccess-protect'));
+        putenv('COMPOSER_HTACCESS_PROTECT');
+    }
 }