Skip to content

fix(binary): normalize comma-separated PE version resources - #5112

Open
Eljees wants to merge 3 commits into
anchore:mainfrom
Eljees:agent/fix-pe-comma-version
Open

Eljees wants to merge 3 commits into
anchore:mainfrom
Eljees:agent/fix-pe-comma-version

Conversation

@Eljees

@Eljees Eljees commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Normalizes the comma-separated version form found in Windows PE VERSIONINFO resources, so 3, 0, 21, 0 becomes 3.0.21.0.

Why

Windows resource string tables frequently mirror the .rc declaration (FILEVERSION 3,0,21,0) rather than the dotted form. Syft used that value verbatim as the package version, which is visible in #5075 — VLC is reported as:

cpe:2.3:a:VLC_media_player:VLC_media_player:3\,0\,21\,0:*:*:*:*:*:*:*

A version containing escaped commas matches nothing in vulnerability data, and the same value flows into the PURL and the package version shown to users.

This only addresses the version portion of that issue; the vendor/product naming discussion there is separate and left alone.

Details

  • extractVersionFromResourcesValue now normalizes a value that consists entirely of comma-separated numbers (with optional surrounding spaces) to the dotted form.
  • Anything else is returned unchanged, so values like 1.2.3 (build 456) keep their existing handling and a value such as 1.0, beta is not rewritten.

Tests

Added Test_findVersionFromVR covering dotted input, both comma-separated forms (3, 0, 21, 0 and 3,0,21,0), a version with a trailing comment, and a non-numeric comma value. go test ./syft/pkg/cataloger/binary/ passes.

Windows VERSIONINFO string tables often carry the .rc-style
comma-separated form of a version (mirroring FILEVERSION 3,0,21,0), so
binaries such as VLC report a version of "3, 0, 21, 0". That value was
used verbatim as the package version, which produced identifiers like
cpe:2.3:a:...:3\,0\,21\,0 that match nothing in vulnerability data.

Normalize values that consist entirely of comma-separated numbers into
the canonical dotted form; anything else (including versions with a
trailing comment) is left untouched.

Signed-off-by: Eljees <3.14hell@gmail.com>
@Eljees

Eljees commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Ping on this one and #5114 - both open since late July, no review yet. They touch different areas (binary PE version resources and the CycloneDX decoder) and are independent.

The first version of this change only rewrote values that consisted
entirely of comma-separated numbers, which missed the spelling that is
most common on Microsoft-built binaries: "1, 0, 0, 1
(WinBuild.160101.0800)". Those kept their commas and still produced a
version that matches nothing.

Rewrite a leading run of comma-separated numbers instead and leave
whatever follows it untouched, so that form becomes
"1.0.0.1 (WinBuild.160101.0800)" and is then treated exactly like the
dotted "10.0.19041.1 (WinBuild.160101.0800)" that reaches this function
today. A value that does not begin with such a run is still returned
unchanged.

Signed-off-by: Eljees <3.14hell@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CsUTRwsaFCwavDJTPwEpW
@Eljees

Eljees commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit (99d5911) that closes a gap I found while re-checking this against today's main.

The original change only rewrote values that were entirely comma-separated numbers. That misses the spelling most common on Microsoft-built binaries, where a build tag follows the version. Measured on main at 3325493 and on this branch:

ProductVersion / FileVersion main this PR, before this PR, now
3, 0, 21, 0 3, 0, 21, 0 3.0.21.0 3.0.21.0
6, 1, 7601, 17514 6, 1, 7601, 17514 6.1.7601.17514 6.1.7601.17514
1, 0, 0, 1 (WinBuild.160101.0800) unchanged unchanged 1.0.0.1 (WinBuild.160101.0800)
2, 5, 0, 0 built by: WinDDK 2, 5, 0, 0 2, 5, 0, 0 2.5.0.0
10.0.19041.1 10.0.19041.1 10.0.19041.1 10.0.19041.1
1.0, beta 1.0, 1.0, 1.0,

The fix is to rewrite a leading run of comma-separated numbers and leave the rest of the string alone, rather than requiring the whole value to match. The deliberate boundary: 1, 0, 0, 1 (WinBuild.160101.0800) now becomes 1.0.0.1 (WinBuild.160101.0800) — it keeps the build tag, because that is exactly what the dotted 10.0.19041.1 (WinBuild.160101.0800) already does when it reaches this function. Whether that trailing tag should be dropped is a separate question about existing behaviour, and I have left it alone rather than widen this PR; the point here is only that the comma spelling stops being treated worse than the dotted one.

Two test cases were added for the new rows; the existing ones are unchanged and still pass.

Verification, since the branch was cut in August: it merges into current main cleanly, and go test ./syft/pkg/cataloger/binary/... on the merge result fails exactly the same tests as a pristine main checkout does in this environment (Test_Cataloger_PositiveCases, Test_PEPackageCataloger, Test_ELFPackageCataloger, Test_JavaBinaryImage, Test_Cataloger_DefaultClassifiers_PositiveCases_Image — all of them need docker to build fixtures, which is not available here). Nothing new is attributable to the change. CI here sits at action_required, so it needs the usual approval click for an outside contributor before it will run.

🤖 Generated with Claude Code

https://claude.ai/code/session_015CsUTRwsaFCwavDJTPwEpW

Bring in the upstream Busybox fixture digest pin and sigstore bundle
installer verification updates. Preserve the PE version normalization
source and regression tests unchanged.

Signed-off-by: Eljees <3.14hell@gmail.com>
Assisted-by: OpenAI Codex

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant