Skip to content

Commit

Permalink
Merge pull request #13 from cs278/ignore-cve
Browse files Browse the repository at this point in the history
Ignore advisory by CVE
  • Loading branch information
cs278 authored May 14, 2021
2 parents 27101f1 + 003c589 commit c7ae144
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 4 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,54 @@ does not exist or it’s more than an hour old. For example:
composer audit --update
```

Configuration
-------------

Composer Audit can be configured using the [`extra`][composer.json extra] property
in your `composer.json` file, all configuration should be supplied under the
`composer-audit` key.

```json
{
...
"extra": {
...
"composer-audit": {
"option1": "super"
},
...
},
...
}
```

### Ignoring an advisory

Currently only filtering advisories by CVE is possible, further options are planned.

#### Ignoring an advisory by CVE

You are able to ignore warnings about an advisory by filtering based on its CVE
reference, this is useful if you decide the risk is acceptable or not applicable
and you cannot otherwise upgrade the package to resolve the problem.

```json
{
...
"extra": {
...
"composer-audit": {
"ignore": [
{"type": "cve", "value": "CVE-2000-1234567"},
{"type": "cve", "value": "CVE-2000-7654321"}
]
},
...
},
...
}
```

Example
-------

Expand Down Expand Up @@ -88,5 +136,6 @@ composer://symfony/http-foundation (2.0.4)

Hyperlinks will be rendered to the appropriate CVE and advisory where available.

[composer.json extra]: https://getcomposer.org/doc/04-schema.md#extra
[FriendsOfPHP/security-advisories]: https://github.com/FriendsOfPHP/security-advisories
[security.symfony.com]: https://security.symfony.com/
61 changes: 57 additions & 4 deletions src/AuditCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,24 @@ protected function execute(InputInterface $input, OutputInterface $output)
// NULL if option is unknown.
$lockOption = $this->getComposer()->getConfig()->get('lock');

// Pull config from the extra array in composer.json.
$config = $this->getComposer()->getPackage()->getExtra()['composer-audit'] ?? [];
$ignoreCves = [];

foreach ($config['ignore'] ?? [] as $rule) {
$type = (string) $rule['type'] ?? '';
$value = (string) $rule['value'] ?? '';

if ($type === 'cve' && $value !== '') {
$ignoreCves[] = $value;
} else {
$output->writeln(sprintf(
'Ignoring invalid ignore rule: `%s`',
json_encode($rule)
), OutputInterface::VERBOSITY_VERBOSE);
}
}

if ($lockOption === null || $lockOption === true) {
if (!$this->getComposer()->getLocker()->isLocked()) {
$output->writeln('<error>Lock file not found.</error>');
Expand Down Expand Up @@ -123,6 +141,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
return \count($packageAdvisories);
}, $advisories));
$packagesAffected = \count($advisories);
$ignoredAdvisories = 0;

// @todo Pluralization?
$output->writeln(sprintf(
Expand All @@ -133,12 +152,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$packagesAffected
));

$output->writeln('');
$exitCode = 0;

ksort($advisories, \SORT_NATURAL | \SORT_ASC);
$firstAdvisory = true;

foreach ($advisories as $reference => $packageAdvisories) {
$output->writeln(sprintf('<info>composer://%s (%s)</info>', $reference, $packages[$reference]));
$firstAdvisoryForPackage = true;

foreach ($packageAdvisories as $advisory) {
$title = $advisory['title'];
Expand Down Expand Up @@ -166,6 +186,22 @@ protected function execute(InputInterface $input, OutputInterface $output)
$cve = $cveLink = null;
}

if (\in_array($cve, $ignoreCves, true)) {
++$ignoredAdvisories;

continue;
}

if ($firstAdvisory) {
$output->writeln('');
$firstAdvisory = false;
}

if ($firstAdvisoryForPackage) {
$output->writeln(sprintf('<info>composer://%s (%s)</info>', $reference, $packages[$reference]));
$firstAdvisoryForPackage = false;
}

if ($output->isDecorated()) {
$output->writeln(sprintf(
$cve !== null ? '* %s: %s' : '* %2$s',
Expand All @@ -185,12 +221,29 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
}

$exitCode = 1;
}

$output->writeln('');
// Only need a spacer if any adisories were written.
if (!$firstAdvisory) {
$output->writeln('');
}
}

if ($ignoredAdvisories) {
$output->writeln(sprintf(
'<info>%u advisories were ignored.</info>',
$ignoredAdvisories
));

// Change exit code to indicate some things were ignored.
if ($exitCode === 1) {
$exitCode = 2;
}
}

return 1;
return $exitCode;
}

if ($output->isVerbose()) {
Expand Down
57 changes: 57 additions & 0 deletions tests/integration/ignore--broken-show-warnings.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
--TEST--
Test invalid ignore rules are handled.
--CONDITION--
true
--COMPOSER--
{
"require-dev": {
"symfony/http-foundation": "=2.0.4"
},
"extra": {
"composer-audit": {
"ignore": [
{"type": "package", "value": "foo/bar"},
{"type": "cve", "value": ""},
{"type": "", "value": "test"}
]
}
}
}
--ARGS--
-vv
--EXPECT-EXIT--
1
--EXPECT-OUTPUT--
Ignoring invalid ignore rule: `{"type":"package","value":"foo\/bar"}`
Ignoring invalid ignore rule: `{"type":"cve","value":""}`
Ignoring invalid ignore rule: `{"type":"","value":"test"}`
Found 9 advisories affecting 1 package(s).

composer://symfony/http-foundation (2.0.4)
* Request::getClientIp() when the trust proxy mode is enabled
- <https://symfony.com/blog/security-release-symfony-2-0-19-and-2-1-4>
* CVE-2012-6431 Routes behind a firewall are accessible even when not logged in
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6431>
- <https://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released>
* CVE-2013-4752 Request::getHost() poisoning
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4752>
- <https://symfony.com/blog/security-releases-symfony-2-0-24-2-1-12-2-2-5-and-2-3-3-released>
* CVE-2014-5244 Denial of service with a malicious HTTP Host header
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5244>
- <https://symfony.com/cve-2014-5244>
* CVE-2014-6061 Security issue when parsing the Authorization header
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6061>
- <https://symfony.com/cve-2014-6061>
* CVE-2015-2309 Unsafe methods in the Request class
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2309>
- <https://symfony.com/cve-2015-2309>
* CVE-2018-11386 Denial of service when using PDOSessionHandler
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11386>
- <https://symfony.com/cve-2018-11386>
* CVE-2018-14773 Remove support for legacy and risky HTTP headers
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-14773>
- <https://symfony.com/blog/cve-2018-14773-remove-support-for-legacy-and-risky-http-headers>
* CVE-2019-18888 Prevent argument injection in a MimeTypeGuesser
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18888>
- <https://symfony.com/cve-2019-18888>

53 changes: 53 additions & 0 deletions tests/integration/ignore--broken.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--TEST--
Test invalid ignore rules are handled.
--CONDITION--
true
--COMPOSER--
{
"require-dev": {
"symfony/http-foundation": "=2.0.4"
},
"extra": {
"composer-audit": {
"ignore": [
{"type": "package", "value": "foo/bar"},
{"type": "cve", "value": ""},
{"type": "", "value": "test"}
]
}
}
}
--ARGS--
--EXPECT-EXIT--
1
--EXPECT-OUTPUT--
Found 9 advisories affecting 1 package(s).

composer://symfony/http-foundation (2.0.4)
* Request::getClientIp() when the trust proxy mode is enabled
- <https://symfony.com/blog/security-release-symfony-2-0-19-and-2-1-4>
* CVE-2012-6431 Routes behind a firewall are accessible even when not logged in
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6431>
- <https://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released>
* CVE-2013-4752 Request::getHost() poisoning
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4752>
- <https://symfony.com/blog/security-releases-symfony-2-0-24-2-1-12-2-2-5-and-2-3-3-released>
* CVE-2014-5244 Denial of service with a malicious HTTP Host header
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5244>
- <https://symfony.com/cve-2014-5244>
* CVE-2014-6061 Security issue when parsing the Authorization header
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6061>
- <https://symfony.com/cve-2014-6061>
* CVE-2015-2309 Unsafe methods in the Request class
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2309>
- <https://symfony.com/cve-2015-2309>
* CVE-2018-11386 Denial of service when using PDOSessionHandler
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11386>
- <https://symfony.com/cve-2018-11386>
* CVE-2018-14773 Remove support for legacy and risky HTTP headers
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-14773>
- <https://symfony.com/blog/cve-2018-14773-remove-support-for-legacy-and-risky-http-headers>
* CVE-2019-18888 Prevent argument injection in a MimeTypeGuesser
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18888>
- <https://symfony.com/cve-2019-18888>

23 changes: 23 additions & 0 deletions tests/integration/ignore--cve-with-error.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
Test that an ignored CVE does not result in an error.
--CONDITION--
true
--COMPOSER--
{
"require-dev": {
"symfony/security-core": "=5.2.7"
},
"extra": {
"composer-audit": {
"ignore": [
{"type": "cve", "value": "CVE-2021-21424"}
]
}
}
}
--ARGS--
--EXPECT-EXIT--
0
--EXPECT-OUTPUT--
Found 1 advisories affecting 1 package(s).
1 advisories were ignored.
45 changes: 45 additions & 0 deletions tests/integration/ignore--cve.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--TEST--
Test that an ignored CVE does not result in an error.
--CONDITION--
true
--COMPOSER--
{
"require-dev": {
"symfony/http-foundation": "=2.0.4"
},
"extra": {
"composer-audit": {
"ignore": [
{"type": "cve", "value": "CVE-2012-6431"},
{"type": "cve", "value": "CVE-2013-4752"},
{"type": "cve", "value": "CVE-2014-5244"}
]
}
}
}
--ARGS--
--EXPECT-EXIT--
2
--EXPECT-OUTPUT--
Found 9 advisories affecting 1 package(s).

composer://symfony/http-foundation (2.0.4)
* Request::getClientIp() when the trust proxy mode is enabled
- <https://symfony.com/blog/security-release-symfony-2-0-19-and-2-1-4>
* CVE-2014-6061 Security issue when parsing the Authorization header
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6061>
- <https://symfony.com/cve-2014-6061>
* CVE-2015-2309 Unsafe methods in the Request class
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2309>
- <https://symfony.com/cve-2015-2309>
* CVE-2018-11386 Denial of service when using PDOSessionHandler
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11386>
- <https://symfony.com/cve-2018-11386>
* CVE-2018-14773 Remove support for legacy and risky HTTP headers
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-14773>
- <https://symfony.com/blog/cve-2018-14773-remove-support-for-legacy-and-risky-http-headers>
* CVE-2019-18888 Prevent argument injection in a MimeTypeGuesser
- <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18888>
- <https://symfony.com/cve-2019-18888>

3 advisories were ignored.

0 comments on commit c7ae144

Please sign in to comment.