Skip to main content

Malicious packages

fremforge checks the packages you actually ship against the OSV MAL-* advisories: packages a registry or researcher has confirmed as deliberately malicious, such as a typosquat or a hijacked release that steals credentials on install. Two things are checked:

  • Repositories. The latest SBOM of each repository’s default branch.
  • Container images. The language packages inside every image published to your organisation’s package registry.

A malicious package is always critical. It is not a vulnerability with a fixed version: remove it, and treat any machine that installed or ran it as compromised.

This is separate from Malware scan, which runs ClamAV signatures over uploaded files.

When the check runs

WhatWhen it is checked
A repository’s default branchRight after each push to it (its SBOM is built and matched within about a minute), and again every day at 05:00 UTC
A container imageAfter each push, re-tag or delete in the package registry (within about 15 minutes), and again every day

The daily run matters because a package is often listed as malicious weeks after it was published. Code and images that have not changed are matched again against the newest advisories.

Matching runs on fremforge’s own scanners against an offline copy of the OSV database. Nothing about your code or images is sent to osv.dev.

What is matched inside an image

The image is scanned with Trivy, the same pull that container image scanning uses. Its language packages are matched: npm, PyPI, Maven, Go, crates.io, RubyGems, NuGet, Packagist, Pub and Hex. Operating-system packages (apk, deb, rpm) are not, because MAL-* advisories are about language registries.

For a multi-architecture image the linux/amd64 variant is the one scanned.

Findings

Findings are listed at Org admin → Code security → Dependencies → Malware. Filter by source (Repositories or Container images) and by state:

  • Open. The package is on the default branch, or in at least one published digest of the image.
  • Dismissed. Someone decided it is acceptable, with a reason.
  • Resolved. It is gone: removed from the default branch, or no published tag or digest of the image contains it any more. If it comes back, the finding reopens.

An image finding is one row per image name. It lists the tags and digests that currently contain the package, so re-tagging the same content does not create a second finding.

The tab’s badge and the Dependency malware tile on the organisation overview count open findings from both sources.

Alerts

A security alert is sent to the organisation members who have security alerts switched on when a malicious package is found for the first time, when a resolved one comes back, and when a dismissal reaches its end date. A finding that is still there the next day does not alert again. Open findings are also counted in the weekly security digest.

Dismissing a finding

Expand Dismiss on the row, pick a reason, and optionally set an end date. After the end date the finding reopens and alerts again. Bulk dismiss is available on the Open list.

  • Repository finding. Dismissing it also stops pull requests in that repository failing the dependency scan on the same package version and advisory, with the same end date.
  • Image finding. Dismissing it stops it blocking pulls of the image (see below). It does not dismiss the same package in any repository, even one with the same name.

Every dismissal is recorded in the audit log with who, why and until when.

Pulling an image that contains a malicious package

A pull of a container image whose digest has an open, undismissed malicious-package finding is refused with 403 DENIED. The message names the package and advisory and links to the Malware tab. This applies to every organisation, whatever its image scanning block setting, and to pulls by tag and by digest.

To unblock a pull: push a fixed image, or dismiss the finding.

Rollout. Since 2026-10-03 this check runs in observation mode: a pull that would be refused is logged but still served. Enforcement will be switched on after the observation period, and this page will say so.