Skip to main content

Supported ecosystems

This is the one list. When another page names ecosystems, it follows this page.

Dependency scanning

Dependency scanning (osv-scanner, on every pull request and on the default branch) reads these files:

EcosystemFiles
npmpackage-lock.json, yarn.lock, pnpm-lock.yaml, bun.lock (not the binary bun.lockb)
PyPIrequirements.txt, poetry.lock, uv.lock, pdm.lock, Pipfile.lock
Gogo.mod
Mavenpom.xml, with every dependency it pulls in: resolved through your organisation’s Maven proxy, without running Maven; see Maven dependency resolution
Gradlegradle.lockfile
CargoCargo.lock
RubyGemsGemfile.lock
Composercomposer.lock
Hexmix.lock
pubpubspec.lock
Conanconan.lock
CRANrenv.lock
NuGetthrough Trivy, with the container image scan of the repository
Terraform and OpenTofu providers.terraform.lock.hcl: the provider binaries the lock pins; see Terraform and OpenTofu providers
GitHub Actionsthe uses: lines of the workflow files in .forgejo/workflows/, .gitea/workflows/ and .github/workflows/; see CI action versions

Container images are scanned by Trivy: the operating-system packages and the language packages inside each image. See Container image scanning.

Maven dependency resolution

A pom.xml names only its direct dependencies. To see what those pull in, dependency scanning resolves each pom.xml the way Maven would: parent poms, imported BOMs, <dependencyManagement>, properties, scopes, exclusions and version ranges. It reads poms only. No Maven, no plugin and no code from your repository runs.

  • Where the poms come from. Every pom is read through your organisation’s Maven proxy, with the platform’s proxy as the fallback. A multi-module build’s own modules are read from the repository. <repositories> declared in a pom are not contacted: an artifact that only a private repository holds is not resolved, and is named (below). No resolution service outside fremforge is asked.
  • What uses the result. The resolved tree is what dependency findings, the fremforge/dep-scan status, the repository’s SBOM and transitive fix pull requests read, so they agree.
  • Cached. A tree is reused for 24 hours while the poms are unchanged. Advisories are matched afresh on every scan, so a new advisory is never hidden by the cache.

When a pom cannot be resolved, it never reads clean. Its direct dependencies are still checked, and:

  • the fremforge/dep-scan status says so even when it is green: 1 pom.xml not fully resolved: transitive dependencies not checked;
  • the pull request comment lists the pom under Not fully checked, with the reason and the artifacts the proxy did not have, even when there are no findings;
  • the dependency findings and SBOM pages show Not fully checked, with a link to the dependency proxy when an artifact is missing;
  • the SBOM carries it as a coverage note (CycloneDX: the fremforge:coverage:maven-unresolved property and an incomplete composition; SPDX: the creation comment);
  • GET /orgs/{org}/code-security/deps/coverage (scope findings:read) returns it for the default branch. By default it lists only repositories with something not fully checked; all=true lists every repository with a coverage record, and repo=<name> filters to one.
curl -sS -H "Authorization: Bearer $FREMFORGE_TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/<org>/code-security/deps/coverage"

The usual reason is an artifact your Maven proxy does not have, such as an internal library published elsewhere: add that repository as an upstream of the proxy. Other reasons are the proxy not answering, a timeout, or a build with more than 60 poms (the rest are reported, not resolved).

Known limits. The resolution reads the poms; it does not run the build. So:

  • a build that rewrites its dependencies with a plugin (maven-shade-plugin relocation, flatten-maven-plugin, a generated pom) is checked as its poms declare it, not as the plugin changes it;
  • a profile that depends on your build machine’s environment (a system property, a file, the operating system or the JDK) may not be applied the way your build applies it.

For the exact tree your build ships, push a CycloneDX SBOM from CI; it is matched as well.

Terraform and OpenTofu providers

There is no advisory database for Terraform providers, but a provider is a Go program. For each provider version in a .terraform.lock.hcl, fremforge scans the provider binary for the Go modules it was built from, and reports their advisories as dependency findings of the repository:

  • Ecosystem Terraform, package the provider address (for example registry.terraform.io/hashicorp/null), version the locked version, manifest the lock file. The summary names the Go module and its version, for example google.golang.org/grpc@v1.69.4 (built into the provider).
  • Only the binary the lock installs. A finding is reported only when one of the lock’s hashes (zh: or h1:) is the provider zip that was scanned. A lock that accepts other bytes gets no findings for a binary it would not install.
  • The same check as any dependency. The findings go through your dependency threshold, dismissals and the comparison with the base branch, so a pull request is blocked only by findings it adds.
  • The first scan of a version is not immediate. A version fremforge has not seen before is queued when a lock that pins it is first scanned, and scanned in the background, usually within the hour. Its findings appear on the next scan of each repository that locks it; until then that version has none.
  • Reachability. Each finding says whether the provider binary links a function the advisory names: reachable or not reachable, or unknown when that cannot be decided. See Reachability.
  • Fixed version. The fixed version of a finding is the first provider release whose binary no longer carries the advisory, among the next ten releases after yours and the newest one. fremforge scans those releases the same way, so it can take an hour or two after the first scan of your version to appear. It stays empty when no such release exists yet, which is common: a provider’s newest release often still ships the vulnerable module.
  • Where the binary comes from. The linux_amd64 zip is fetched once, through fremforge’s own provider mirror, from the location the provider’s registry publishes. For HashiCorp’s providers that is HashiCorp’s release site, releases.hashicorp.com, which fremforge does not operate: it is used only to fetch the public provider zip, nothing about your repository is sent to it, and fremforge keeps the copy it scanned.

