Skip to content

Releases

fleetreach 1.6.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 07:18

Added

  • SBOM input matches OS packages. pkg:deb, pkg:apk and pkg:rpm components go to the same
    distro matchers as an image, so a Syft or Trivy image SBOM scans in full. The release comes from
    the distro qualifier or the operating-system component, and each package's source from what
    the tool wrote. A document that names no release, or several, is a coverage gap, and so is one
    that names no source packages. SPDX has no module stream labels, so on a Red Hat module build
    the scan says it may differ from the image.
  • fix plan reads each repo's ranges before it proposes a target, for npm's
    package-lock.json and for Cargo. A target your own manifest leaves out is a new
    manifest-bump edit: fix apply raises the range, an exact pin included, then updates the
    lock. A target a published package leaves out, peer ranges included, is blocked and names the
    package to update first, rather than failing in fix apply.
  • fix plan keeps targets clear of advisories of their own. The queue only knows the
    advisories some repo already has, so a target could carry one that starts above every installed
    version, and the re-scan then refused the bump. The plan now reads the OSV exports (--osv-dir,
    or wherever a scan finds them) and moves the target to the lowest fix that adds nothing. This
    also restores Maven's four-part fixes such as 3.41.2.2, which the plan had cut to a version
    that does not exist.
  • scan --reachability builds witness chains for Ruby, PHP, .NET, Java and Kotlin, Elixir and
    Swift.
    A chain starts at the import line in your source and follows the lockfile, for example
    imported at app/models/user.rb:3 via loofah → nokogiri. Positive-only, like Python's. JSON
    reports the line as reachability.import_site.
  • SARIF codeFlows follow import chains, for npm and Python too, and start at the import line
    where it is known.
  • licenses --detect reads the license files packages ship, with the spdx crate's own
    matcher over the SPDX texts, in pure Rust, on this machine. A package nothing declared takes
    the license its files say, unless one of them could not be recognized. A package whose files
    name a license its declaration does not account for is a mismatch, with its verdict in
    [settings.licenses] mismatch.
  • licenses --detect --download reads packages that are not on this machine. It fetches each
    public package's archive for npm, Cargo, PyPI, RubyGems, Hex and Go, checks it against the
    lockfile's hash (the tree hash in go.sum for Go), and keeps only its license files in a cache
    keyed by that hash, which --detect then reads offline.
  • SBOM input takes CycloneDX XML, SPDX tag-value and GitHub's dependency graph export, and
    finds SBOMs by itself. [settings.sbom] discover scans the SBOMs in a repo with nothing else
    to read, [[repo]] sbom_discover sets that per repo, and [[source]] sbom_assets fetches
    those on the latest release on fleet sync (GitHub, Gitea, Forgejo). An SBOM older than the
    newest lockfile commit is a coverage gap.
  • pkg:golang and pkg:cargo in an SBOM are now matched, with RustSec and the crates.io
    export for Rust. Go names compare without case where a purl lost it, as Trivy's do. Direct
    dependencies are found below the lockfile and project nodes Trivy puts under the root, in
    every ecosystem.
  • scan --health asks registries what a lockfile cannot show: npm and NuGet deprecations,
    PyPI, RubyGems, crates.io and NuGet yanks, Packagist abandoned with the replacement, Go
    deprecations and retractions, Hex retirements and Maven relocations, plus archived GitHub
    repos with a token and low OpenSSF Scorecards with [settings.health] min_scorecard. Only
    public packages are sent, and answers are cached for a week. A package with no answer is a
    coverage gap, never clean.
  • Scope for Cargo, Bundler, Hex, NuGet and Go, and a gate per scope. A package only dev
    dependencies lead to is now scope: dev in these five too, so --ignore-dev-deps, SBOM
    scope: excluded and license scope = "runtime" cover them. --fail-on-dev and
    [settings.gate.scope] dev give dev packages their own floor, or never; diff --base takes
    the flag. Known malware keeps the runtime floor. Whatever cannot be read stays runtime: against
    cargo tree, go list, Bundler and mix deps on real repos, no package those tools ship was
    called dev. Go needs the dependency source, so run go mod download first. See "Gate on what
    ships".
  • diff --base <ref> says what a change brought in. New findings are compared per
    occurrence and placed by git: brought in, with the lockfile line and the manifest line that
    caused it; already at the merge base, so the advisory is what changed, which no longer
    gates; or not placed, which still gates. Fixture PRs from real lockfiles passed on all twelve
    ecosystems.
  • SARIF regions now also cover gradle.lockfile, packages.config, pylock.toml and
    requirements files under other names.
  • Five more [[source]] kinds: gitea, forgejo, bitbucket (Cloud), bitbucket-server
    (Data Center) and azure (Azure DevOps). topics on a forge without topics is a config
    error. Listings refuse a next link off the API, a pager that repeats, and Azure's redirect
    to sign-in. A sync without a token now says that only public repos were listed.
  • fleet sync and scan --sync report the repos added, removed and renamed since the last
    listing, by the forge's own repo id, and --history-dir appends them to inventory.jsonl.
  • SSL_CERT_FILE sets the trusted roots for forge listings, for a forge behind a private CA.
  • A repo with nothing fleetreach reads now says "no recognized lockfile or manifest", not "no
    Cargo.lock found".
  • scan --incremental reuses a repo's findings while the binary, the advisory data for its
    ecosystems and the files a scan reads are unchanged, and skips loading the advisory data of any
    ecosystem with nothing to re-scan. On 10,471 repos a warm run took about half the time and a
    third of the memory, with byte-identical output. A fleet of a few large monorepos gains
    nothing; see the new scale benchmark page. Maven, Gradle, SBOM inputs and govulncheck are
    never reused.
  • db sync updates an export record by record. It reads the ecosystem's modified_id.csv,
    fetches only the changed records and rewrites all.zip, instead of downloading the whole zip
    again. A cache five days old took 8 seconds, against 300 MB before. Every one of 329,822
    records then matched a fresh download byte for byte, and a 121-repo scan came out identical.
    Anything doubtful falls back to the whole export; --force always downloads it. Releases
    like Debian:12 have no listing on osv.dev and stay whole downloads.
  • db snapshot and --db-snapshot pin a run. The manifest hashes every source; a pinned
    scan is offline and exits 2 unless the directory holds exactly those files.
  • db bundle and db import --bundle carry all the advisory data in one tar: OSV and
    distro exports, RustSec, KEV, EPSS, CVE and CSAF indexes, and the NVD and Vulnrichment caches.
    db sync --source gains rustsec, kev, epss, nvd and vulnrichment. An imported
    scan with --enrich matched the online one on 1,182 findings, run with network access denied,
    and 44 images matched on 19,286 findings.
  • scan --offline --enrich reads KEV, EPSS, NVD scores and Vulnrichment from the data directory.
  • --db on a RustSec clone reports its commit, so --max-db-age works there. It used to be
    unknown.
  • fix apply handles pnpm, yarn, Composer, Bundler, NuGet and Maven. Lockfile managers
    update with scripts and plugins off; NuGet and Maven change the declared version, or the
    property it reads. Checked on 30 throwaway repos across all twelve update paths: 28 edits
    verified, and every changed lockfile passed the package manager's frozen install.
  • fix apply keeps its pull requests current. A re-run leaves a branch verified on the
    current base alone, rebuilds a stale one, and skips closed or merged requests and branches
    someone else pushed to. --close-obsolete closes requests the plan no longer wants, only
    in repos it scanned.
  • fix apply --max-prs, --canary and --stop-after-failures limit a rollout.
  • Gradle builds without a lockfile are scanned. They were skipped before. Version catalogs
    and literal declarations resolve through the POM resolver, with the highest version winning,
    and the result is always marked partial. Against real Gradle, 163 of 173 packages matched on
    Spring PetClinic, 17 of 18 on Aeron and 71 of 109 on the Airflow Java SDK.
  • Releases add static musl builds for Linux x86-64 and ARM64, and a Windows ARM64 build. The
    install script picks musl on Alpine.
  • pnpm-lock.yaml version 5 is read, and a catalog: dependency is proven to use the version
    its importer records. Across 39 real lockfiles, the package sets match pnpm list, yarn list,
    yarn info and bun pm ls on 35; the other four are explained in
    docs/specs/16-a-plus.md.
  • SBOM components carry hashes from the lockfile: Cargo, npm, pnpm, yarn v1, bun, Bundler, mix,
    uv, Poetry, pylock and Composer. Sampled against registry downloads: 442 hashes across ten
    lockfile formats, all matching. NuGet's contentHash is left out, since it skips the package
    signature and matched none of 25 downloads.
  • sbom writes CycloneDX 1.7 by default, with --cyclonedx-version 1.6 on request, and XML
    with -f cyclonedx-xml. All 121 test BOMs pass the official schemas in both versions, the XML
    holds the same content as the JSON, and Grype and Trivy read them.
  • CI runs the whole test suite in a network namespace with no route out, so a test or feature
    that needs the network fails the build.
  • ci/fleetreach.gitlab-ci.yml, a template a GitLab pipeline can include to scan a r...
