Added vulnerability scanning support for Windows Server 2025 hosts (#41232)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40036

Ran nvd locally to generate the new
`fleet_msrc_Windows_Server_2025-2026_03_08.json` file.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added vulnerability scanning support for Windows Server 2025 hosts,
enabling detection of security vulnerabilities on the latest Windows
Server platform.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Victor Lyuboslavsky
2026-03-10 14:03:59 -05:00
committed by GitHub
parent 5c893a7b8e
commit bae3f022e2
5 changed files with 64 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
* Added vulnerability scanning support for Windows Server 2025 hosts.
@@ -76,6 +76,9 @@ func NewProductFromFullName(fullName string) Product {
// We need this to match the product with a host's OS, so we'll add them here.
versionString := ""
switch {
case strings.Contains(fullName, "Windows Server 2025"):
versionString = "24H2"
case strings.Contains(fullName, "Windows Server 2022"):
versionString = "21H2"
@@ -196,6 +199,8 @@ func (p Product) Name() string {
return "Windows Server 2019"
case strings.Contains(val, "Windows Server 2022"):
return "Windows Server 2022"
case strings.Contains(val, "Windows Server 2025"):
return "Windows Server 2025"
case strings.Contains(val, "Windows Server,"):
return "Windows Server"
@@ -150,6 +150,18 @@ func TestFullProductName(t *testing.T) {
prodName: "Windows Server 2022",
finalName: "Windows Server 2022 (Server Core installation) Version 21H2",
},
{
fullName: "Windows Server 2025",
arch: "all",
prodName: "Windows Server 2025",
finalName: "Windows Server 2025 Version 24H2",
},
{
fullName: "Windows Server 2025 (Server Core installation)",
arch: "all",
prodName: "Windows Server 2025",
finalName: "Windows Server 2025 (Server Core installation) Version 24H2",
},
{
fullName: "Windows 10 Version 20H2 for x64-based Systems",
arch: "64-bit",
@@ -554,6 +566,7 @@ var msrcWinProducts = Products{
"11923": "Windows Server 2022",
"11924": "Windows Server 2022 (Server Core installation)",
"12244": "Windows Server 2022, 23H2 Edition (Server Core installation)",
"12436": "Windows Server 2025 Version 24H2",
}
func TestMatchesOperatingSystem(t *testing.T) {
@@ -633,6 +646,16 @@ func TestMatchesOperatingSystem(t *testing.T) {
want: "12244",
err: nil,
},
{
name: "Windows Server 2025 with display version",
os: fleet.OperatingSystem{
Name: "Microsoft Windows Server 2025 Datacenter 24H2",
Arch: "64-bit",
DisplayVersion: "24H2",
},
want: "12436",
err: nil,
},
{
name: "unknown OS",
os: fleet.OperatingSystem{
@@ -1336,6 +1336,41 @@ func TestParser(t *testing.T) {
}
})
t.Run("should include Windows Server 2025 from 2026-Feb feed", func(t *testing.T) {
febSrcPath := filepath.Join("..", "testdata", "msrc-2026-feb.xml.bz2")
febDstPath := filepath.Join(t.TempDir(), "msrc-2026-feb.xml")
extractXMLFixtureFile(t, febSrcPath, febDstPath)
febF, err := os.Open(febDstPath)
require.NoError(t, err)
febXML, err := parseXML(febF)
febF.Close()
require.NoError(t, err)
febBulletins, err := mapToSecurityBulletins(febXML)
require.NoError(t, err)
// Windows Server 2025 bulletin should exist
winServer2025 := febBulletins["Windows Server 2025"]
require.NotNil(t, winServer2025, "expected a bulletin for Windows Server 2025")
require.Equal(t, "Windows Server 2025", winServer2025.ProductName)
// Should contain both base and Server Core products
require.Contains(t, winServer2025.Products, "12436", "expected product ID 12436 (Windows Server 2025)")
require.Contains(t, winServer2025.Products, "12437", "expected product ID 12437 (Windows Server 2025 Server Core)")
// Product names should be correctly normalized with version string
require.Equal(t, parsed.Product("Windows Server 2025 Version 24H2"), winServer2025.Products["12436"])
require.Equal(t,
parsed.Product("Windows Server 2025 (Server Core installation) Version 24H2"),
winServer2025.Products["12437"],
)
// Should have vulnerabilities with vendor fixes
require.NotEmpty(t, winServer2025.Vulnerabities, "expected vulnerabilities for Windows Server 2025")
require.NotEmpty(t, winServer2025.VendorFixes, "expected vendor fixes for Windows Server 2025")
})
t.Run("the remediations are parsed correctly", func(t *testing.T) {
// Check the remediations of a random CVE (CVE-2022-29126)
expectedRemediations := []msrcxml.VulnerabilityRemediation{
Binary file not shown.