{"record":{"id":"4f6690f7c1df141f","repo":"composer/composer","slug":"package-global-suffix-contains-a-composer-plugi","errorCode":null,"errorMessage":"{package}{global_suffix} contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.\nYou can run \"composer {global_prefix}config --no-plugins allow-plugins.{package} [true|false]\" to enable it (true) or disable it explicitly and suppress this exception (false)\nSee https://getcomposer.org/allow-plugins","messagePattern":"(.+?)(.+?) contains a Composer plugin which is blocked by your allow-plugins config\\. You may add it to the list if you consider it safe\\.\nYou can run \"composer (.+?)config --no-plugins allow-plugins\\.(.+?) \\[true\\|false\\]\" to enable it \\(true\\) or disable it explicitly and suppress this exception \\(false\\)\nSee https://getcomposer\\.org/allow-plugins","errorType":"exception","errorClass":"PluginBlockedException","httpStatus":null,"severity":"error","filePath":"src/Composer/Plugin/PluginManager.php","lineNumber":821,"sourceCode":"                        return $allow;\n\n                    case '?':\n                    default:\n                        $attempts++;\n                        $this->io->writeError([\n                            'y - add package to allow-plugins in composer.json and let it run immediately',\n                            'n - add package (as disallowed) to allow-plugins in composer.json to suppress further prompts',\n                            'd - discard this, do not change composer.json and do not allow the plugin to run',\n                            '? - print help',\n                        ]);\n                        break;\n                }\n            }\n        } elseif ($optional) {\n            return false;\n        }\n\n        throw new PluginBlockedException(\n            $package.($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '').' contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.'.PHP_EOL.\n            'You can run \"composer '.($isGlobalPlugin || $this->runningInGlobalDir ? 'global ' : '').'config --no-plugins allow-plugins.'.$package.' [true|false]\" to enable it (true) or disable it explicitly and suppress this exception (false)'.PHP_EOL.\n            'See https://getcomposer.org/allow-plugins'\n        );\n    }\n}\n","sourceCodeStart":803,"sourceCodeEnd":828,"githubUrl":"https://github.com/composer/composer/blob/c435d285c9120efdca35696769c72ea9fdcc0466/src/Composer/Plugin/PluginManager.php#L803-L828","documentation":"Thrown by PluginManager as a PluginBlockedException when a Composer plugin package is not explicitly allowed (or disallowed) in the 'config.allow-plugins' map of composer.json and the user did not authorize it interactively (or the session is non-interactive). Since Composer 2.2 plugins run only when whitelisted, to prevent arbitrary code execution from dependencies. The message tells you exactly how to allow or block it via config.","triggerScenarios":"During dependency resolution/install, PluginManager::arePluginsAllowed() finds the package missing from allow-plugins; the interactive prompt (y/n/d/?) either was never shown (non-interactive) or the user exhausted attempts. Reached via PluginManager::loadRepository() / registerPackage() when a package provides Composer\\Plugin\\PluginInterface.","commonSituations":"Upgrading to Composer 2.2+ where allow-plugins is required; CI runs (non-interactive) where a new plugin dependency triggers the block; a fresh 'composer require' of a package that ships a plugin (e.g. composer-require-fixer, phpstan/extension-installer).","solutions":["Run the exact command from the message: composer config --no-plugins allow-plugins.<package> true to allow it (or false to suppress).","For global plugins, prefix with 'global': composer global config --no-plugins allow-plugins.<package> true.","Add the full allow-plugins map to composer.json config and commit it so CI is reproducible.","In CI, ensure the runner is non-interactive only AFTER allow-plugins is configured, or set COMPOSER_NO_INTERACTION=1 after committing the list."],"exampleFix":"// before\n{ \"config\": {} }\n// after\n{\n  \"config\": {\n    \"allow-plugins\": {\n      \"phpstan/extension-installer\": true,\n      \"dealerdirect/phpcodesniffer-composer-installer\": true\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"// Pre-check allow-plugins config before running install in CI\n$pkg = 'phpstan/extension-installer';\n$cfg = json_decode(file_get_contents('composer.json'), true);\n$allowed = $cfg['config']['allow-plugins'] ?? [];\nif (!array_key_exists($pkg, $allowed)) {\n    // explicitly allow or disallow to avoid the interactive block\n    $cfg['config']['allow-plugins'][$pkg] = true;\n    file_put_contents('composer.json', json_encode($cfg, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));\n}","typeGuard":"function pluginIsDecided(string $pkg, array $config): bool {\n    return array_key_exists($pkg, $config['config']['allow-plugins'] ?? []);\n}","tryCatchPattern":"try {\n    // run composer operation\n} catch (\\Composer\\Plugin\\PluginBlockedException $e) {\n    // parse package name, prompt user, then run the suggested config command\n    throw $e;\n}","preventionTips":["Commit an explicit 'allow-plugins' map in composer.json for every plugin you use.","Run 'composer install' once interactively after adding a plugin dependency to seed the config.","In CI set --no-interaction only after the allow-plugins map is committed."],"tags":["plugins","allow-plugins","security","config","composer-json"],"backgroundTag":null,"analyzedSha":"c435d285c9120efdca35696769c72ea9fdcc0466","analyzedAt":"2026-08-07T18:58:23.525Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}