Blog

The Versioning Ghost: Why OS Context is the Missing Coordinate

Amit Agam
January 7, 2026

In the world of Software Composition Analysis (SCA), we often treat the tuple of (package_name, version) as a unique identifier. For example, given an NPM package angular version 1.8.0 - we would know precisely which source code was used, and what vulnerabilities affect that version.It is a common misconception that a package version maps directly to a fixed set of source code and, by extension, a static vulnerability profile. 

In reality, a single package version can represent entirely different security states depending on the underlying operating system. This discrepancy fundamentally challenges the standard mental model that links a version number to a specific source code version. Without accounting for these environment-specific variations, organizations operating solely on package names and versions risk significant inaccuracies in their vulnerability reporting

Take for example Alpine's musl library. In Alpine 3.21, version 1.2.5-r9 contains security fixes for CVE-2025-26519. Yet, in the early builds of 3.22, the same version string was used for a build that lacked those fixes (which only arrived later in 1.2.5-r10). This is no minor issue. To quantify, we mapped Alpine versions against package strings and compared APKBUILD hashes. We found over 10,000 instances where the same version string yielded different hashes; even after fuzzy matching to ignore trivial changes, over 1000 "version collisions" remained where the actual patches differed.

This isn't just an Alpine quirk; it’s a systemic challenge. In the Debian and Ubuntu ecosystems, the same version string can hide divergent security realities. For instance, the VLC media player often sees version collisions; a specific version like 3.0.16 might exist in both Debian Stable and an Ubuntu LTS release, but the Debian snapshot may include backported security fixes that the Ubuntu version lacks. Because Ubuntu often syncs from Debian at a specific point in time, the "same" version string across these distros frequently masks different patch levels.

The RPM ecosystem (RHEL, Oracle Linux) attempts to solve this by including the target OS (e.g., .el8) in the string. However, even this is insufficient. Oracle Linux and RHEL may build from different source repositories or apply vendor-specific patches. A security rule applied to openssl-1.1.1k-1.el8 on RHEL might be inaccurate when applied to the same string on Oracle Linux, as the underlying source origins vary. 

To address these ghost versions, security tools must move toward more descriptive formats like Package URL (purl), which encodes the distribution and version directly (e.g., pkg:apk/alpine/musl@1.2.5-r9?distro=3.21). This transforms the identifier from a vague label into a precise coordinate, ensuring vulnerability management is a three-dimensional process: Package, Version, and OS Context. 

Whether you're tracking "MongoBleed" (CVE-2025-14847) or a simple path traversal, your security posture depends on the "where" just as much as the "what". Without the OS version as a mandatory coordinate, you aren't just scanning - you're guessing.