# Service inventory and CVE review This Python project turns Nmap XML into a remediation queue. A finding retains its service banner and advisory link so a reviewer can check the package before opening a patch ticket. The supplied XML is hand-authored sample data. Its three hosts use documentation addresses in `192.0.2.0/24`. No hosts were scanned to produce it. ## Run the sample Python 3.10 or later is sufficient. There are no third-party Python dependencies. ```sh python3 scan_report.py report fixtures/nmap.xml --fixture --out reports python3 -m unittest discover -s tests -v ``` Open `reports/report.html`. `reports/demo.json` contains the same inventory and findings for the portfolio interface. The sample produces three open services and two potential matches. The OpenSSH 9.8p1 entry has no match in this two-advisory catalog. ## Bring an authorized inventory If Nmap is installed, this command inventories selected services on your own machine: ```sh nmap -sV -p 22,80,443 -oX local-inventory.xml 127.0.0.1 python3 scan_report.py report local-inventory.xml --out local-report ``` For another environment, obtain permission and supply an existing Nmap XML export. This project reads XML. It does not run a scanner, execute exploit checks, or change remote hosts. ## Matching decisions `fixtures/advisories.json` is a curated catalog reviewed on October 13, 2026. The Apache rule is an exact upstream version match. The Portable OpenSSH rule compares numeric versions and explicitly excludes OpenBSD when that platform appears in the service evidence. A product CPE must match before version checks run. A missing version or an unrecognized package suffix produces `manual-review`, not a positive finding. CPEs with escaped components are outside this parser's supported subset. Nmap's table-derived service labels cannot establish a version match. Potential matches remain unconfirmed. Distribution packages often retain an upstream version while carrying a backported fix. The OpenSSH rule covers the 8.5p1 to 9.7p1 regression interval, not older historical vulnerabilities. No match means no match in this catalog, not that a machine is secure. The HTML report escapes inventory text. The XML parser accepts Nmap's bare doctype but rejects external DTDs and entity declarations. The CLI accepts at most 5 MB of UTF-8 XML. ## Automatically cross-reference the inventory with NVD Add `--nvd` to include public-database candidates in both the HTML report and JSON. An optional `NVD_API_KEY` is read from the environment. It is never written to the report. ```sh python3 scan_report.py report local-inventory.xml --nvd --out local-report ``` The NVD path converts supported Nmap application CPEs to CPE 2.3, preserving separate version and update fields. An OpenSSH `9.2:p1` URI becomes a CPE with version `9.2` and update `p1`. Missing versions or complex escaped CPEs are recorded as skipped lookups with a reason. Product names are never guessed into CPEs. Each distinct CPE is queried once. Responses are reused for 24 hours from `/nvd-cache`, with retrieval times included in the report. Use `--nvd-refresh` to bypass the cache or `--nvd-cache DIRECTORY` to share it between reports. The client calls the NVD CVE API 2.0 with `cpeName` and `isVulnerable`, paginates with `startIndex`, and spaces successive network requests by 6.5 seconds. HTTP errors stop the command. It writes each complete response cache only after all pages succeed. NVD candidates appear in a separate section with their CVE descriptions and links. The JSON retains NVD applicability configurations. These candidates remain unverified: operating-system prerequisites and downstream patches need review before choosing a supported fixed package. The original two curated rules keep their own results. The default sample remains offline. The integrated inventory-to-NVD-to-report path is covered by a mocked integration test, not a live API test. ## Query one CPE directly For a lookup outside an inventory report, supply an exact CPE 2.3 application identifier from the NVD dictionary: ```sh python3 scan_report.py fetch-nvd \ --cpe 'cpe:2.3:a:apache:http_server:2.4.49:*:*:*:*:*:*:*' \ --out reports/nvd-candidates.json ``` Review each candidate's configurations and vendor advisory before extending the curated catalog. ## Primary references - [Apache's CVE-2021-41773 advisory](https://httpd.apache.org/security/vulnerabilities_24.html#CVE-2021-41773) and [the incomplete-fix follow-up](https://httpd.apache.org/security/vulnerabilities_24.html#CVE-2021-42013) - [OpenSSH 9.8 release notes](https://www.openssh.org/txt/release-9.8) - [NVD CVE-2021-41773](https://nvd.nist.gov/vuln/detail/CVE-2021-41773) and [CVE-2024-6387](https://nvd.nist.gov/vuln/detail/CVE-2024-6387) - [NVD CVE API 2.0](https://nvd.nist.gov/developers/vulnerabilities) - [Nmap XML output](https://nmap.org/book/output-formats-xml-output.html) The catalog is intentionally small enough to inspect. It is not a current, comprehensive vulnerability feed.