NAME

Test::CPAN::Health::Check::SecurityAdvisories - Check for known CVEs in the distribution and its dependencies

SYNOPSIS

use Test::CPAN::Health::Check::SecurityAdvisories;

my $check  = Test::CPAN::Health::Check::SecurityAdvisories->new;
my $result = $check->run($dist);

DESCRIPTION

Consults the CPAN::Audit advisory database to check whether the distribution under analysis, or any of its declared runtime or test dependencies, have known CVEs or security advisories.

The CPAN::Audit database is bundled with the module and does not require a network connection during the check itself. An optional call to cpan-audit update (or the equivalent) can refresh the database from the CPAN Security Group's upstream advisory repository.

Scoring:

  • 100 -- no advisories found in distribution or any dependency.

  • 50 -- advisories found only in indirect/test dependencies.

  • 0 -- advisories found in the distribution itself or a direct runtime dependency. The Report hard-caps the overall score at 60.

The ReverseDeps context value (populated by an earlier check) is used to scale the urgency message: a distribution with many downstream users carries a higher implicit risk.

LIMITATIONS

  • CPAN::Audit only covers advisories that have been submitted to the CPAN Security Advisory database. Not all CVEs are catalogued there.

  • Version range matching follows CPAN::Audit's own logic; unusually formatted version strings may produce false negatives.

  • This check is skipped when no_network is set and the local advisory database is absent (i.e. CPAN::Audit is not installed).

run

PURPOSE

Scan the distribution and its full dependency tree against the CPAN::Audit advisory database. Classify findings by severity and affected dep type (self / direct runtime / test / indirect).

API SPECIFICATION

INPUT

dist     Test::CPAN::Health::Distribution  required
context  Hashref                           optional  prior check results;
                                                     reads context->{reverse_deps}

OUTPUT

Test::CPAN::Health::Result with:

check_id  'security_advisories'
status    'pass' | 'fail' | 'skip' | 'error'
score     0 | 50 | 100
summary   human-readable verdict
details   list of "MODULE vVERSION: CVE-XXXX-YYYY (CVSS N.N)" strings
url       link to CPAN Security Advisory page for the distribution

MESSAGES

Code  | Severity | Message                            | Resolution
------+----------+------------------------------------+---------------------
SEC01 | SKIP     | CPAN::Audit not available          | cpanm CPAN::Audit
SEC02 | PASS     | No known advisories found          |
SEC03 | FAIL     | {n} advisories in dist/direct deps | Update affected modules
SEC04 | FAIL     | {n} advisories in test/indirect    | Update affected modules

FORMAL SPECIFICATION

-- Z schema (placeholder) --
SecurityAdvisoriesOp
dist         : Distribution
advisories   : seq Advisory
direct_hits  : seq Advisory
indirect_hits: seq Advisory
score        : {0, 50, 100}
status       : {pass, fail, skip, error}
-------------------------------------------------------
advisories  = CPAN::Audit.scan(dist.meta.prereqs)
direct_hits  = {a : advisories | a.dep_type in {self, runtime}}
indirect_hits = advisories \ direct_hits
#direct_hits > 0  => status = fail /\ score = 0
#indirect_hits > 0 /\ #direct_hits = 0 => status = fail /\ score = 50
#advisories = 0   => status = pass /\ score = 100

SIDE EFFECTS

Reads the CPAN::Audit SQLite/JSON advisory database from disk.

USAGE EXAMPLE

my $result = $check->run($dist, \%context);

AUTHOR

Nigel Horne, <njh at nigelhorne.com>

LICENSE AND COPYRIGHT

Copyright (C) 2025-2026 Nigel Horne.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.