NAME
cpan-audit-declared-chain - audit the transitive runtime closure of the declared dependency chain for permitted vulnerable resolutions
WHAT IT IS
A fail-closed advisory gate that reads the distribution's own declared runtime requirements, walks every runtime requirement reachable from them using the metadata cpanm writes next to each installed distribution, and reports any distribution whose lowest still-permitted release falls inside a published CPAN security advisory range.
WHAT IT IS FOR
It answers the question an installer answers, which is not the question an installed-distribution scan answers. A scan of what happens to be installed reports the versions a resolver already picked, and a resolver always picks the newest release, so that scan stays green while the declared floors still permit a vulnerable version. This gate reports the floor itself.
WHY IT EXISTS
The advisory floor list was originally derived from the modules the cpanfile names, while the real exposure comes from the transitive closure. Two modules reached the product that way and were only caught by manual audit:
HTTP::Date, required bylibwww-perl, where a vulnerable 6.06 satisfied every declared requirement.HTML::Parser, required bylibwww-perlunder the namesHTML::EntitiesandHTML::HeadParser, where the only floor anywhere in the chain was 3.71 and a vulnerable 3.83 satisfied it.
Neither module is named in the cpanfile and neither is called by the product, so no source-level check could ever have found them. The declared floor is the whole mitigation, and this gate is what verifies the floor is actually there.
WHEN TO USE
Run it whenever dependency metadata changes, whenever an advisory floor is raised, and as a continuous-integration step against the isolated dependency root the build resolves. It is deliberately a live gate: the advisory database moves, so a chain that was clean yesterday can legitimately fail today.
HOW TO USE
Give it the Perl library root whose distribution metadata should be walked. The cpanfile and the reviewed advisory disposition file default to the ones next to the script, and both can be overridden.
Exit codes are fail-closed:
0- no distribution in the closure permits a version inside an advisory range.1- at least one permitted vulnerable resolution was found.2- the gate could not audit the whole chain (bad usage, missingCPAN::Audit, a library root with no distribution metadata, or a distribution metadata file it could not read or parse). It never reports a clean chain it did not establish, and an unreadable metadata file is not established: dropping one shrinks the closure, and a smaller closure is exactly what hides a finding.
WHAT USES IT
The continuous-integration dependency audit job runs it against the isolated local/lib/perl5 root the build resolves, and t/109-declared-chain-advisory-closure.t exercises both its contracts and its detection behaviour against synthetic metadata fixtures.
EXAMPLES
Example 1 - audit the isolated dependency root a build resolved:
script/cpan-audit-declared-chain local/lib/perl5
Example 2 - audit the operator's own library root:
script/cpan-audit-declared-chain "$HOME/perl5/lib/perl5"
Example 3 - audit a candidate cpanfile before committing it:
script/cpan-audit-declared-chain --cpanfile /tmp/candidate-cpanfile local/lib/perl5
Example 4 - audit with an alternative reviewed disposition list:
script/cpan-audit-declared-chain \
--exclude-file /tmp/reviewed-advisories.txt local/lib/perl5
AUTHOR
Developer Dashboard Contributors