0.5.0
A feature release. The advisory database now carries exploit data (FIRST EPSS scores and CISA's
Known Exploited Vulnerabilities catalogue) and reports order findings by that urgency; abandoned
packages on a dependency path are named; and the Phase 3 fixture corpus is complete with five Drupal
and five Symfony cases, seventeen real historical projects in all. The GitHub workflows were hardened
after a scan.
Added
-
Exploit data in the advisory database.
remediate:db-buildenriches every CVE with its FIRST
EPSS probability and percentile and its CISA KEV listing date (--enrich, on by default;
--epss-file/--kev-fileread local copies). Only the CVEs the database names are stored. A
feed that cannot be fetched is recorded in the metadata and the build continues without it;
remediate:db-statusshows what the database carries. Reports order findings by urgency (known
exploited first, then EPSS, then severity; development-only findings last), printEPSS 0.93 (97th percentile); listed in CISA KEV since …under each advisory, and count KEV-listed packages in the
summary. JSON gainsepss,epss_percentileandkev_addedper advisory and
packages_known_exploitedin the summary; SARIF tags such rulesknown-exploited; CycloneDX and
GitLab reports carry the values. The dataset hash includes KEV membership (a new listing changes
what to fix first) but not EPSS scores. Databases built without the data still read; their reports
sayno exploit data. Tests: both feeds with scripted downloads and local files, build-to-report
round trip, a failing feed, hash behaviour, an old database, ordering rules, every output format. -
Abandoned packages on the dependency path. When Packagist marks the vulnerable package or a
parent on its path abandoned (the marker travels incomposer.lock, so this needs no network), the
report says so with the replacement Packagist names, under the finding and in the summary; JSON
gainsabandonedper finding andpackages_with_abandoned_dependencyin the summary; SARIF,
CycloneDX and GitLab reports carry the names. The lock snapshot now preserves the marker. Tests:
planner detection on a scripted lock, every output format. -
Phase 3 fixture corpus complete: five Drupal and five Symfony cases. New real historical
fixtures: Mass.gov on Drupal 10.3 (the meta-package's tilde pins let every November 2024 fix through
as a plain update; an abandoned Goutte on the path), Open Social's project template (the
distribution's~10.2.5pin permits the Drupal 10.2.9 patch; Twig 3.14 needs a package the lock
never had), Acquia CMS (Drupal 10.3 withoutcore-recommended, a monorepo whose modules come from
pathrepositories with branch aliases), wallabag (Symfony 5.4 on PHP 7.4: eleven of sixteen
advisories fixable, Guzzle 5 stuck behind the root constraint and an abandoned adapter) and Mautic 5
(a monorepo whose ownpathpackage pins PhpSpreadsheet below the fix). Each carries provenance,
the reasoning behind the expected command and stored reports; the case-studies page grows with them. -
bin/build-fixture.phplearned what these projects needed: it fetches the requirement closure of
every version it keeps (metadata Composer never loaded for the locked graph), takespath/
artifactpackages from the lock file with their branch aliases and a neutral dist while dropping
other versions of those names (a path repository takes precedence), splits and retries advisory API
batches that come back unreadable, and stores fixture manifests ascomposer.fixture.json/
composer.fixture.lock.expected.jsongainedroot_versionfor projects whose dependencies
conflict with the root package by version.
Security
- GitHub workflows hardened after an Aikido scan: every action is pinned to a commit SHA with its
version noted (and a Dependabot configuration keeps the pins current); no workflow expression is
interpolated into a shell script any more, values reach scripts through the environment (the
forceinput of the advisory-database workflow was the reported template-injection vector); the
advisory-database workflow's write permissions moved from the workflow to its single job and the CI
workflow defaults to read; every checkout runs withpersist-credentials: false(the badge push
and the release steps use explicit tokens).bin/run-fixture.phpvalidates the fixture name before
building a path from it.
Changed
- Findings are ordered by urgency (see above); before, they were ordered by package name. The stored
fixture reports and the case-studies page are regenerated accordingly. - Test fixtures moved from
tests/Fixture/<name>totests/Fixture/third-party/<name>, and their
manifests are stored ascomposer.fixture.json/composer.fixture.lock. The fixtures' historical
lock files are vulnerable on purpose and raised hundreds of Dependabot alerts; GitHub's dependency
graph parses everycomposer.jsonandcomposer.lockin a repository whatever the directory (the
third-partyname alone did not exempt them), and does not parse the renamed files.
bin/build-fixture.phpwrites the new layout by default.