Skip to content

0.5.0

Choose a tag to compare

@hexblot hexblot released this 10 Sep 13:43
· 24 commits to main since this release
v0.5.0
30b49e9

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-build enriches every CVE with its FIRST
    EPSS probability and percentile and its CISA KEV listing date (--enrich, on by default;
    --epss-file / --kev-file read 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-status shows what the database carries. Reports order findings by urgency (known
    exploited first, then EPSS, then severity; development-only findings last), print EPSS 0.93 (97th percentile); listed in CISA KEV since … under each advisory, and count KEV-listed packages in the
    summary. JSON gains epss, epss_percentile and kev_added per advisory and
    packages_known_exploited in the summary; SARIF tags such rules known-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
    say no 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 in composer.lock, so this needs no network), the
    report says so with the replacement Packagist names, under the finding and in the summary; JSON
    gains abandoned per finding and packages_with_abandoned_dependency in 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.5 pin permits the Drupal 10.2.9 patch; Twig 3.14 needs a package the lock
    never had), Acquia CMS (Drupal 10.3 without core-recommended, a monorepo whose modules come from
    path repositories 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 own path package 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.php learned what these projects needed: it fetches the requirement closure of
    every version it keeps (metadata Composer never loaded for the locked graph), takes path /
    artifact packages 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 as composer.fixture.json /
    composer.fixture.lock. expected.json gained root_version for 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
    force input 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 with persist-credentials: false (the badge push
    and the release steps use explicit tokens). bin/run-fixture.php validates 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> to tests/Fixture/third-party/<name>, and their
    manifests are stored as composer.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 every composer.json and composer.lock in a repository whatever the directory (the
    third-party name alone did not exempt them), and does not parse the renamed files.
    bin/build-fixture.php writes the new layout by default.