Skip to content

Commit

Permalink
Fix handling of plugin activation when running as root
Browse files Browse the repository at this point in the history
When running without `COMPOSER_ALLOW_SUPERUSER` set so it always happens after prompting, or does not happen if input is non-interactive.

Also fixed support for bash completions hanging when running as root

Fixes #11024
  • Loading branch information
Seldaek committed Sep 14, 2022
1 parent d6411ff commit a75fbf0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,7 @@
### [2.4.2] 2022-09-14

* Fixed bash completion hanging when running as root without `COMPOSER_ALLOW_SUPERUSER` set (#11024)
* Fixed handling of plugin activation when running as root without `COMPOSER_ALLOW_SUPERUSER` set so it always happens after prompting, or does not happen if input is non-interactive
* Fixed package filter on `bump` command (#11053)
* Fixed handling of --ignore-platform-req with upper-bound ignores to not apply to conflict rules (#11037)
* Fixed handling of `COMPOSER_DISCARD_CHANGES` when set to `0`
Expand Down
69 changes: 48 additions & 21 deletions src/Composer/Console/Application.php
Expand Up @@ -205,6 +205,28 @@ public function doRun(InputInterface $input, OutputInterface $output): int
}
}

$needsSudoCheck = !Platform::isWindows()
&& function_exists('exec')
&& !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER')
&& (ini_get('open_basedir') || !file_exists('/.dockerenv'));
$isNonAllowedRoot = false;

// Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins
if ($needsSudoCheck) {
$isNonAllowedRoot = function_exists('posix_getuid') && posix_getuid() === 0;

if ($isNonAllowedRoot) {
if ($uid = (int) Platform::getEnv('SUDO_UID')) {
// Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
// ref. https://github.com/composer/composer/issues/5119
Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
}
}

// Silently clobber any remaining sudo leases on the current user as well to avoid privilege escalations
Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
}

// avoid loading plugins/initializing the Composer instance earlier than necessary if no plugin command is needed
// if showing the version, we never need plugin commands
$mayNeedPluginCommand = false === $input->hasParameterOption(['--version', '-V'])
Expand All @@ -216,6 +238,21 @@ public function doRun(InputInterface $input, OutputInterface $output): int
);

if ($mayNeedPluginCommand && !$this->disablePluginsByDefault && !$this->hasPluginCommands) {
// at this point plugins are needed, so if we are running as root and it is not allowed we need to prompt
// if interactive, and abort otherwise
if ($isNonAllowedRoot) {
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');

if ($io->isInteractive() && $io->askConfirmation('<info>Continue as root/super user</info> [<comment>yes</comment>]? ')) {
// avoid a second prompt later
$isNonAllowedRoot = false;
} else {
$io->writeError('<warning>Aborting as no plugin should be loaded if running as super user is not explicitly allowed</warning>');

return 1;
}
}

try {
foreach ($this->getPluginCommands() as $command) {
if ($this->has($command->getName())) {
Expand Down Expand Up @@ -245,6 +282,10 @@ public function doRun(InputInterface $input, OutputInterface $output): int
$this->hasPluginCommands = true;
}

if ($isNonAllowedRoot && !$io->isInteractive()) {
$this->disablePluginsByDefault = true;
}

// determine command name to be executed incl plugin commands, and check if it's a proxy command
$isProxyCommand = false;
if ($name = $this->getCommandName($input)) {
Expand Down Expand Up @@ -277,30 +318,16 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
$io->writeError(sprintf('<warning>Warning: This development build of Composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
}

if (
!Platform::isWindows()
&& function_exists('exec')
&& !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER')
&& (ini_get('open_basedir') || !file_exists('/.dockerenv'))
) {
if (function_exists('posix_getuid') && posix_getuid() === 0) {
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');

if ($io->isInteractive()) {
if (!$io->askConfirmation('<info>Continue as root/super user</info> [<comment>yes</comment>]? ')) {
return 1;
}
if ($isNonAllowedRoot) {
if ($commandName !== 'self-update' && $commandName !== 'selfupdate' && $commandName !== '_complete') {
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');

if ($io->isInteractive()) {
if (!$io->askConfirmation('<info>Continue as root/super user</info> [<comment>yes</comment>]? ')) {
return 1;
}
}
if ($uid = (int) Platform::getEnv('SUDO_UID')) {
// Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
// ref. https://github.com/composer/composer/issues/5119
Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
}
}
// Silently clobber any remaining sudo leases on the current user as well to avoid privilege escalations
Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
}

// Check system temp folder for usability as it can cause weird runtime issues otherwise
Expand Down

0 comments on commit a75fbf0

Please sign in to comment.