Read more

fleetreach 1.5.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 05:27

Added

  • Repo context and SSVC decisions (spec 08). [[repo]] takes exposure,
    mission_impact, safety_impact, owner and tags, with [settings.context.defaults]
    for the rest. Each vulnerable occurrence then gets a CISA SSVC deployer decision
    (immediate, out-of-cycle, scheduled, defer) from KEV exploitation, the advisory's
    CVSS vector (Automatable) and the repo's exposure and impact, through the published
    ssvc:DT_DP:1.0.0 table, tested row by row against CERT/CC's data. -f ssvc lists the
    decisions with their vector and reason; fix-first and remediation sort by them; SARIF
    results carry the outcome and take their level from it; -f owners splits the fix queue by
    owner. --fail-on-ssvc <outcome> gates on them and, given alone, replaces the default
    severity gate. Fail-closed throughout: without KEV data nothing is decided (and the gate
    exits 2), missing context takes the most urgent values, and only a sound NotReachable or a
    phantom dependency lowers a decision to defer. [settings.ssvc] poc_epss optionally
    counts a high EPSS as a public proof of concept.
  • Findings carry the advisory's cvss_vector (additive JSON field).
  • SSVC, continued (spec 08). CISA Vulnrichment supplies CISA's own Exploitation and
    Automatable per CVE where it has assessed one (fetched under --enrich, cached a day, or
    read from a clone with --vulnrichment-dir); it only ever raises Exploitation.
    [settings.ssvc] table loads your own decision table in CERT/CC's CSV layout, validated to
    cover all 72 combinations and recorded as custom:<sha256>. impact, blast and
    packages (and packages-json) show the most urgent outcome and a reach weighted by it
    ([settings.ssvc] weights, default 8/4/2/0), and rank by it. [[source]] takes the same
    context fields for every repo it discovers.
  • Upgrade risk from fleet evidence (spec 13, phase 1). Each remediation upgrade is rated
    low (within the current major), medium (breaking, but at least 3 repos already run the
    target or newer in its major) or high, with the reasons and the evidence (repos,
    newest). -f remediation shows a Bump risk column, remediation-json the risk,
    risk_reasons and evidence fields, and fix plan edits and pull request descriptions
    carry the risk. The JSON report gains package_versions: the versions of each vulnerable
    package that the fleet's lockfiles hold, and in which repos.
  • bun.lock is read in full (bun 1.2+, lockfile versions 0 and 1): workspaces, nested
    copies resolved the way Node loads them, dev scope and dependency paths. Checked against
    osv-scanner on opencode, midday, elysia and bun's own lockfile: the same 4,829 registry
    packages. The binary bun.lockb is still reported as partial coverage.
  • SPDX output and vulnerabilities in the SBOM (spec 05). fleetreach sbom -f spdx writes
    SPDX 2.3 JSON (purls, DEPENDS_ON and DEV_DEPENDENCY_OF relationships, coverage in
    comments, a content-derived namespace). --report report.json embeds a saved scan's
    findings: CycloneDX vulnerabilities[] with ratings, affects, KEV, EPSS and SSVC
    properties and an analysis that is not_affected only for a sound verdict (static
    NotReachable: code_not_reachable; phantom: requires_dependency), or SPDX SECURITY
    advisory references. Both formats pass their official schemas, and an SPDX document scans
    back to the same findings.
  • Scan history, trends and SLAs (spec 09, phases 1 and 2). scan --history-dir DIR
    records each run as a gzipped snapshot plus an index of every finding's first and last
    sighting and fix. fleetreach history trend|age|sla|mttr reads it: open findings per run
    by severity, SSVC, ecosystem or owner; the oldest open findings; breaches of a
    [settings.sla] policy keyed by SSVC outcome or severity (history sla exits 1 on a
    breach, 2 without a policy); and time to fix. Fail-closed: a run that exited 2, an errored
    repo or a partly-read source never marks a finding fixed, ignored findings are recorded as
    ignored, and --history-dir refuses the flags that drop findings. [settings.history] keep prunes old snapshots while the index keeps first-seen dates; a lost or stale index is
    rebuilt from the snapshots.
  • Notifications (spec 09, phase 3). fleetreach notify --history-dir DIR reports what
    the newest run changed (new findings, fixed findings) and every breach of [settings.sla]
    (with -c), grouped by owner. It prints, or POSTs to --webhook (HTTPS; network builds),
    a stable fleetreach-notify/1 JSON payload or, with -f slack, a Slack Block Kit message;
    a webhook gets nothing when nothing changed unless --always. --github-issues (gh) or
    --gitlab-issues (glab) with --repo keeps one issue per owner, found again by a hidden
    marker, rewritten each run, closed when the owner has nothing open and reopened when a
    finding comes back. A gap run never makes old findings look new.
  • Static HTML report (spec 09, phase 4). fleetreach report html --history-dir DIR -o fleet-report.html writes one self-contained page (no external resources) to host
    anywhere: summary tiles, open findings per run by severity with gap runs marked, SLA
    breaches, a queue per owner, fix campaigns from a saved fix status (--fix-status) and
    time to fix by severity. Light and dark, usable at phone width, deterministic for a given
    history.
  • GitLab merge requests for fix apply --open-pr and fix status, through glab:
    the open merge request from a fleetreach/* branch is updated, otherwise one is created.
    The forge is read from each repo's origin host, or set with --forge gitlab|github.
    fix status rows gain a forge field and GitLab states are reported as OPEN, MERGED
    and CLOSED, like GitHub's.
  • Fleet novelty signal (spec 10, phase 4). With --signals and --history-dir,
    fleetreach:new-to-fleet flags packages whose name no earlier recorded run of the fleet
    has read, the cheap early sign of a planted dependency (strongest next to a typosquat or a
    recent release). Each history snapshot now records the package names it read, and the
    index keeps them past retention. The first run that records names is the baseline and
    flags nothing.
  • Maven mirrors from settings.xml (spec 04). --maven-fetch fetches POMs through
    the mirror of Maven Central that ~/.m2/settings.xml (or --maven-settings FILE) names,
    chosen with Maven's mirrorOf rules, with credentials from the matching <server> and
    ${env.NAME} expansion. A configured mirror that cannot be used (plain HTTP, encrypted
    password, unset variable) stops the scan instead of falling back to Maven Central.
    sbom and licenses take --maven-fetch and --maven-settings too.
  • Fixes on an older line (spec 13). Remediation items list alternatives: for repos
    still on an older major (or 0.x minor) than the target, the smallest version on their
    own line that clears their advisories, with what it leaves open and the fleet evidence.
    -f remediation shows them under the action (or 1.4.2 on 1.x (3 repos)), and fix plan
    gives those repos a low-risk lock bump to it instead of a blocked breaking upgrade. Plan
    edits are now marked breaking per repo: a repo on an older line crossing a major is
    breaking even when the fleet's newest version is not.
  • fix apply for Go and uv (spec 07). Go modules are bumped with go get <module>@v<to>, then go list -deps -test ./... records the checksums the build needs
    (both with GOTOOLCHAIN=local and GOWORK=off), and uv.lock with uv lock --upgrade-package <pkg>==<to> --no-build, so neither runs package code; both are
    verified by the re-scan like Cargo and npm. A raised go directive is named in the result,
    the commit and the pull request, which now also say what the update ran.
  • Go from the osv.dev export (spec 01, phase 3). Without govulncheck, the module-level
    Go scan reads Go/all.zip from --osv-dir or the default cache like every other
    toolchain-free ecosystem, so fleetreach db sync now covers Go and no separate
    vuln.go.dev mirror is needed. --go-vuln-db=file:// still takes a mirror (or an unzipped
    export). Only GO- records are used, so GHSA copies are not double-counted; an export
    with no GO- record is an error, not a clean database.
  • A new website (spec 15): docs, guides, integrations, use cases, dated comparisons and
    examples in one Astro Starlight site, replacing the mdBook docs. Every example is real
    output from a frozen demo fleet (website/demo), regenerated by npm run examples and
    checked in CI, as is the CLI reference generated from --help. Each page has a Markdown
    copy, and the site publishes llms.txt, llms-full.txt, a sitemap and JSON-LD. Old
    /docs/*.html addresses redirect. The README is shorter and points to the site.

Changed

  • Faster on large lockfiles and large fleets, with byte-identical output (checked on a
    10,471-repo fleet and 13 large open-source monorepos):
    • Dependency chains are built from one walk of each lockfile's graph instead of one walk per
      package. npm, Hex and Julia asked for a chain for every package, so a big lockfile was
      quadratic: the 13-monorepo scan went from 9.2s to 2.7s.
    • sbom builds each repo's inventory and BOM in parallel, and reads each crate's or NuGet
      package's license once per run instead of once per repo: 37s to 4.3s on the 10k fleet.
      With --fetch-licenses, deps.dev is asked once per package for the whole fleet, not once
      per repo. licenses reads repos in parallel too.
    • --signals reads repos in parallel: 16s to 5.2s on the 10k fleet.
    • The OSV databases a fleet needs load at the same time instead of one after another.

Fixed

Found by checking each feature against real repos (gitea, caddy, hugo, spring-petclinic,
elysia, a ...

Read more

fleetreach 1.4.0

Choose a tag to compare

@github-actions github-actions released this 31 Oct 16:22

Added

  • SBOMs as a scan input. [[repo]] sbom = "build/bom.json" scans a CycloneDX (1.4 to
    1.6) or SPDX 2.3 JSON document instead of the repo's lockfiles, for builds fleetreach cannot
    read. Components are routed by purl to the ecosystem matchers (each feeder gained a public
    scan_installed), with direct dependencies and paths from the document's graph. Coverage is
    full only when CycloneDX asserts completeness; unscannable components are named. An SBOM
    from fleetreach sbom scans back to identical findings.

  • Fix pull requests. fix apply --push pushes each verified fleetreach/* branch, and
    --open-pr [--draft] opens a pull request for it with gh, or updates the open one on a
    re-run. The description lists the advisories, flags breaking jumps, states the
    verification and names the campaign's other repos. Unverified branches are never pushed.
    fix status lists the pull requests of every repo. Tested against a real private repo.

  • Typosquat signal. scan --signals also flags npm, PyPI and Cargo dependencies one edit
    from a popular package they are not, against bundled lists (17,338 npm, 15,000 PyPI and
    5,000 crate names, refreshed by scripts/update-popular.py). Registry-equivalent spellings,
    siblings in one npm scope and version-digit forks are not flagged. Measured at 1.6 flags per
    1,000 distinct names on real projects, all legitimate, so it stays opt-in.

  • Release-age signal (scan --release-age 72h). Warns on dependency versions published
    less than the given time ago, the question that matters during a worm outbreak. Publish
    times come from deps.dev (opt-in: it sends names and versions; cached), and a version
    deps.dev cannot date is listed separately, never treated as old. licenses --fetch and
    this signal share one deps.dev client and cache.

  • Maven transitive resolution. A pom.xml is resolved into the dependency tree Maven
    would build, in pure Rust and without running Maven: parent chains, properties,
    dependencyManagement and imported BOMs, default profiles, nearest-wins mediation with
    scope widening, exclusions, optional dependencies, version ranges and multi-module
    reactors. POMs come from ~/.m2/repository and a local cache; scan --maven-fetch also
    fetches missing ones from Maven Central (opt-in: it sends coordinates). Unresolvable items
    are named as partial coverage. Matched mvn dependency:list on test projects (25 of 25, and
    85 of 85 artifacts and versions for a Spring Boot project, with one scope label differing).

  • Supply-chain signals (scan --signals). Lockfile hygiene as warnings, read from files
    already parsed and with no network: install scripts (npm hasInstallScript), git, URL or
    path sources, registries outside the public ones or [settings.signals] registries
    (matched on the whole host, so lookalike hosts are caught), registry packages without a
    checksum, and third-party GitHub Actions pinned to a movable tag instead of a commit SHA.
    Opt-in, so existing reports and --fail-on-warnings gates do not change.

  • Known malware is first-class. OSV MAL- findings are always critical, are never
    hidden by --min-severity, and the remediation queue and fix plan say to remove the
    package and rotate credentials instead of suggesting a version.

  • License inventory and policy. fleetreach licenses gives every dependency's license
    (SPDX, with where it came from: composer.lock, package-lock.json, node_modules, the
    Cargo registry cache, virtualenv metadata, the NuGet cache) and a category (forbidden,
    restricted, reciprocal, notice, unencumbered). --fetch looks unknown ones up on deps.dev,
    opt-in because it sends package names, with a permanent local cache. A
    [settings.licenses] policy (allow/deny lists, per-category verdicts, unknown = "deny"
    by default, runtime scope, per-package exceptions with a reason) turns them into
    violations: exit 1 on a denied license. fleetreach sbom fills CycloneDX licenses from
    the same data. Cargo licenses agree with cargo-deny's on this repository.

  • fleetreach fix: verified fix branches. fix plan turns a saved report's
    remediation queue into per-repo edits (lock bumps, or blocked with the reason: no fix, a
    breaking jump without --allow-breaking, an unsupported ecosystem). fix apply performs
    each lock bump in a git worktree on a fleetreach/<campaign>/... branch with a lock-only
    command that runs no package code (cargo update --precise, npm update --package-lock-only --ignore-scripts, or a GitHub Actions tag rewrite), then re-scans:
    the commit is marked verified only when the targeted advisories are gone and nothing new
    appeared. Your work tree is never touched and nothing is pushed.

  • GitLab fleet sources. [[source]] kind = "gitlab" lists a GitLab group with all its
    subgroups (or a user namespace) on gitlab.com or a self-managed instance (api_url), with
    the same include/exclude globs, topics, archived and fork filters and sparse checkouts as
    GitHub. GITLAB_TOKEN (or token_env) authenticates private groups.

  • Stable SARIF fingerprints. Every result carries partialFingerprints keyed on the
    advisory, ecosystem, repo and package (not the version), so GitHub code scanning keeps one
    alert per finding with its history across scans and through bumps that do not fix it.
    Before, every result pointed at the same lockfile location, so code scanning could merge
    the same advisory across repos or packages into one alert.

Changed

  • Repo ids from fleet sources keep the full namespace path of nested URLs
    (group/sub/name, previously sub/name), so same-named projects in different subgroups
    no longer collide. A git source with a nested URL gets a new id, so a saved baseline
    or a [[repo]] override written against the old id needs updating.

fleetreach 1.3.0

Choose a tag to compare

@github-actions github-actions released this 31 Oct 01:19

Added

  • fleetreach sbom: CycloneDX 1.6 SBOMs. One BOM per repo from the same sources scan
    reads, in all 12 ecosystems: a component per package with its purl (git dependencies keep
    their remote and revision), dev-only packages as scope: excluded, the lockfiles'
    dependency graph, and compositions that mark components from partly-read sources
    incomplete. Deterministic (content-derived serial number, SOURCE_DATE_EPOCH); exit 2
    if any source could not be read. Validated against the official CycloneDX 1.6 schema on
    21 real repos (up to 13,291 packages), and against osv-scanner's package lists.

  • Python without a lockfile. The PyPI feeder now reads pylock.toml (PEP 751) and, when
    a repo has no Python lockfile at all, its requirements files (requirements*.txt,
    *requirements.txt, requirements/*.txt) with -r includes, -c constraints, hashes and
    markers. pip-compile and uv output is full coverage with dependency paths from # via
    annotations; pinned files with no sign of a resolver are labelled partial, and unpinned
    requirements direct-only with their names listed, never guessed. Checked against pip's own
    parser on warehouse, NetBox and Home Assistant (1,603 of 1,603 pinned packages). Fleet
    sources now check out these files too.

  • .NET without packages.lock.json. The NuGet feeder reads obj/project.assets.json
    (the full graph from dotnet restore, with dependency paths; partial when older than the
    project file), legacy packages.config, and otherwise the project files' PackageReference
    items with central package management, VersionOverride, global references and simple
    $(Property) values, labelled direct-only. Range and floating versions are named, never
    guessed. Checked statically on eShop, both CleanArchitecture templates and nopCommerce:
    every one of 236 package references read with its central version.

fleetreach 1.2.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 22:37

Added

  • Prebuilt binaries, Homebrew and a container image. Each tagged release now builds
    fleetreach (with the network feature) for Linux x86-64/ARM64, macOS Apple silicon/Intel
    and Windows x86-64, attaches the archives with SHA256SUMS and signed build provenance,
    publishes ghcr.io/tess-fun/fleetreach for linux/amd64 and linux/arm64, and renders a
    Homebrew formula. scripts/install.sh installs the right archive after checking its
    SHA-256. The GitHub Action installs the prebuilt binary (seconds) instead of compiling from
    source, with a new version input; it still builds with cargo where no binary exists.
  • OSV exports without per-ecosystem flags. Network builds fetch exactly the osv.dev
    exports a fleet needs into ~/.cache/fleetreach/osv/ and keep them fresh (conditional
    requests, atomic install, never replacing a good copy with a failed download). One
    --osv-dir (or FLEETREACH_OSV_DIR, [settings.osv] dir) laid out like the osv.dev
    bucket serves every ecosystem for air-gapped use. New fleetreach db sync and
    fleetreach db status. Each export's source, age and hash is recorded in
    provenance.osv.
  • pnpm and yarn lockfiles. The npm feeder reads pnpm-lock.yaml (v6, v9) and yarn.lock
    (v1 and berry, including aliases, patches and workspaces) with direct/transitive, dev scope
    and dependency paths, validated on 19 real lockfiles. Several npm-family lockfiles in one
    directory are all read.
  • Coverage labels. Sources read with less than a full resolved graph (pom.xml without
    gradle.lockfile, bun.lock/bun.lockb) are listed in a JSON coverage array, on
    stderr and in the summary line. --require-full-coverage makes them exit 2.
  • Fleet sources. [[source]] entries discover repos from a GitHub organization or user
    (with include/exclude globs, topics, archived and fork filters, GitHub Enterprise via
    api_url) or a list of https URLs. fleetreach fleet sync / scan --sync keep shallow,
    blob-less, sparse checkouts holding only lockfiles and manifests; the commit scanned is
    recorded in provenance.sources. A failed listing stops the run; a failed clone is an
    errored gap. git runs without hooks, submodules or the file:// transport, and the token
    never appears on the command line.

Changed

  • --max-db-age now also checks every OSV export used (upstream Last-Modified from a sync,
    else file mtime; unknown age refuses).
  • NVD severity backfill caches answers per CVE (7 days for a score, 1 day for none), waits
    only between real requests, and says how long an unkeyed lookup will take. NVD_API_KEY
    is now documented.

Fixed

  • --npm-prune-unreachable could mark packages NotReachable in a pnpm node_modules
    layout, whose transitive packages the import graph does not walk. It no longer prunes
    there.
  • --npm-prune-unreachable pruned tools the project runs. The npm import graph only started
    from imports, so a package run as a command (vitest, jest, stylelint, eslint from a
    package.json script or a CI workflow step) and everything it loads came out NotReachable;
    on matomo all 18 npm findings were, including a critical Vitest advisory. Executables named in
    scripts and .github/workflows are now resolved through each installed package's bin and
    treated as entry points, with witness chains such as vitest → vite → esbuild.