Not covered: Terraform modules; a provider built before Go 1.18 (for example hashicorp/null 3.1.0), whose binary carries no module list to read; and the Go standard library the provider was built with. A security fix for a provider is not opened: update the version in your configuration and run tofu init -upgrade or terraform init -upgrade.

CI action versions

Every uses: owner/repo@<version> in a workflow file directly under .forgejo/workflows/, .gitea/workflows/ or .github/workflows/ is matched against the GitHub Actions advisories (GHSA) in fremforge’s own copy of the OSV database, since 18 October 2026. No call is made to GitHub: the advisories come from that copy and the version from your workflow file.

  • The version is the tag (actions/download-artifact@v4.1.2), or, for an action pinned to a commit, the version comment beside it (actions/download-artifact@<sha> # v4.1.2), which is how pinning tools write it. A pinned action without such a comment has no version to match.
  • A finding is a dependency finding: ecosystem GitHub Actions, package owner/repo, the workflow file as the manifest. It goes through your dependency threshold, dismissals and the comparison with the base branch, so a pull request is blocked only by findings it adds, in the fremforge/dep-scan check.
  • If fremforge’s copy of the GitHub Actions advisories is missing, a repository whose workflows name versioned actions fails its dependency scan rather than passing with no findings.

Not covered: a major-only tag (@v4) or a branch, which names no version; workflow files in sub-directories or outside those three directories, composite actions’ own action.yml, and symlinked workflow files. Whether a reference is pinned to a commit is checked separately; see Workflow pinning.

Security fixes

Security fixes open a pull request for:

  • npm, including Yarn, pnpm and Bun with bun.lock (not the binary bun.lockb: run bun install --save-text-lockfile once to switch);
  • Go;
  • PyPI;
  • Maven;
  • Gradle with a lockfile, which is refreshed in a job on your organisation’s own runner;
  • NuGet;
  • Cargo;
  • Composer, composer.json and composer.lock;
  • pub, pubspec.yaml and pubspec.lock;
  • RubyGems, Gemfile.lock, which is updated in a job on your organisation’s own runner (Bundler reads the Gemfile, which is Ruby code fremforge does not run);
  • Hex, mix.lock, which is updated in a job on your organisation’s own runner, in the official elixir image (Mix reads mix.exs, which is Elixir code);
  • GitHub Actions, the workflow file: the action is moved to the lowest version that fixes every open advisory, pinned to that tag’s commit with the tag as a comment (@<sha> # v4.1.3). The tags are read from the action mirror on frem.sh, never from github.com;
  • base images: the FROM line of a Dockerfile, within the same major version.

They fix direct dependencies, and these transitive ones (see Transitive dependencies):

  • npm with package-lock.json, pinned with overrides;
  • pnpm with pnpm-lock.yaml (lockfile version 9.0), pinned with overrides;
  • Yarn 1 with yarn.lock, pinned with resolutions (Yarn 2 and later are not supported);
  • PyPI with uv.lock or poetry.lock, by moving the lock entry;
  • Maven, pinned with <dependencyManagement> in the pom.xml the finding came from (or the root pom.xml, for a package seen in an uploaded SBOM);
  • Gradle with gradle.lockfile, pinned with a dependency constraint;
  • Go modules marked // indirect in go.mod;
  • Composer packages that composer.json does not name, by updating composer.lock in a job on your organisation’s own runner;
  • RubyGems and Hex: every fix is a lock file update, so a package another package pulls in is fixed the same way as one the manifest names.

Not fixed, each with its reason on the finding: bun.lockb, which only Bun can rewrite, and pub and Bun packages that the manifest does not name. For any other ecosystem, a fix request answers not yet supported.

Reachability

Reachability gives a verdict for:

EcosystemLevel
npmfunction, or import when the advisory names no functions
Gofunction, from the Go binaries in your images
PyPIimport
Mavenimport
Terraform and OpenTofu providersfunction, from the provider binary the lock pins

Every other ecosystem gets the verdict unknown.

Dependency proxy

The dependency proxy serves npm, PyPI, Maven, NuGet, Go, Cargo, Helm and RPM packages, container images, and Terraform and OpenTofu modules.

Not covered

Terraform modules and Helm chart versions are not checked against vulnerability advisories. CI action versions are; see CI action versions. Terraform and OpenTofu providers are, from their binaries; see Terraform and OpenTofu providers. The container images a Helm chart deploys are; see Images your Helm charts deploy. Infrastructure-as-code files get misconfiguration checks only, in their own check, fremforge/iac-scan; see IaC scanning. Whether action references are pinned to a commit is checked too; see Workflow pinning.