, (*1)
Drupal Paranoia
Composer plugin for improving the website security for composer-based Drupal websites by moving all PHP files out of docroot., (*2)
Why use this Plugin?
The critical security issue with Coder is a good example to consider moving PHP files outside of docroot:
- SA-CONTRIB-2016-039 - Remote Code Execution
- https://twitter.com/drupalsecurity/status/753263548458004480, (*3)
More related links:
- Moving all PHP files out of the docroot
- #1672986: Option to have all php files outside of web root, (*4)
Requirements
Except for Windows, this plugin should work on environments that have Composer support. Do you use Windows? Help us., (*5)
Installation
Make sure you have a based drupal-composer/drupal-project project created., (*6)
Rename your current docroot directory to /app
., (*7)
cd drupal-project-root
mv web app
Update the composer.json
of your root package with the following values:, (*8)
"extra": {
"drupal-paranoia": {
"app-dir": "app",
"web-dir": "web"
},
"installer-paths": {
"app/core": ["type:drupal-core"],
"app/libraries/{$name}": ["type:drupal-library"],
"app/modules/contrib/{$name}": ["type:drupal-module"],
"app/profiles/contrib/{$name}": ["type:drupal-profile"],
"app/themes/contrib/{$name}": ["type:drupal-theme"],
"drush/contrib/{$name}": ["type:drupal-drush"]
}
}
Explaining:
- /app folder: Drupal full installation.
- /web folder: Will contain only symlinks of the assets files and PHP stub files (index.php, install.php, etc) from the /app
folder., (*9)
Use composer require ...
to install this Plugin on your project., (*10)
composer require drupal-composer/drupal-paranoia:~1
Done! The plugin and the new docroot are now installed., (*11)
Asset file types
The asset files are symlinked from /app
to /web
folder., (*12)
Default asset file types are provided by the plugin:, (*13)
robots.txt
.htaccess
*.css
*.eot
*.ico
*.gif
*.jpeg
*.jpg
*.js
*.map
*.otf
*.png
*.svg
*.ttf
*.woff
*.woff2
To extend the list of assets file types you can use the asset-files
config:, (*14)
"extra": {
"drupal-paranoia": {
"app-dir": "app",
"web-dir": "web",
"asset-files": [
"somefile.txt",
"*.md"
]
},
"..."
}
If you need to modify the list you can use the post-drupal-set-asset-file-types
event:, (*15)
"scripts": {
"post-drupal-set-asset-file-types": [
"DrupalProject\\composer\\ScriptHandler::setAssetFileTypes"
],
"..."
},
<?php
/**
* @file
* Contains \DrupalProject\composer\ScriptHandler.
*/
namespace DrupalProject\composer;
use DrupalComposer\DrupalParanoia\AssetFileTypesEvent;
class ScriptHandler {
public static function setAssetFileTypes(AssetFileTypesEvent $event) {
$asset_file_types = $event->getAssetFileTypes();
// Do what you want with the asset file types.
$event->setAssetFileTypes($asset_file_types);
}
}
By the purpose of this plugin, the following files types are not allowed and if listed they will be ignored:, (*16)
*.inc
*.install
*.module
*.phar
*.php
*.profile
*.theme
Exclude paths
With the drupal-paranoia option excludes, you can provide paths that should not be symlinked or stubbed to /web
folder. The plugin provides no excludes by default., (*17)
"extra": {
"drupal-paranoia": {
"app-dir": "app",
"web-dir": "web",
"excludes": [
"core/install.php",
"sites/simpletest"
]
},
"..."
}
NOTE: Consider to exclude /install.php
from your site. There are security concerns when this URL is publicly available, it can be used to create a list of contributed modules existing on the site.
You can exclude it via plugin as described above or via .htaccess
rules.
- DO#2840973: Install system should not produce PHP errors
- https://www.drupalxray.com, (*18)
Web server docroot
Change the document root config of your web server to point to /web
folder., (*19)
Plugin events
This plugin fires the following named event during its execution process:, (*20)
-
drupal-paranoia-post-command-run: Occurs after the command
drupal:paranoia
is executed.
Example of event subscriber
<?php
namespace MyVendor;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use DrupalComposer\DrupalParanoia\PluginEvents as DrupalParanoiaPluginEvents;
class MyClass implements PluginInterface, EventSubscriberInterface
{
protected $composer;
protected $io;
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;
}
public static function getSubscribedEvents()
{
return array(
DrupalParanoiaPluginEvents::POST_COMMAND_RUN => 'postDrupalParanoiaCommand',
);
}
public function postDrupalParanoiaCommand(CommandEvent $event) {
// Add your custom action.
}
}
Local development
Every time you install or update a Drupal package via Composer, the /web
folder will be recreated., (*21)
composer require drupal/devel:~1.0
> drupal-paranoia: docroot folder has been rebuilt.
When working with themes, CSS and JS for example, it may be necessary to rebuild the folder manually to symlink the new assets., (*22)
composer drupal:paranoia
Public files
This plugin assumes that the public files folder exists at app/sites/<site>/files
and symlinks web/sites/<site>/files -> ../../../app/sites/<site>/files
., (*23)