OSV recommendations
Dependency scanning surfaces individual CVEs. The Recommendations tab on Security › Findings › Dependencies (/<org>/_admin/security/findings/dependencies?view=recommendations) turns that list into a fix list: every open finding with a published fix becomes one card — repo + package + current → fix + which CVEs that one upgrade resolves.
How recommendations are computed
The grouping key is (repo_full_name, ecosystem, package_name, current_version, fixed_version). Findings sharing all five collapse into one card.
Sorting is three-stage:
- Reachability — a card takes the most reachable reachability verdict of the findings it fixes: reachable first, then unknown (including not analysed), then not reachable.
- Severity (within a verdict) — critical → high → medium → low.
- EPSS score (within severity) — the highest EPSS score across the bundled vulns wins.
So a low-severity advisory your code reaches sorts above a critical one that is not reachable, and within one verdict and severity, an advisory that is being exploited sorts above a theoretical one. A card that is not reachable is still listed; it only moves down. The overview’s top recommendations and the weekly digest use the same order.
What the card shows
acme/api critical
npm:lodash 4.17.20 → 4.17.21
3 vulns fixed · EPSS 23.4% · CVE-2021-23337, CVE-2020-8203 +1A card whose verdict is reachable or not reachable also shows Reachable or No call path next to its severity.
- Manifest paths — if the same package is pinned in
package-lock.jsonandpnpm-lock.yaml, both are listed. - EPSS — the highest exploit-prediction probability across the bundled CVEs (0–100%). The daily refresh job pulls EPSS data from FIRST.org.
- Vulnerability IDs — first three shown inline; rest in a
+Nsummary.
Getting the upgrade PR
Each card has an Open fix PR button for packages in the ecosystems that get security fixes (see Supported ecosystems). It opens one pull request that bumps that package in that repository, as your organisation’s dependency bot, and it waits for review or merges when its checks pass, as your organisation chose; see Merging. Once requested, the card shows Fix proposed: #N with the state of the pull request.
Other ways to get the bump:
- Let Dependency updates open the PRs. With Dependency updates enabled, Renovate opens a security update PR in its next nightly run after an advisory (OSV) is published for a dependency, ignoring your
scheduleand the release-age wait. When an open Renovate PR already bumps a package, the finding on the Findings tab links to it (Renovate PR #n). - Trigger a run now. The Recommendations tab has a Trigger a dependency-update run button that starts an out-of-cycle Renovate run for the whole organisation, at most once an hour. If Dependency updates is not enabled, the tab links to the page where you enable it.
- Bump it yourself. Each card names the package, the installed version and the suggested fixed version, so you can make the change in your own branch and let the PR scan confirm the findings are gone.
The old Open upgrade PR endpoint stays retired and answers 410 Gone; the Open fix PR button is its replacement.
Needs migration: the fix is under another package
Some advisories have no fix on the package you use, but are fixed under a successor that the advisory itself names: a new module path or major version, or a renamed package. Examples from real advisories:
| You use | Fixed only in |
|---|---|
Go github.com/docker/docker | github.com/moby/moby/v2 |
Go github.com/pion/dtls/v2 | github.com/pion/dtls/v3 |
Go gopkg.in/square/go-jose.v2 | gopkg.in/go-jose/go-jose.v2 |
npm request | @cypress/request |
Such a finding shows Needs migration to <package> (fixed in <version>) instead of “no fix yet”, on the Findings and By package tabs, in the API (needs_migration, see Findings API) and in the weekly digest. It does not appear on Recommendations and gets no Open fix PR button: moving to another module or package changes imports and often the API, so it is a code change for you to make, not a version bump.
How the successor is chosen:
- The advisory must affect your installed version, and list no fixed version of your package above it. If your own package has a fix, the finding gets that fix as usual.
- The successor is another package in the same ecosystem that the advisory lists with a fixed version. Its version shown is the lowest one the advisory does not affect. An advisory’s aliases (for example a Go
GO-…record and itsGHSA-…twin) are read together. - When several are listed, Go prefers the same major version as yours (
go-jose.v2togo-jose/go-jose.v2, notgo-jose/v4), then the lowest higher major, and never suggests a lower major of the same module. Other ecosystems prefer a name that ends in yours (requestto@cypress/request). - When the versions cannot be ordered, or no other package is fixed, the finding keeps “no fix yet”. An advisory that is fixed nowhere, such as
golang.org/x/crypto/openpgp(unmaintained), is never shown as a migration.
Why this is not the same as the Findings tab
The Findings tab is the canonical source — one row per (CVE × manifest). Recommendations are the actionable summary:
- A package with no published fix never appears on Recommendations (it’s not actionable yet).
- A package fixable by a single upgrade appears once on Recommendations and N times on Findings (one per CVE).
- A dismissed finding never appears on either.
Use Findings to triage individual CVEs and dismissals; use Recommendations to drive the day’s actual fix work.
Via REST API
GET /_app/api/v1/orgs/:slug/security/recommendations (findings:read) returns the Recommendations themselves, in the order of the tab: one entry per repository, package and current version, with fixed_version, highest_severity, vulnerability_count, vulnerability_ids, manifest_paths, max_epss, reachability, known_exploited and finding_id, the default-branch finding a security fix request names (null when every finding of the group is on a pull request).
The underlying CVE findings — the raw data that Recommendations rolls up — are available on the public API surface. Use this when building a custom dashboard, exporting to a ticketing system, or driving prioritisation from an AI agent.
- List dependency findings
GET /_app/api/v1/orgs/:slug/code-security/deps/findings— one row per (CVE × manifest), withpackage_name,current_version,fixed_version,severity,vulnerability_id,manifest_path. Group client-side by(repo_full_name, ecosystem, package_name, current_version, fixed_version)to reproduce the Recommendations rollup. - Dismiss a finding
POST /_app/api/v1/orgs/:slug/code-security/deps/findings/:id/dismissbody:{ "reason": "..." }
The list endpoint requires a Personal Access Token (PAT) with the findings:read scope; dismissals require findings:write:
curl -H "Authorization: Bearer ${FREMFORGE_PAT}" \
"https://frem.sh/_app/api/v1/orgs/acme/code-security/deps/findings?include_dismissed=false"See the public REST API reference for the full OpenAPI specification.
See also
- Fix-by SLA — how the SLA pill on the Findings tab is computed.
- Security digest — emails the top 5 fixable findings, reachable first, every Monday.
- Push protection — secrets blocked at push time, the upstream half of the same supply-chain triad.