Empty string accepted as a valid version in Maven/NuGet/RubyGems, and sorts as minimum
评估
调研方向
该 issue 指向 univers.versions 以及 MavenVersion、NugetVersion、RubygemsVersion、SemverVersion 和 PypiVersion 类,因此请检查这些实现对空字符串的处理和比较行为。比较 SemVer/PyPI 当前如何拒绝 "",然后据此统一调整这三个不一致的 scheme,并添加涵盖 Version("") 构造以及跨 scheme 排序的测试。先使用提供的 Python snippets 复现,然后运行相关的版本解析/比较测试子集;当空输入具有一种一致的结果,并且跨 scheme 测试在没有静默的最小值排序行为的情况下通过时,即完成。
由索引模型根据 Issue 内容生成。
描述
Summary
MavenVersion, NugetVersion and RubygemsVersion accept the empty string "" as a valid version, while SemverVersion, PypiVersion and others correctly raise InvalidVersion. Worse, the accepted empty version then sorts below every real version, so downstream range logic silently produces a confident but wrong answer rather than failing.
Tested with univers 32.0.1 on CPython 3.13.
Reproducer
from univers.versions import (
MavenVersion, NugetVersion, RubygemsVersion, SemverVersion, PypiVersion,
)
# Accepted (inconsistent):
MavenVersion("") # -> MavenVersion(string='')
NugetVersion("") # -> NugetVersion(string='')
RubygemsVersion("") # -> RubygemsVersion(string='')
# Correctly rejected:
SemverVersion("") # -> InvalidVersion
PypiVersion("") # -> InvalidVersion
Three different behaviours across schemes, none of them an error for the first group:
MavenVersion("") < MavenVersion("0.0.1") # True -- sorts as minimum
RubygemsVersion("") < RubygemsVersion("0.0.1") # True -- sorts as minimum
NugetVersion("") < NugetVersion("0.0.1") # TypeError:
# '<' not supported between instances of 'NoneType' and 'Version'
So NugetVersion accepts the value at construction and then raises on comparison, which is a third distinct outcome.
Why the silent ordering is the harmful part
Consider an OSV range built from a malformed advisory:
{"type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": ""}]}
Because MavenVersion("") is accepted and sorts as the minimum, the interval [0, "") evaluates to the empty set. Code comparing this against the advisory's previous range concludes, with no error and no warning, that the affected set was reduced to nothing — i.e. that the range was retracted.
We hit this in a measurement study over the git history of the GitHub Advisory Database. GHSA emitted schema-invalid {"fixed": ""} into 2,107 advisory revisions during a single week in March 2023. Because three of the ecosystems we needed silently accepted it, our comparator produced roughly 1,000 spurious "affected range narrowed" events in Maven alone — a confidently wrong classification, not a crash we could catch. The npm/PyPI/Go paths were unaffected precisely because they raise InvalidVersion.
The general hazard: a caller cannot rely on "the version parsed successfully" as a validity check, and the failure is scheme-dependent, so it shows up only in some ecosystems and looks like real data.
Suggested resolution
Whatever the decision on leniency, the three schemes should agree with each other and with the rest of the library. Options, in our order of preference:
- Raise
InvalidVersionfor""inMavenVersion,NugetVersionandRubygemsVersion, matchingSemverVersion/PypiVersion. An empty string is not a version in any of these ecosystems' specs. - If empty is to be accepted deliberately (see #10), make it consistent across all schemes and define its ordering explicitly rather than letting it fall out of the attribute tuple — the current
NugetVersionTypeErroron comparison shows the ordering is not well-defined today.
A test asserting identical "" behaviour across every Version subclass would prevent the schemes drifting apart again.
Related
- #10
parse_version() should accept None and empty strings— related but pointing the other way; this report is about the inconsistency between schemes and the silently wrong ordering, independent of which behaviour is chosen. The comment there that "None or empty would be the same... I am not sure this would make any sense" suggests option 1 is the intended direction. - #203
Do not allow creation of VersionRange with empty constraint— same family of problem one level up, at the range rather than the version.
Happy to send a PR for option 1 plus the cross-scheme test if that is the direction you'd like.
- 主要语言
- Python
- 星标
- 50
- 派生
- 31
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
aboutcode-org/univers 的其他 Issue
-
Do not allow creation of `VersionRange` with empty constraint可能已有人在做 @MGpromax 于 65 天前认领。 未关闭bug High-Priority
难度 2/5 1-3 小时 新手友好度 65/100
aboutcode-org/univers#203 ·
-
maven.py: "release" qualifier not treated as release alias可能已有人在做 @selsky 于 71 天前认领。 未关闭
难度 1/5 1 小时以内 新手友好度 82/100
aboutcode-org/univers#188 ·
-
VersionRange.invert() returns a complement that excludes versions outside an enumerated range可能已有人在做 @akashrajeev 于 13 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 72/100
aboutcode-org/univers#214 · 1 条评论 ·
-
难度 2/5 1-3 小时 新手友好度 15/100
aboutcode-org/univers#206 · 3 条评论 · 2 个 reaction ·
-
难度 4/5 3-5 天 新手友好度 18/100
aboutcode-org/univers#205 ·
查看 aboutcode-org/univers 的全部 Issue
相似的 Issue
-
priority middle
难度 1/5 1 小时以内 新手友好度 62/100
KATO-Hiro/AtCoderClans#12940 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 76/100
huggingface/huggingface_hub#5283 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 78/100
维护者通常 1 天内回复
-
enhancement
难度 1/5 1 小时以内 新手友好度 86/100
维护者通常 1 天内回复
-
bug example
难度 2/5 1-3 小时 新手友好度 86/100
维护者通常 1 天内回复