Files
vulncheck/tests/test_defender_software_inventory.py
T
vulncheck 37ac04e34b feat(defender): read installed software from MDE instead of waiting on Intune
Intune's detectedApps refreshes every 7 days per device, so the app-CVE scan
ran against week-old version strings — a browser patched this morning still
read last week's version, and the finding stayed open until the next
Discovered-apps cycle.

Intune's replacement, Enhanced App Inventory, collects multiple times per day
but has no API: `deviceInventories` is absent from the Graph beta $metadata
(no entity, no navigation property on managedDevice), its doc pages 404, and
the official export-report list has no app-inventory reportName —
AppInv{RawData,Aggregate,ByDevice} are all Discovered apps. Microsoft says
Graph support is planned for later in 2026. Until then the data is
portal-only.

Defender for Endpoint already exposes the same thing app-only and documented:
/machines/SoftwareInventoryByMachine, one tenant-wide paginated call, keyed by
the machine ids the Defender sync already matches to assets. It follows device
telemetry rather than a weekly cycle. Feed it into _run_app_inventory — the
same EOL / M365 / app→CVE pipeline detectedApps feeds — so the fresher list
wins wherever Defender covers the device, and detectedApps stays for the rest.

The only translation is the name: Defender reports CPE-style tokens (vendor
`microsoft`, product `visual_studio_code`) while the product registry matches
installer names. _pkg_name joins and un-escapes them, dropping the vendor when
the product already carries it.

Best-effort throughout: a tenant without Software.Read.All or without Defender
Vulnerability Management gets an empty inventory and the previous behaviour.

Also extends tools/probe_intune_app_inventory.py to walk the whole matrix —
URL shapes, the documented config resource, and every plausible export report
name — so the Intune-side verdict can be re-checked against a live tenant when
Microsoft ships the Graph route.
2026-08-18 10:26:29 +02:00

23 lines
954 B
Python

"""Defender's normalised (vendor, product) must land on a name the product
registry actually matches — that join is the only translation between MDE's
software inventory and the app-CVE scan."""
from app.services.defender_service import _pkg_name
from app.services.app_cve_scanner_service import resolve_product
def test_pkg_name_joins_vendor_and_product():
assert _pkg_name("microsoft", "edge") == "microsoft edge"
assert _pkg_name("microsoft", "visual_studio_code") == "microsoft visual studio code"
def test_pkg_name_does_not_repeat_the_vendor():
assert _pkg_name("microsoft", "microsoft_office") == "microsoft office"
assert _pkg_name("", "7-zip") == "7-zip"
assert _pkg_name("igor pavlov", "") == ""
def test_joined_name_resolves_to_a_product():
# the whole point: what MDE reports must be scannable
assert resolve_product(_pkg_name("google", "chrome"))
assert resolve_product(_pkg_name("microsoft", "edge"))