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:
| Kind | Who | Named by |
|---|---|---|
job | A Forgejo Actions job token | The job’s repository, <owner>/<repo> |
robot | A registry robot | The robot’s name. login holds its bot user |
bot | Another fremforge system bot | Its login |
user | A person’s token or session | Their login |
anonymous | A request without a credential | Nothing |
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.
sourceisadvisory_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.
sourceispackage_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.
| Filter | Meaning |
|---|---|
days | How many UTC days back, today included: 1 to 730, default 30 |
vulnerable | true (default) for versions with an open advisory; false for every pulled version |
min_severity | low, medium, high or critical |
ecosystem | The package type: npm, pypi, maven, nuget, go, container, … |
origin | registry (your own packages) or proxy (the dependency proxy) |
name | A package name, exact |
consumer_kind | job, robot, bot, user or anonymous |
consumer | A 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.