aveloxis-cve¶
A sidecar for Aveloxis that analyses commits on every branch of a repository, and complexity over time.
Some projects fix CVEs on separate maintenance branches (release, stable and LTS backports). Aveloxis walks only the default branch, so those fixes never reach its tables. aveloxis-cve records, for a chosen subset of the repositories Aveloxis already collects:
which commits are on which branch (
branch_repos,branch_commits);rolling complexity: sliding 60-day windows advanced one month at a time, with a full-repository scc snapshot and a changed-files-only analysis per window (
repo_labor_rolling).
Zero coupling¶
Aveloxis does not know aveloxis-cve exists.
aveloxis-cve reads
aveloxis_data,aveloxis_opsandaveloxis_scan, and writes only its own schema,aveloxis_cve.Nothing in
aveloxis_cvereferences an Aveloxis object (no foreign keys, views or functions). So no object of the sidecar's can stand in the way of Aveloxis's DDL, andDROP SCHEMA aveloxis_cve CASCADEremoves the sidecar completely.init-dbandmigratewait for their migration lock by polling, never with a blocking lock request that would stallCREATE INDEX CONCURRENTLYelsewhere in the database.aveloxis-cve keeps its own, fully independent clones, made from the forge URL Aveloxis records. It never reads, seeds from or writes Aveloxis's clone directory.
A repository must already be in Aveloxis, with a completed collection, before aveloxis-cve will analyse it.
Requirements¶
A complete Aveloxis install that has finished at least one collection cycle for every repository you track.
aveloxis-cve doctorchecks this.Go 1.26+,
git, andscc(for the complexity analysis).
Install¶
go install github.com/aveloxis/aveloxis-cve/cmd/aveloxis-cve@latest
A DBA creates the least-privilege role once, as a superuser, in the Aveloxis database (see the header of sql/roles.sql). The role can read aveloxis_data, aveloxis_scan and aveloxis_augur_data, except chaoss_user, which holds password hashes. Default privileges cannot exclude a table by name, so if Aveloxis creates chaoss_user after the script ran, re-run the script; doctor fails until you do. In aveloxis_ops it can read only schema_meta and collection_queue; the rest of that schema holds forge tokens, password hashes and API keys, so the role gets no wider grant there. It owns aveloxis_cve.
psql -d aveloxis -v ON_ERROR_STOP=1 \
-v cve_role=aveloxis_cve \
-v cve_password="$AVELOXIS_CVE_DB_PASSWORD" \
-v aveloxis_owner=aveloxis \
-f sql/roles.sql
The script refuses to create the role with an empty cve_password (for example, with AVELOXIS_CVE_DB_PASSWORD unset). To use another authentication method (peer, cert), create the login role first; the script then leaves its authentication alone. Re-running it needs no password.
Then:
cp aveloxis-cve.example.json aveloxis-cve.json # edit; see docs/configuration.md
chmod 600 aveloxis-cve.json
aveloxis-cve init-db # creates aveloxis_cve tables (first installation)
aveloxis-cve doctor # read-only health check
aveloxis-cve repos add --repo-group-id 3 # or --repo-id / --url / --url-file / --query
aveloxis-cve repos add --url-file urls.txt # one URL per line; - reads stdin
aveloxis-cve repos list
After installing a new release of aveloxis-cve, apply its schema changes:
aveloxis-cve migrate
Commands¶
Command |
What it does |
|---|---|
|
Print the version. |
|
First installation: create the |
|
After installing a new release: apply its schema changes to the installed |
|
Read-only checks: tools, directories, the connection, the Aveloxis columns aveloxis-cve reads, write privileges it should not have, the schema version, and the readiness of each tracked repo. |
|
Track repositories, selected by |
|
Manage the tracked subset. |
|
For each tracked repo that is ready in Aveloxis: clone it (first run) or fetch it into |
|
On each synced repo's default branch, computes every complete sliding window not yet stored, or marked due ( |
|
|
|
When each CVE fix reached each branch (including archived ones), and how long after the first branch. A fix is found by its message, a cherry-pick trailer, or an identical patch-id (manual backports). |
|
Re-resolve commit authors to Aveloxis contributors (read-only lookups): unresolved authors, or with |
|
Per-repo summary: default branch, branches, archived tips, commits, CVE-tagged commits, last sync. |
|
Graceful shutdown. Records a stop request in the database. The commands it stops are every |
What gets recorded (schema aveloxis_cve)¶
Table / view |
Contents |
|---|---|
|
The repositories you chose, with their last sync and labor outcomes. |
|
Every live branch and archived tip ( |
|
Every commit on any branch: CVE/GHSA ids, cherry-pick trailers, patch-id, and the Aveloxis contributor it resolves to. |
|
Every commit's files counted exactly as Aveloxis counts them in |
|
Full membership: one row per (branch, commit), with |
|
Commits by branch and file. |
|
Rolling complexity windows: per-window totals, the full scc snapshot, and changed files (A added / D deleted / M modified / N touched but unchanged / X created and removed). A window with |
|
scc results keyed by file content, file name and scc version. |
|
Each |
|
CVE fixes, how they were matched, and when they landed on each branch. |
Windows are (start, end]: a commit that lands exactly at start belongs to the previous window. When a sync changes history inside computed windows (a late push of an old-dated commit, a force-pushed default branch), the next labor run recomputes them; the stored windows stay, marked, until each is replaced. Landing times never run backwards along a branch, even when committer clocks did. The first window is [first, end], so the first commit is counted. A snapshot counts the files Aveloxis's repo_labor would: those scc's own walk reaches in a checkout. A tracked file that a .gitignore, .ignore or .sccignore names is not counted (for example, redis's deps/jemalloc/configure), and neither are .gitmodules paths or .git/.hg/.svn directories. A .gitignore, .ignore or .sccignore that is a symlink is read through the link, as in a checkout. A symlinked .gitmodules is not, because git cannot check such a tree out. aveloxis-cve applies that walk to each snapshot's tree without checking it out, using the matcher scc 3.7.0 is built with. A file the walk skips still appears among a window's changed files, but without metrics. Each file the walk reaches is measured alone with scc (--no-gitignore --no-ignore --no-scc-ignore), by its name and content only, so cached measurements carry over between snapshots.
Documentation¶
docs/ holds the full documentation:
the schema diagram;
the analysis guide, with tested SQL for every research question: CVE fixes and their propagation and backports, complexity over the windows, and the two together.
The same pages build into an HTML site with Sphinx (docs/conf.py); see development for the command.
Data¶
docs/data.md describes every table, view and column of the aveloxis_cve schema: what a row is, where each value comes from, which command writes it and when, the Aveloxis data read, the personal data stored, and how to remove it.
Git version¶
New clones use git's reftable ref format when git is 2.45 or newer. That lets them hold branch names a filesystem-backed ref store cannot: non-UTF-8 names, and names differing only in case on macOS. Such a clone cannot be read by an older git; if you downgrade git, delete clone_dir and let sync re-clone.
Development¶
go test ./... # unit tier
AVELOXIS_CVE_TEST_DB="postgres:///postgres?host=/tmp" go test ./... # + DB tier
gofmt -l . && go vet ./... && staticcheck ./... && golangci-lint run ./...
AVELOXIS_CVE_TEST_DB is a DSN for a superuser on a disposable test cluster, never a production one. CREATEDB is not enough: the sql/roles.sql tests run that script, which requires a superuser. Each DB-tier test gets its own scratch database (cvet_*), which is dropped afterwards. Some tests also create cluster-wide login roles (cvet_role_*) and drop them when they finish; a run killed midway can leave some behind. Those tests log in as the scratch roles, with random passwords, over the DSN's host and port, so the cluster's pg_hba.conf must allow that (password or trust authentication, not peer only). Scratch databases are created with ICU en-US collation, so golden results agree on every machine: the cluster must be PostgreSQL 15 or later, built with ICU, with a UTF-8 or C default locale (LC_COLLATE and LC_CTYPE).
The tests run git with no global or system git configuration, so your own ~/.gitconfig does not change their results. Tests that need reftable refs skip when git is older than 2.45. Under CI ($CI set), a missing tool or a git that is too old fails the run instead.