Specification: CVE Detection in Validation and Client Reporting - #6292
Specification: CVE Detection in Validation and Client Reporting#6292denelon wants to merge 2 commits into
Conversation
…#2204) Specification for integrating vulnerability detection into the WinGet ecosystem — validation pipeline flagging, client reporting via 'winget security' command, and Group Policy controls for enterprise. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Trenly
left a comment
There was a problem hiding this comment.
My main concern is mostly about using the severity instead of the actual CVSS. I'd prefer to use the actual CVSS if possible, since it provides a greater level of fidelity. If the severity is important for user facing features, that mapping could be internal to the CLI
| 2. **Known CVE flagging** — If the submitted version has known CVEs: | ||
| - Add a `Security-CVE` label to the PR | ||
| - Post a bot comment listing CVEs with severity ratings (CVSS score) | ||
| - Do NOT auto-reject — moderators approve with acknowledgment |
There was a problem hiding this comment.
Distinguish between community moderator vs MSFT moderated with waiver
| - Do NOT auto-reject — moderators approve with acknowledgment | ||
| 3. **Severity-based workflow:** | ||
| - Critical/High (CVSS ≥ 7.0): Require explicit moderator approval | ||
| - Medium (CVSS 4.0–6.9): Warning, auto-approve still possible |
There was a problem hiding this comment.
There currently is no auto-approve, everything is either community moderated or MSFT moderated. Auto-approve would only happen for verified publisher
|
|
||
| | Command | CVE Behavior | | ||
| |---------|-------------| | ||
| | `winget list` | `--include-security` flag adds CVE column | |
| |---------|-------------| | ||
| | `winget list` | `--include-security` flag adds CVE column | | ||
| | `winget upgrade` | Security-relevant upgrades highlighted with ⚠️ | | ||
| | `winget install --version` | Non-blocking warning when version has known CVEs | |
There was a problem hiding this comment.
Blocking if GPO disallows installs with CVEs?
| | `winget list` | `--include-security` flag adds CVE column | | ||
| | `winget upgrade` | Security-relevant upgrades highlighted with ⚠️ | | ||
| | `winget install --version` | Non-blocking warning when version has known CVEs | | ||
| | `winget show` | `--security` flag shows CVE details | |
There was a problem hiding this comment.
Why add a new flag? winget show is already a single package level, no need to require additional user action just to see CVE data
| Security: | ||
| Advisories: | ||
| - Id: CVE-2024-32002 | ||
| Severity: Critical |
There was a problem hiding this comment.
Should users be specifying severity, or should it be determined automatically based on CVSS? What is the risk if a user marks a CVSS 8.0 as Medium severity?
| | Argument | Commands | Description | | ||
| |----------|----------|-------------| | ||
| | `--ignore-security-warnings` | install, upgrade | Proceed despite CVE warnings | | ||
| | `--include-security` | list, show | Show CVE information | |
There was a problem hiding this comment.
See comments above regarding this parameter
| |----------|----------|-------------| | ||
| | `--ignore-security-warnings` | install, upgrade | Proceed despite CVE warnings | | ||
| | `--include-security` | list, show | Show CVE information | | ||
| | `--severity` | security scan | Minimum severity to report | |
There was a problem hiding this comment.
Is this strictly an enum, or would users be able to do --severity 7.0 ?
Some orgs specify that anything with a CVSS 8.0 or above is not allowed, others allow 7.0 CVSS; More granular control will be needed than just Critical/High/Med/Low in my opinion
|
|
||
| ### Schema Version | ||
|
|
||
| This feature requires manifest schema version 1.29.0 for the optional `Security` field. The CVE detection itself works without manifest changes (uses external database lookups). |
There was a problem hiding this comment.
Remove specific version information
| Node.js OpenJS.NodeJS 18.12.0 18.20.3 winget ⚠️ High | ||
| VS Code Microsoft.VS.. 1.90.0 1.91.0 winget | ||
|
|
||
| ⚠️ 2 packages have security updates. Run 'winget upgrade --all' to apply. |
There was a problem hiding this comment.
What if users want to only upgrade packages with security updates? winget upgrade --all --security ?
| | `winget show` | `--security` flag shows CVE details | | ||
| | `winget configure test` | Reports CVE compliance status per resource | | ||
|
|
||
| #### Data Source Architecture |
There was a problem hiding this comment.
We've found this to be pretty difficult. Manually mapping package IDs to CPEs helped, but a lot of raw NVD entries don't have accurate version ranges. Third-party dbs might have better data
afaik, GHSA's global db doesn't have a PURL format for Windows apps and doesn't ingest CPE data, eg GHSA-589r-wg5p-vwjq. CVE-2024-32002 in Git.Git is another good example, it's GHSA-8h77-4q3w-gfgv in https://github.com/git/git but is not available in the global db
| | `CVEBlockInstallSeverity` | Enum | None | Block installs at or above severity (None/Low/Medium/High/Critical) | | ||
| | `CVEBlockUpgradeSeverity` | Enum | None | Block upgrades to versions with CVEs at/above severity | | ||
| | `CVEScanFrequency` | Int | 1440 | Cache refresh interval in minutes | | ||
| | `CVEReportingEndpoint` | String | Empty | URL to POST scan results for fleet visibility | |
There was a problem hiding this comment.
This could be really powerful, I'd love to write an example server or something
Architecture change: CVE metadata comes from Microsoft's private validation infrastructure and is added to merged manifests (like icons). Community contributions to CVE mappings are disallowed by policy. Key changes: - Critical CVEs (CVSS >= 9.0) block submission; lower severities informational - Pipeline hash reconciliation for out-of-band merged manifest updates - Use numeric CVSS thresholds for GPO (not enum), enabling granular control - Replace --include-security with --details (consistent with PUA spec) - Add winget upgrade --all --security for security-only upgrades - Add CVSS score field to advisory schema (severity derived, not user-specified) - Remove version-specific info from headings - Acknowledge PURL/CPE mapping challenges (NVD gaps, GHSA limitations) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.Unrecognized words (8)cpe These words are not needed and should be removedAAD ABCD abi ACL'd AMap Amd appdata ARMNT asan Baz bitmask bluetooth boundparms brk Buf certs cgi CMSG codepage commandline constexpr Cov cswinrt CTL Dbg Dcom decompressor dedupe DEFT devhome Dns dsc ERANGE errcode errmsg errstr filemode Finalizers FULLWIDTH fuzzer GES github Hackathon HINSTANCE hlocal hmac Hyperlink ICONDIR icu idx img inet Intelli iwr JDK LCID lhs LONGLONG LPBYTE LPCWSTR LPDWORD LPSTR LPVOID LPWSTR MAJORVERSION MAXLENGTH maxvalue MDs MINORVERSION mta nlohmann NONAME NOUPDATE NTFS ofile oid oop OPTOUT outfile OUTOFMEMORY PARAMETERMAP pdb PDWORD pid PKCS pkix placeholders positionals posix pscustomobject pseudocode PSHOST publickey qword redirector regexes remoting reparse REQS rhs rowid RTTI runspace runtimes SARL savepoint Scm sid sqlite subdir subkey trimstart ttl typedef uninitialize uninstallation UNMARSHALING userprofile versioned Webserver website wildcards winreg WMI workaround Wpp wslTo accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands... in a clone of the git@github.com:denelon/winget-cli.git repository curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.26/apply.pl' |
perl - 'https://github.com/microsoft/winget-cli/actions/runs/27972889258/attempts/1' &&
git commit -m 'Update check-spelling metadata'Pattern suggestions ✂️ (2)You could add these patterns to Alternatively, if a pattern suggestion doesn't make sense for this project, add a Warnings and Notices
|
| Count | |
|---|---|
| ℹ️ candidate-pattern | 2 |
| 2 |
See
If the flagged items are 🤯 false positives
If items relate to a ...
-
binary file (or some other file you wouldn't want to check at all).
Please add a file path to the
excludes.txtfile matching the containing file.File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.
^refers to the file's path from the root of the repository, so^README\.md$would exclude README.md (on whichever branch you're using). -
well-formed pattern.
If you can write a pattern that would match it,
try adding it to thepatterns.txtfile.Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.
Note that patterns can't match multiline strings.
| - Id: CVE-2023-22490 | ||
| Cvss: 5.5 | ||
| FixedIn: "2.39.2" | ||
| Description: "Path traversal in clone" |
There was a problem hiding this comment.
Should there be individual links to each advisory?
| winget security scan [--source <source>] [--severity <minimum>] | ||
| winget security show <package-id> |
There was a problem hiding this comment.
I don't see much value in having a separate command for this.
There was a problem hiding this comment.
I agree; I'd rather just see a single command like winget audit [--source <source>] [--severity <minimum>] and use winget show <query> --details for the CVE information
| | Command | CVE Behavior | | ||
| |---------|-------------| | ||
| | `winget list` | CVE column shown via `--details` | | ||
| | `winget upgrade` | Security-relevant upgrades highlighted with ⚠️; `--security` flag to upgrade only packages with security fixes | |
There was a problem hiding this comment.
How do we know when an upgrade has security fixes? Going from a version with a CVE to one without it?
| - Not present in the public `winget-pkgs` manifest files | ||
|
|
||
| > [!NOTE] | ||
| > Mapping WinGet package IDs to PURLs/CPEs is a known challenge. Many NVD entries have inaccurate version ranges, and GHSA's global database doesn't cover Windows-specific package formats well. Microsoft's internal infrastructure uses multiple data sources and manual curation to improve accuracy over time. |
There was a problem hiding this comment.
Is this validation infrastructure going to be winget's, or will we use something from another team?
| | `EnableCVEDetection` | Bool | Enabled | Master toggle for all CVE features | | ||
| | `CVEBlockInstallThreshold` | Float | 0 (disabled) | Block installs when any CVE has CVSS ≥ this value (e.g., 7.0) | | ||
| | `CVEBlockUpgradeThreshold` | Float | 0 (disabled) | Block upgrades to versions with CVSS ≥ this value | | ||
| | `CVEScanFrequency` | Int | 1440 | Cache refresh interval in minutes | |
There was a problem hiding this comment.
Would this mean "happens on the next run of winget after at least X minutes", or "there is a scheduled task running every X minutes"?
|
|
||
| ### Part 2: Client CVE Reporting | ||
|
|
||
| #### New command: `winget security` |
There was a problem hiding this comment.
Many other package mangers (like those listed above) use audit - I'd recommend using that or including it as an alias to reduce friction
| winget security scan [--source <source>] [--severity <minimum>] | ||
| winget security show <package-id> |
There was a problem hiding this comment.
I agree; I'd rather just see a single command like winget audit [--source <source>] [--severity <minimum>] and use winget show <query> --details for the CVE information
| |---------|-------------|------------|-------------| | ||
| | `enableCVEDetection` | N/A | `EnableCVEDetection` | GPO wins | | ||
| | `minimumReportCvss` | `--severity` | N/A | Arg overrides setting | | ||
| | `cacheRefreshMinutes` | N/A | `CVEScanFrequency` | GPO wins | |
There was a problem hiding this comment.
Does there need to be consideration where the user settings are MORE secure than the group policy? I assume group policy would always override, but maybe there's a world where the user wants their cache to refresh more often than GPO.
Suggest that this be treated as a maximum interval and users can configure shorter intervals in their user settings. If user has a longer interval in their setting, clamp to GPO value
|
|
||
| ```powershell | ||
| # Scan installed packages | ||
| Get-WinGetSecurityScan [-Source <String>] [-MinimumCvss <Double>] |
There was a problem hiding this comment.
I'm going to probably start some controversy here, but this seems more like a diagnostic scan and may be better served by a Diagnostic Verb such as Measure-WinGetSecurity or Test-WinGetSecurity. Alternatively, I could see a lifecycle verb like Invoke-WinGetAudit
Not that Get-WinGetSecurityScan or Get-WinGetAudit isn't correct or isn't a good choice - just throwing alternative options on the table since this is still in the spec stage
| | `enableCVEDetection` | N/A | `EnableCVEDetection` | GPO wins | | ||
| | `minimumReportCvss` | `--severity` | N/A | Arg overrides setting | | ||
| | `cacheRefreshMinutes` | N/A | `CVEScanFrequency` | GPO wins | | ||
|
|
There was a problem hiding this comment.
Are these only user settings, or would there also be admin settings as well? Does this need a complete chain of precedence?
GPO <--(overrides)-- Admin Setting <--(overrides)-- User Setting
|
|
||
| Your organization's policy blocks installation of packages with Critical vulnerabilities. | ||
| Use 'winget install OldPackage' without --version to install the latest safe version, | ||
| or use --ignore-security-warnings to override (if permitted by policy). |
There was a problem hiding this comment.
I'd think we can detect if policy allows the argument and leave this out of the message if not permitted
| ### Accessibility | ||
|
|
||
| - Security warnings use text labels (not just emoji/color) — screen readers announce severity levels | ||
| - `winget security scan --output json` provides structured data for programmatic consumption |
There was a problem hiding this comment.
I don't think we should mix --output json with this specification. If JSON is desired, use the powershell cmdlets for structured data. Leave the JSON output feature with the separately filed issue
| | `CVEBlockInstallThreshold` | Float | 0 (disabled) | Block installs when any CVE has CVSS ≥ this value (e.g., 7.0) | | ||
| | `CVEBlockUpgradeThreshold` | Float | 0 (disabled) | Block upgrades to versions with CVSS ≥ this value | | ||
| | `CVEScanFrequency` | Int | 1440 | Cache refresh interval in minutes | | ||
| | `CVEReportingEndpoint` | String | Empty | URL to POST scan results for fleet visibility | |
There was a problem hiding this comment.
If this is somthing the CLI is posting should the spec include an example of the body that would be reported up to the endpoint? How does this align with the future considerations?
Is reporting up to an endpoint actually part of the requested feature, or should that be a separate feature and a separate spec? I feel like it should be separate, but understand the need / desire for the endpoint
| - Incremental sync — only fetch new advisories since last update timestamp | ||
| - `winget security scan` scans local cache only — O(n) where n = installed packages | ||
|
|
||
| ## Potential Issues |
There was a problem hiding this comment.
There is another potential issue around missing CVSS scores. A CNA can reserve the CVE before the CVSS is calculated, the score could be in dispute, etc. Options could include gracefully handling them, adding a user option if they want to be notified of CVEs with no CVSS, or simply omitting them.
Not strictly necessary for initial implementation, but a consieration should be given
| 4. **Data freshness** — NVD can lag days behind disclosure. GHSA is faster for GitHub-hosted projects. Microsoft's periodic rescan frequency determines how quickly CVE data propagates to clients. | ||
| 5. **Privacy** — Bulk-download model avoids per-package queries but requires local storage (~5-10 MB for advisory database). | ||
| 6. **Pipeline hash reconciliation** — Out-of-band merged manifest updates (from periodic rescan) require the publishing pipeline to recompute hashes and republish source indexes without a corresponding PR submission. This is new pipeline functionality that must be designed carefully to avoid race conditions with ongoing submissions. | ||
| 7. **Reporting endpoint trust** — Enterprise reporting endpoints must be configured by GPO to prevent data exfiltration of installed software inventory. |
There was a problem hiding this comment.
This conflicts with the user setting described above. Recommend resolving the conflict by removing the user setting
📖 Description
Specification for CVE (Common Vulnerabilities and Exposures) detection and reporting in the WinGet ecosystem. Integrates at two levels: the
winget-pkgsvalidation pipeline (flagging/blocking packages with known CVEs during submission) and the WinGet client (informing users when installed packages have known vulnerabilities).Key architectural decisions:
Security-CVElabelwinget upgrade --all --securityupgrades only packages with available security fixesChanges addressing review feedback (June 22):
--include-securitywith--details(consistent with PUA spec)winget upgrade --all --securityfor security-only upgradesAuthored with GitHub Copilot assistance.
🔗 References
Related Issues:
🔍 Validation
Spec document — no code changes to validate.
✅ Checklist
📋 Issue Type
Microsoft Reviewers: Open in CodeFlow