A Malware Record Can Be Wrong in Both Directions. We Found Both in Our Own Package Check on the Same Day.
Every package check that uses OSV's malicious-package data makes the same quiet assumption: the versions in the record are the versions that are bad. On October 18 we found that assumption wrong in both directions inside our own check-package tool, once in the morning and once in the evening. One error blocked clean software. The other let malware through. Here is each one, and the single rule we now use for both.
Too many blocked: a legitimate package compromised once
On October 8 a worm in the Mini Shai-Hulud family poisoned one version of tensorlake, an AI-agent SDK: 0.5.144. Its OSV record lists that version. It also carried a version range with a start and no end, imported from a GitHub advisory that listed "every version". Our check followed the range, so it blocked the clean 0.5.143 and the maintainers' fixed 0.5.145 along with the poisoned release. A false positive on a legitimate SDK teaches people to ignore blocks, which is worse than the false positive itself.
We scoped that record to 0.5.144 (the override switches itself off if OSV changes the record) and opened a pull request asking OpenSSF to narrow it upstream.
Too few blocked: a package that is malware from the start
That evening, safeguard.sh published an analysis showing the opposite problem: on October 18, 71 PyPI packages and 53 npm packages were still serving versions their malware records do not name. We checked our own tool against their example, leakdeep, a PyPI package presented as an OSINT and credential-leak tool (OSV MAL-2026-17921). The record lists the nine versions that existed when it was written. Asked about an unlisted version, our check answered "review", not "block". For a package that is malware in every release, the author only has to upload a new version to get past a version-scoped check. leakdeep itself has since been removed from PyPI, so no one can install it now, but the gap was real for every package in that analysis.
One rule for both
The two cases need opposite answers, and a list of special cases would fail the third time. So we use one test, applied only after the record and OSV's own range have been checked:
If every version the registry published before the record is listed as malicious, the package is the malware. Later versions inherit the block.
If any earlier version is clean, the record stays version-scoped. That is what a legitimate package compromised once looks like.
tensorlake has clean versions before its record, so only 0.5.144 blocks. A package like leakdeep has none, so an unlisted new version blocks. If the registry cannot be reached, nothing changes. It shipped the same evening, and we checked it against live packages: tensorlake 0.5.145 still returns review, and the unlisted 0.1.24 release of the compromised MemTensor plugin also returns review, because that plugin had unlisted versions before its record too. One edge case we accept on purpose: a legitimate package whose only release before its record was the poisoned one would block its next, clean release. That is rare. A brand-new single-version typosquat, which this rule now blocks, is common.
What to do if you run your own check
Read the record's versions and ranges together, and ask which kind of package it is before deciding what an unlisted version means.
Treat an open-ended range on a long-lived legitimate package as a likely import artifact, and a short version list on a young, low-download package as likely incomplete.
Pin versions in lockfiles either way. A version you never resolve is a version no record has to cover.
check-package is free on our MCP server and in our GitHub Checks Action, and the updates page lists both changes with before-and-after examples. Credit to safeguard.sh for the unlisted-version counts and the leakdeep example, and to Socket and SafeDep for the tensorlake analysis.
We checked each version and verdict in this post against the live registries and our live check before publishing. At least 5% of what remains is still wrong, and we don't know which.
If this was useful, or if it wasn't, rate it at the bottom of the page. It is the only direct signal we get.
Every indicator in this post is in the feed. Free.
1.58M+ IOCs, STIX 2.1 / TAXII, 88% novel vs ThreatFox, exploited-CVE leads ahead of CISA. No credit card — a free API key in 30 seconds, and you can audit every claim above against the live endpoints.
Was this useful? Thirty seconds, no cookies, no tracking, no third parties, your address hashed and never stored. If the box below does not load, the same question lives at https://analytics.dugganusa.com/nps.html?post=a-malware-record-can-be-wrong-in-both-directions-we-found-both-in-our-own-package-check-on-the-same



Comments