Skip to main content

Pulled package versions

A dependency finding says that a version is declared somewhere. The pull census says something else: which package versions were actually downloaded, by which consumer, and how recently. It is counted from the registry access log, so it covers your own packages in the fremforge registry and the packages your organisation pulls through the dependency proxy, including pulls from CI outside fremforge that use a registry robot.

What counts as a pull

A pull is a download that succeeded and names a version: an npm tarball, a PyPI file, a Maven artifact, a NuGet package, a Go module zip, a generic or other registry file, or a container image pulled by tag. These are not counted:

  • metadata reads, such as an npm packument or a PyPI simple index;
  • refused requests;
  • container layer downloads, which name only a digest.

A download that a policy in shadow mode would have refused, but let through, counts as a pull.

Consumers

Every pull is attributed to the consumer the access log recorded:

KindWhoNamed by
jobA Forgejo Actions job tokenThe job’s repository, <owner>/<repo>
robotA registry robotThe robot’s name. login holds its bot user
botAnother fremforge system botIts login
userA person’s token or sessionTheir login
anonymousA request without a credentialNothing

Which advisories are joined

  • Versions pulled through the dependency proxy (npm, PyPI, Maven, NuGet and Go) are matched against the OSV advisory index the proxy’s package policy evaluates. Version ranges are evaluated, not just exact versions. source is advisory_index.
  • Versions of your own registry packages carry the open findings of that package file, the same findings the package policy reads. Dismissed and resolved findings are left out. source is package_findings.
  • Container images are counted, but this list shows no advisories for them. Image findings are on the image scanning pages.

In the console

In the org admin, open Security → Components → Pulled versions. The page lists the same versions as the API, with the same order and filters: package name, period (today, or the last 7, 30, 90 or 365 days), minimum severity, ecosystem, source (your own registry or the dependency proxy), consumer type and consumer. Tick Include versions without a known advisory to see every pulled version, not only the vulnerable ones. Each row shows the worst severity, up to three advisories with a fixed version, the number of pulls by consumer type, the top consumers and when the version was last and first pulled. The line above the table says up to when access events have been counted. Next page and First page move through the list; Export CSV downloads every matching version with the current filters, in the same columns as the API’s CSV.

Reading it with the API

With an API token that carries components:read or findings:read:

curl -sS -H "Authorization: Bearer $FFP_TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/acme/components/pulled?days=30&min_severity=high"

By default the list holds only vulnerable versions, most severe first and then most recently pulled. Each item has the version and its purl, the worst severity, the advisories with their fixed versions, the total pulls, the pulls per consumer kind, first_seen_at and last_seen_at, and up to ten consumers with their own counts and times.

FilterMeaning
daysHow many UTC days back, today included: 1 to 730, default 30
vulnerabletrue (default) for versions with an open advisory; false for every pulled version
min_severitylow, medium, high or critical
ecosystemThe package type: npm, pypi, maven, nuget, go, container, …
originregistry (your own packages) or proxy (the dependency proxy)
nameA package name, exact
consumer_kindjob, robot, bot, user or anonymous
consumerA repository (owner/name), a robot name or a login

Pass a page’s next_cursor as cursor to get the next page, with the same filters, and stop when it is null. A page holds up to 500 versions (limit). Add format=csv for every matching version as CSV. A query that matches more than 50,000 versions answers 413 too-many-rows; narrow it. See the API reference for the full shape.

How fresh it is, and how long it is kept

The census is rolled up from the access log every hour. window.rolled_up_to in the response says up to when access events have been counted.

The census follows the access log’s evidence retention, and is deleted by the same daily job: a day’s counts go once the newest download they count is past the access_log retention, or the access_log_ci retention for CI pulls through the dependency proxy. While a legal hold is in place, nothing is deleted.

In the data export

Every data export contains the census as metadata/pulled-versions.ndjson, one line per UTC day, package version and consumer, the rows this page adds up. See Export schema. The advisories are not in the file: they are joined when you read the list, from advisory data that changes over time.

Limits

  • A pull is not a deployment. A version can be pulled by a build and never shipped, or pulled once and cached for months.
  • Pulls from caches outside fremforge are not seen. Only requests that reach the fremforge registry or dependency proxy are counted.
  • Teams are not recorded. A user’s pull is attributed to the user.