Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Core Vendor Hardening Laravel Package

drupal/core-vendor-hardening

Composer plugin for Drupal that hardens the vendor directory by stripping unnecessary files such as tests, documentation, and version-control metadata from dependencies. It reduces deployment size and attack surface while keeping required code intact.

Deep Wiki
Context7

Getting Started

drupal/core-vendor-hardening is a Composer plugin that strips development files (tests, docs, .git, etc.) out of vendor/ packages and drops an .htaccess/web.config deny file into the vendor directory — but only meaningfully when vendor/ is web-accessible.

  1. Install it:

    composer require drupal/core-vendor-hardening
    

    Put it in require (not require-dev) if production installs must harden; a --no-dev build will not install a dev-only plugin and therefore will not run it.

  2. Allow the plugin under Composer 2:

    "config": {
      "allow-plugins": {
        "drupal/core-vendor-hardening": true
      }
    }
    
  3. Point it at the web root in the root composer.json:

    "extra": {
      "drupal-core-vendor-hardening": {
        "web-root": "."
      }
    }
    

    Use "." for a flat layout where the project root is the docroot, or "web" if the docroot is web/ and vendor/ was moved inside it.

  4. Run composer install or composer update and verify the result:

    ls -la vendor/.htaccess
    ls vendor/some/package
    

Where to look first: the extra.drupal-core-vendor-hardening block in composer.json, then the plugin source (typically src/VendorHardeningPlugin.php in the package) to see the exact cleanup patterns and event subscriptions. composer install -vvv and COMPOSER_DEBUG_EVENTS=1 show when the plugin fires.

First use case: a legacy flat-docroot deployment where your only web server protection for vendor/ is Apache .htaccess, and you want to shrink the deploy artifact by removing test suites and docs from every package.

Implementation Patterns

Flat-docroot hardening (the intended case). Configure "web-root": "." so the plugin recognizes vendor/ as inside the docroot. On post-install/post-update it writes vendor/.htaccess with Require all denied / Deny from all and prunes configured junk files from each installed package.

Verify in CI. Add a cheap assertion so a future config change doesn't silently turn hardening off:

test -f vendor/.htaccess || { echo "vendor hardening not applied"; exit 1; }
grep -q "Deny from all\|Require all denied" vendor/.htaccess

Deploy pipeline. If the plugin lives in require-dev, build artifacts in a stage that installs dev dependencies, run hardening, then produce the production tree. If it lives in require, a plain composer install --no-dev --optimize-autoloader during deploy is enough — but remember the plugin must actually be installed for it to run.

Pair with drupal/core-composer-scaffold. Scaffold copies files into the web root; vendor hardening prunes the vendor tree. Keep scaffold config explicit and run a full composer install after changing either so both plugins re-execute.

Complement with server config (nginx). The plugin only writes Apache/IIS files. For nginx, add explicitly:

location ^~ /vendor/ { deny all; return 404; }

Customization is limited. The cleanup list is largely baked into the plugin; per-package whitelists are not a first-class option. If one package breaks, the practical paths are (a) patch the plugin with cweagans/composer-patches, (b) fork it, or (c) accept the hardcoded list and document the exception.

Gotchas and Tips

  • Silent no-op when vendor is outside the web root. This is the big one. With the standard modern layout (vendor/ at project root, docroot web/), the plugin has nothing to protect and effectively does nothing. Confirm the vendor path actually sits under the configured web-root before expecting results.
  • --no-scripts and --no-plugins kill it. --no-plugins is obvious; --no-scripts suppresses the script-event hooks, so the post-command pass won't run. Package-level install events may still fire, which can lead to partially hardened trees — verify after any unusual install invocation.
  • Dev-vs-prod dependency placement. A plugin in require-dev plus composer install --no-dev in production equals no hardening at deploy time. Pick deliberately and test the exact production command.
  • Removing files can break runtime autoloads. It's rare, but some packages load fixtures or templates from tests/ or docs/. If a package starts throwing "file not found" after enabling the plugin, diff the vendor tree (git diff --no-index) to see what was pruned.
  • Apache-only protection. .htaccess does nothing on nginx, Caddy, or a CDN origin. Always pair with server-level deny rules.
  • Windows/IIS. The plugin drops web.config; don't strip it from your deploy artifact.
  • Permissions. The plugin writes into vendor/; ensure the build user owns it, otherwise composer install fails halfway through.
  • Config changes require a re-run. Editing web-root won't retroactively harden an existing tree — run composer install (or composer update) again.
  • Symlinked vendor directories. Path containment checks can misbehave when vendor/ is a symlink; keep it a real directory.
  • Legacy posture. Low star count and Drupal 8/9-era origins mean compatibility with current Composer/PHP versions should be validated on a branch before rolling it out. If your layout already keeps vendor/ outside the docroot, skip this package entirely.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource