diff --git a/README.md b/README.md index 02731fd..db23fe8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Security Check Plugin for Composer +# Security Check Plugin for Composer 2.x For global install: @@ -13,13 +13,13 @@ Run these commands to see some sample behavior: mkdir insecure-project cd insecure-project composer init --name="insecure/project" --description="insecure project" -l MIT -n - composer require symfony/symfony:2.5.2 + composer require 3f/pygmentize:1.0 composer require fancyguy/composer-security-check-plugin composer audit composer audit --format=simple composer audit --format=json composer validate - composer require symfony/symfony --update-with-all-dependencies + composer require 3f/pygmentize --update-with-all-dependencies composer audit By default this tool uploads your `composer.lock` file to the [security.symfony.com](https://security.symfony.com/) webservice which uses the checks from https://github.com/FriendsOfPHP/security-advisories. diff --git a/composer.json b/composer.json index 4fa71cb..831f64f 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,10 @@ { "name": "Steve Buzonas", "email": "steve@fancyguy.com" + }, + { + "name": "Jeroen Vermeulen", + "email": "jeroen@magehost.pro" } ], "support": { @@ -21,19 +25,16 @@ "psr-4": { "FancyGuy\\Composer\\SecurityCheck\\Test\\": "tests/" } }, "require": { - "composer-plugin-api": "^1.1", + "composer-plugin-api": "^2.0", "symfony/yaml": "^4.1", "ext-json": "*", "ext-curl": "*" }, "require-dev": { - "composer/composer": "^1.6", + "composer/composer": "^2.0", "phpunit/phpunit": "^7.2" }, "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - }, "class": "FancyGuy\\Composer\\SecurityCheck\\SecurityCheckPlugin" } } diff --git a/src/Checker/HttpChecker.php b/src/Checker/HttpChecker.php index ef3b923..0b42bf7 100644 --- a/src/Checker/HttpChecker.php +++ b/src/Checker/HttpChecker.php @@ -34,7 +34,7 @@ protected function doCheck($lock) list($headers, $body) = $this->doHttpCheck($lock, $certFile); - if (!(preg_match('/X-Alerts: (\d+)/', $headers, $matches) || 2 == count($matches))) { + if (!(preg_match('/X-Alerts: (\d+)/i', $headers, $matches) || 2 == count($matches))) { throw new RuntimeException('The web service did not return alerts count.'); } @@ -59,7 +59,7 @@ public function testConnection() unlink($tmplock); - if (!(preg_match('/X-Alerts: (\d+)/', $headers, $matches) || 2 == count($matches))) { + if (!(preg_match('/X-Alerts: (\d+)/i', $headers, $matches) || 2 == count($matches))) { throw new RuntimeException('The web service did not return alerts count.'); } diff --git a/src/SecurityCheckPlugin.php b/src/SecurityCheckPlugin.php index 710c447..1681e28 100644 --- a/src/SecurityCheckPlugin.php +++ b/src/SecurityCheckPlugin.php @@ -7,9 +7,9 @@ use Composer\Factory; use Composer\IO\IOInterface; use Composer\Installer\InstallationManager; -use Composer\Installer\InstallerEvent; -use Composer\Installer\InstallerEvents; use Composer\Installer\NoopInstaller; +use Composer\Installer\PackageEvent; +use Composer\Installer\PackageEvents; use Composer\Plugin\Capable; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; @@ -19,6 +19,7 @@ use Composer\Repository\InstalledFilesystemRepository; use Composer\Script\Event as ScriptEvent; use Composer\Script\ScriptEvents; +use Composer\Util\Loop; use FancyGuy\Composer\SecurityCheck\Checker\DefaultChecker; use FancyGuy\Composer\SecurityCheck\Util\DiagnosticsUtility; @@ -39,8 +40,12 @@ public static function getSubscribedEvents() array('onCommandEvent'), ), // audit install candidates and possibly block installs - InstallerEvents::POST_DEPENDENCIES_SOLVING => array( - array('onInstallerEvent'), + PackageEvents::PRE_PACKAGE_INSTALL => array( + array('onPackageEvent'), + ), + // audit update candidates and possibly block installs + PackageEvents::PRE_PACKAGE_UPDATE => array( + array('onPackageEvent'), ), // status ScriptEvents::POST_STATUS_CMD => array( @@ -58,6 +63,10 @@ public static function getSubscribedEvents() private $composer; + private $config; + + private $loop; + private $io; protected function getComposer() @@ -65,6 +74,16 @@ protected function getComposer() return $this->composer; } + protected function getConfig() + { + return $this->config; + } + + protected function getLoop() + { + return $this->loop; + } + protected function getIO() { return $this->io; @@ -74,8 +93,16 @@ public function activate(Composer $composer, IOInterface $io) { $this->composer = $composer; $this->io = $io; + $this->config = Factory::createConfig(); + $this->loop = new Loop(Factory::createHttpDownloader($this->getIO(), $this->getConfig())); } + public function deactivate(Composer $composer, IOInterface $io) { + } + + public function uninstall(Composer $composer, IOInterface $io) { + } + public function getCapabilities() { return array( @@ -102,7 +129,7 @@ public function onPreCommandRunEvent(PreCommandRunEvent $event) { } - public function onInstallerEvent(InstallerEvent $event) + public function onPackageEvent(PackageEvent $event) { $operations = $event->getOperations(); if (!$operations) { @@ -110,17 +137,9 @@ public function onInstallerEvent(InstallerEvent $event) return; } - $installedRepo = $event->getInstalledRepo(); + $repo = $event->getLocalRepo(); - $isFilesystemInstall = false; - foreach ($installedRepo->getRepositories() as $repo) { - if ($repo instanceof InstalledFilesystemRepository) { - $isFilesystemInstall = true; - break; - } - } - - if (!$isFilesystemInstall) { + if (!$repo instanceof InstalledFilesystemRepository) { // noop return; } @@ -137,18 +156,16 @@ public function onInstallerEvent(InstallerEvent $event) } $localRepo = new InstalledArrayRepository($packages); - $im = new InstallationManager(); + $im = new InstallationManager($this->getLoop(), $this->getIO()); $im->addInstaller(new NoopInstaller); - foreach ($operations as $operation) { - // TODO: Fake passes like in Installer::extractDevPackages() break things - // Ideally we should have the local repository being used in the event - // For now, blindly ignore exceptions. The noop installer throws only - // when a package is not installed. We'll assume it is in another context - try { - $im->execute($localRepo, $operation); - } catch (\Exception $e) {} - } + // TODO: Fake passes like in Installer::extractDevPackages() break things + // Ideally we should have the local repository being used in the event + // For now, blindly ignore exceptions. The noop installer throws only + // when a package is not installed. We'll assume it is in another context + try { + $im->execute($localRepo, $operations); + } catch (\Exception $e) {} $locked = array();