A Composer plugin implementing responsibility propagation for security audits.
Stops upstream/framework transitive dependency advisories from blocking your library, extension, or plugin CI — while keeping them visible in audit reports.
Since Composer 2.9, block-insecure defaults to true, blocking any package version with a security advisory during composer update, require, or remove (and install without a lock file, which triggers dependency resolution). For library/extension developers, this means:
- Your TYPO3 extension requires
typo3/cms-corefor compatibility typo3/cms-coretransitively depends onfirebase/php-jwt- When
firebase/php-jwtgets a security advisory, your CI breaks - You have no control over this — you didn't choose
firebase/php-jwt - The TYPO3 team is responsible for updating their framework dependencies
This affects every framework ecosystem: Drupal modules, Symfony bundles, Laravel packages, WordPress plugins, Magento modules, Shopware plugins, and more.
1. Disable the security check entirely
COMPOSER_NO_SECURITY_BLOCKING=1 composer updateThis silences all advisories — including ones in your own dependencies that you can and should fix. You lose the safety net completely. A real vulnerability in a package you chose goes unnoticed.
2. Manually maintain config.audit.ignore
{
"config": {
"audit": {
"ignore": {
"PKSA-y2cr-5h3j-g3ys": "firebase/php-jwt - framework dep",
"CVE-2024-XXXXX": "some-other/lib - framework dep"
}
}
}
}Every new advisory requires a manual commit to every affected repo. With dozens of extensions and frequent advisories, this becomes a constant maintenance burden. Worse: stale ignore entries accumulate and nobody reviews whether they're still needed — or whether they're now hiding a vulnerability in a package you do control.
Both approaches share the same fundamental flaw: they treat security as all-or-nothing when the real question is who is responsible for which dependency.
Security responsibility follows the dependency chain:
| Role | Responsible For |
|---|---|
| Extension/Plugin developer | Their direct dependencies |
| Framework team | Framework's transitive dependencies |
| Application/Project assembler | Everything (they ship the final product) |
This plugin automatically detects your framework dependencies and prevents their transitive security advisories from blocking dependency resolution (composer update/require/remove). Advisories are still reported — they just don't block.
This plugin must be installed globally — it needs to be loaded before your project's dependencies are resolved.
composer global config allow-plugins.netresearch/composer-audit-responsibility true
composer global require netresearch/composer-audit-responsibilityAdd this step after PHP setup and before composer install:
- name: Install audit-responsibility plugin
run: |
composer global config allow-plugins.netresearch/composer-audit-responsibility true
composer global require netresearch/composer-audit-responsibility --no-interactionNo changes to your project's composer.json are needed.
The plugin auto-detects your framework from the type field in composer.json:
| Package Type | Detected Framework |
|---|---|
typo3-cms-extension |
typo3/cms-core |
symfony-bundle |
symfony/framework-bundle, symfony/http-kernel |
drupal-module |
drupal/core |
wordpress-plugin |
johnpbloch/wordpress-core, roots/wordpress |
magento2-module |
magento/framework |
shopware-platform-plugin |
shopware/core |
contao-bundle |
contao/core-bundle |
cakephp-plugin |
cakephp/cakephp |
neos-plugin |
neos/neos |
flow-package |
neos/flow |
oroplatform-bundle |
oro/platform |
silverstripe-vendormodule |
silverstripe/framework |
pimcore-bundle |
pimcore/pimcore |
laravel-package |
laravel/framework |
yii2-extension |
yiisoft/yii2 |
For projects that use type: library or need custom upstream declarations:
{
"extra": {
"audit-responsibility": {
"upstream": ["typo3/cms-core", "helhum/typo3-console"]
}
}
}If you have the plugin installed globally but want a specific extension/library to opt out (i.e., have all advisories block normally):
{
"extra": {
"audit-responsibility": {
"block-upstream": true
}
}
}Note: Application projects (
type: projectortype: librarywithout explicitupstreamconfig) are never affected by this plugin — it only activates for framework-specific package types (extensions, bundles, modules, plugins). No configuration needed to exclude them.
- Detection — Identifies platform/framework packages from your
typeor explicit config - Graph analysis — Walks the dependency graph (BFS) to classify every package:
- Direct: In your
require— your responsibility - Platform-only: Only reachable through framework packages — framework's responsibility
- Shared: Reachable through both your deps AND framework — your responsibility (conservative)
- User-transitive: Only reachable through your non-framework deps — your responsibility
- Direct: In your
- Policy enforcement — Platform-only advisories don't block; everything else still blocks normally
When a package is reachable through both your dependencies AND the framework:
your-extension
├── typo3/cms-core → psr/log (platform path)
└── my/logging-lib → psr/log (user path)
Conservative rule: If you have ANY dependency path to a package, it's your responsibility. psr/log blocks in this case because you chose my/logging-lib which also depends on it.
| Approach | Scope | Maintenance | Visibility |
|---|---|---|---|
config.audit.ignore per advisory |
Per-advisory | Update for every new advisory | Hidden |
COMPOSER_NO_SECURITY_BLOCKING=1 |
All deps | None | Hidden |
| This plugin | Framework deps only | None (auto-detected) | Preserved |
- PHP >= 8.1
- Composer >= 2.9
MIT License. See LICENSE for details.
Contributions are welcome! Please open an issue or pull request on GitHub.