DataRobot cve-sync
Homepage · Documentation · Support
Note
This project is in beta (0.0.x). CLI flags, action inputs, and policy entries may change
between releases. Releases are patch bumps, and the ref you pin decides both the tool version and
the policy content, so pin to a tag and read the changelog before bumping.
One curated list of minimum safe Python package versions, propagated into every repo that resolves those packages, and enforced there.
Some CVE fixes cannot travel through package metadata, so every repo has to carry its own copy of them. cve-sync keeps those copies correct. It is not a scanner: detection and ticketing stay with whatever corporate scanner your org already runs, and cve-sync picks up after that, from a version someone has decided is safe. ADVANCED.md explains why this is necessary.
Copy examples/1-gate-only.yml into your repo as
.github/workflows/cve-sync.yml:
name: cve-sync
on: [pull_request]
permissions:
contents: read
jobs:
gate:
uses: datarobot-oss/cve-sync/.github/workflows/cve-sync-gate.yml@main
permissions:
contents: readNo inputs. It covers every resolution root in the repo plus any lock artifacts a copier template ships, and it runs in regression mode: it fails a pull request only if that pull request makes compliance worse. That is what makes it safe to make required.
The body of that job lives here, not in your repo, so a fix upstream reaches you
on your next run with no pull request of your own to open, review, and merge.
examples/README.md has the reasoning and the tradeoff.
Start here, and run it for a cycle before adding anything that writes.
cve-sync wiring --write
That writes .taskfiles/cve-sync.yml, or the make dialect of the same commands
if your repo uses make. Include it once at the repo root:
includes:
cve-sync: ./.taskfiles/cve-sync.ymltask cve-sync:status # is any resolution root behind the policy? reads only
task cve-sync:sync # splice the residue into every root and re-lock
task cve-sync:check # strict compliance over every root's lock
That file is generated, not maintained. Once the resync job from step 3 is wired,
it rewrites the file on every run, so your copy cannot fall behind the way a
hand-copied one does. Nothing to .gitignore and no cache to manage: the policy
ships inside the wheel, so fetching the tool fetches the policy with it.
uvx --from "git+https://github.com/datarobot-oss/cve-sync.git@main" cve-sync check --target .
Edit policy/floors.toml, validate, and open a pull request here:
[[floor]]
package = "aiohttp"
spec = ">=3.14.1"
cve = ["CVE-2025-69229"]
ticket = "PROJ-31617"uv run cve-sync validate
If something caps that package below the floor, it needs a scoped override too.
task fix-cve works that out for you.
ADVANCED.md walks through every command and every piece of the tooling in plain language. Read that when you need a command you have not used yet, or you are wiring up more than the gate.
docs/ goes a level deeper on each subject: the policy model, adopting cve-sync, copier templates, base images, finding and fixing CVEs, and developing cve-sync.
The tooling is general: cve-sync reads any uv.lock and floors are ordinary
PEP 440 specs. policy/ is not. It is DataRobot's own registry, chosen for the
packages DataRobot's stacks resolve, so pointing it at an unrelated project
mostly produces no-ops. Fork it and replace policy/, or keep the tool and point
it at your own tree with --policy.
This repo lives in datarobot-oss, which carries no official support. Issues and
pull requests are welcome: see contributing and
security. The repo is datarobot-oss/cve-sync; the
package and CLI it ships are datarobot-cve-sync and cve-sync.
Beta, and in use. The full build (policy model, the floor gate, rendering, the resync, the audit and fix commands, and the CI actions) is in place. Adoption across the dependency pyramid is ongoing.