NuGet dependency scanning goes beyond dotnet audit. You need visibility into which vulnerabilities have active exploits (CISA KEV) and which are likely to be exploited soon (EPSS scores). Learn the difference in our guides on EPSS and exploit prediction and CISA KEV-tracked vulnerabilities.
The Silent Risk in Your .csproj File
Your team ships a new feature to your ASP.NET Core microservice. It's polished, tested, and your CI pipeline passes. But buried in your packages.config (or worse, not even checked since 2019) is an older version of Newtonsoft.Json with a known deserialization vulnerability—CVE-2022-24765.
You run dotnet list package --vulnerable and get output. A few advisories show up. Your team marks the task as "medium priority" and moves on. Three months later, you're reading a security disclosure: that Newtonsoft.Json vulnerability is now on the CISA Known Exploited Vulnerabilities (KEV) catalog. Attackers have working exploits. Now it's "critical."
This is the gap between having vulnerability advisories and knowing which ones matter right now. The .NET ecosystem has grown to 350+ million NuGet packages, but most teams still rely on basic tooling that can't distinguish between a bug report and an active attack vector. If you're new to the concept, our guide to how dependency vulnerability scanning works covers the fundamentals this NuGet-specific workflow builds on.
What We'll Cover
- The NuGet ecosystem: PackageReference vs packages.config
- What dotnet audit finds—and doesn't
- How GeekWala scans .NET projects
- Real-world vulnerability patterns in .NET libraries
- Building a scanning workflow for ASP.NET Core teams
- Best practices and common pitfalls
- FAQ
The NuGet Ecosystem: PackageReference vs packages.config
NuGet dependencies are declared through two formats depending on project age: the modern PackageReference syntax in .csproj, and the legacy packages.config XML file still common in pre-SDK .NET Framework projects. Which format you use changes how completely your scanner can see transitive dependencies and version pinning.
PackageReference (Modern Standard)
Since .NET Core 1.0 (2016), the PackageReference format in .csproj files has been the recommended way to declare dependencies:
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="StackExchange.Redis" Version="2.6.86" />
</ItemGroup>
Strengths:
- Transitive dependencies are resolved automatically
- Supports version ranges (
[12.0, 13.0)) - Works with
Directory.Packages.propsfor centralized version management - Integrates cleanly with MSBuild and NuGet restore
- First-class support in modern tooling
Vulnerability scanning implications:
- Direct and transitive dependencies are explicit in the lock graph
- Version pinning strategies matter:
13.0.1vs13.0.*vs[13.0, 14.0)all have different attack surfaces Directory.Packages.propscentralizes risk: if your shared version is vulnerable, all projects inherit the issue
packages.config (Legacy Format)
Older .NET Framework projects (pre-SDK) still use packages.config, an XML file in the project root:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net462" />
<package id="log4net" version="2.0.8" targetFramework="net462" />
</packages>
Weaknesses for security:
- Transitive dependencies aren't always explicit
- Harder to detect unused packages (security hygiene issue)
- Version pinning less flexible
- Slower to update: often requires manual removal and re-add
- Many teams never audit
packages.configfiles
Reality check: Even though .NET Framework reached end-of-life in April 2024, millions of legacy applications still depend on packages.config. If you're supporting enterprise customers, you're probably maintaining at least one. Microsoft's .NET Support Policy provides guidance on migration timelines.
Transitive Dependency Risks
A critical .NET security principle: your project's risk profile includes not just direct dependencies, but the entire dependency tree.
MyApp.csproj
├── Newtonsoft.Json (13.0.1) ← you explicitly depend on this
├── EntityFramework (6.4.4) ← you explicitly depend on this
│ └── EntityFramework.SqlServer (6.4.4)
│ └── System.Data.SqlClient (4.8.5)
│ └── Microsoft.Identity.Client (4.46.0)
│ └── System.Net.Http (4.3.1) ← VULNERABLE to OpenSSL padding oracle
│ └── System.Security.Cryptography.Algorithms (4.3.0) ← VULNERABLE
└── Serilog (3.0.1)
└── Serilog.Sinks.File (5.0.0)
In this tree, you have five layers of dependencies. A vulnerability in System.Security.Cryptography.Algorithms (layer 5) is your problem even though you never directly referenced it. The .NET runtime doesn't know to patch it until you update EntityFramework, which depends on SqlClient, which depends on Microsoft.Identity.Client.
This cascading effect is why transitive dependency visibility is critical.
What dotnet audit Finds—and Doesn't
dotnet audit (and its predecessor dotnet list package --vulnerable) is Microsoft's built-in scanner — zero setup, fast, and it cross-references the National Vulnerability Database automatically. What it can't do is tell you which of those findings anyone is actually exploiting, so every "critical" advisory looks the same regardless of real-world risk.
dotnet audit: The Built-In Scanner
Microsoft's dotnet audit command is the official way to scan for known vulnerabilities:
dotnet list package --vulnerable
# or
dotnet audit
Sample output:
Package Current Resolved Severity
Newtonsoft.Json 11.0.2 11.0.2 high Microsoft Security Advisory
log4net 2.0.8 2.0.8 critical RCE via unsafe logging patterns
System.Net.Http 4.3.1 4.3.1 high OpenSSL padding oracle
What It Does Well
✅ Scans .csproj and packages.config files automatically ✅ Detects most published CVEs (data from National Vulnerability Database) ✅ Shows direct and transitive dependencies ✅ Zero setup required (part of .NET SDK) ✅ Fast (typically <1 second) ✅ Supports suppression (through NuGet.config)
The Critical Gaps
❌ No EPSS scoring: You don't know which vulnerabilities are likely to be exploited next ❌ No CISA KEV matching: You don't know which vulnerabilities already have working exploits ❌ No context about active exploitation: All "critical" vulnerabilities look the same ❌ No prioritization: A 10-year-old patched advisory and a 3-day-old zero-day both show as "high" ❌ Limited remediation guidance: Just tells you to upgrade, not whether the upgrade is easy or introduces breaking changes ❌ No dependency update impact analysis: Doesn't warn you if an upgrade could break your code
Comparison Table: dotnet audit vs GeekWala
| Feature | dotnet audit | GeekWala |
|---|---|---|
| Scans .csproj | ✅ | ✅ |
| Scans packages.config | ✅ | ❌ (use packages.lock.json or an SBOM) |
| Scans Directory.Packages.props | ✅ | ❌ (centrally managed versions are skipped; scan packages.lock.json) |
| Shows EPSS scores | ❌ | ✅ (0.0–1.0 scale) |
| Shows CISA KEV status | ❌ | ✅ (actively exploited) |
| Indicates exploit availability | ❌ | ⚠️ (CISA KEV marks confirmed exploitation; public exploit code isn't tracked) |
| Tracks exploitation trends | ❌ | ❌ (shows today's EPSS, refreshed daily) |
| Suggests update paths | ⚠️ (suggests newest) | ✅ (fixed version + dotnet add package command) |
| Multi-project workspace support | ✅ | ✅ |
| API for CI/CD integration | ⚠️ (exit code only) | ✅ (JSON, webhooks) |
| Historical vulnerability tracking | ❌ | ✅ |
How GeekWala Scans .NET Projects
GeekWala scans .NET projects by reading the PackageReference entries in a .csproj (or the exact versions, transitive ones included, in packages.lock.json), then cross-referencing every package+version against OSV, EPSS, and CISA KEV and ranking findings by confirmed-exploited status first, then exploitation probability, then severity.
Supported File Formats
GeekWala parses two NuGet dependency declaration formats:
1. PackageReference (.csproj)
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
Extraction: Package name + exact version pinned in XML
2. packages.lock.json
"Newtonsoft.Json": { "type": "Direct", "resolved": "13.0.1" }
Extraction: Exact resolved versions, direct and transitive. This is also how you cover projects that use Central Package Management (Directory.Packages.props), because a .csproj that gets its versions centrally has no Version attribute to read. packages.config is not parsed; convert to PackageReference or scan an SBOM.
The Scanning Process
When you upload your .NET project to GeekWala:
- Parsing: GeekWala reads the
PackageReferenceentries in a.csproj(resolving$(Property)versions), or the exact versions — transitive ones included — inpackages.lock.json. References with no version, which is how central package management viaDirectory.Packages.propslooks from the.csproj, are skipped with a warning, so commitpackages.lock.json(setRestorePackagesWithLockFile) for full coverage. - Vulnerability lookup: Cross-reference each package+version against:
- OSV (Open Source Vulnerabilities): Primary CVE source
- EPSS: Exploitation Prediction Scoring System (0.0–1.0)
- CISA KEV: Known Exploited Vulnerabilities catalog
- Ranking: CISA KEV first, then EPSS, then severity
- Remediation: Show the fixed version and a
dotnet add package <name> --version <fixed>command
Example: Scanning a Real ASP.NET Core Project
Given this .csproj:
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
</ItemGroup>
GeekWala's scan output would look like:
| Package | Version | Issues | EPSS | KEV | Action |
|---|---|---|---|---|---|
| Newtonsoft.Json | 11.0.2 | CVE-2022-24765 (RCE) | 0.87 | ✅ | Upgrade to 13.0.3 |
| log4net | 2.0.8 | CVE-2022-24265 (RCE) | 0.91 | ✅ | Upgrade to 2.0.14 |
| EntityFramework | 6.4.4 | CVE-2021-24107 (Info Disc) | 0.52 | ❌ | Monitor or upgrade |
| Microsoft.AspNetCore.Mvc | 2.2.0 | 12 vulnerabilities (EOL) | avg 0.68 | ✅ (3 CVEs) | Migrate to 6.0 LTS |
Each row includes:
- EPSS score: How likely this CVE will be exploited in the next 30 days
- KEV status: Whether CISA has confirmed active exploitation
- Fixed version: The upgrade target comes from the advisory record, with a
dotnet add packagecommand; a jump like 2.2 to 6.0 is a major migration, so plan for breaking changes yourself - Upgrade command:
dotnet add package <name> --version <fixed>
Real-World Vulnerability Patterns in .NET Libraries
Four recurring patterns account for most of the real-world risk in .NET dependencies: unsafe Newtonsoft.Json deserialization, log4net's unsafe object serialization, the ASP.NET Core 2.2 end-of-life cascade with 50+ frozen CVEs, and an OpenSSL padding oracle buried four layers deep in System.Net.Http's transitive chain.
Pattern 1: Newtonsoft.Json Deserialization RCE (CVE-2022-24765)
Impact: Affects millions of ASP.NET applications
Root cause: Unsafe JSON deserialization with TypeNameHandling = TypeNameHandling.All
// DANGEROUS: Allows arbitrary type instantiation
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
var obj = JsonConvert.DeserializeObject(userInput, settings);
An attacker can craft JSON that instantiates arbitrary .NET types and invoke methods:
{
"$type": "System.Diagnostics.ProcessStartInfo",
"FileName": "cmd.exe",
"Arguments": "/c evil-command"
}
Vulnerable versions: < 13.0.1
EPSS score: 0.87 (87% probability of exploitation in the next 30 days)
CISA KEV status: Yes (added March 2022)
Patched in: 13.0.1 (October 2022)
Remediation: Upgrade immediately. If you can't upgrade, set TypeNameHandling = TypeNameHandling.None (the default in 13+)
Pattern 2: log4net Serialization RCE (CVE-2022-24265)
Impact: Affects ASP.NET apps using log4net for structured logging
Root cause: Unsafe serialization of event properties in the ObjectStateFormatter
When log4net serializes objects to storage (file, database, or network sink), it uses the .NET BinaryFormatter, which is inherently unsafe:
// Vulnerable pattern: logging untrusted objects
var userData = JsonConvert.DeserializeObject<User>(request.Body); // attacker input
Logger.Info($"User activity: {userData}"); // log4net serializes userData
If an attacker controls the serialized object, they can achieve RCE during deserialization.
Vulnerable versions: < 2.0.14 EPSS score: 0.91 (91% probability of exploitation in the next 30 days) CISA KEV status: Yes (added August 2022) Patched in: 2.0.14 (August 2022) Remediation: Upgrade to 2.0.14+. If you're on legacy .NET Framework, this is non-negotiable.
Pattern 3: Microsoft.AspNetCore.Mvc EOL Cascade (2.2 vs 6.0 LTS)
Impact: Affects older ASP.NET Core projects that haven't kept up
The issue: ASP.NET Core 2.2 reached end-of-life in December 2019. Its vulnerability database is frozen.
ASP.NET Core 2.2 (EOL Dec 2019)
├── 50+ known CVEs across the framework
├── No security patches
└── Transitive dependencies pinned to vulnerable versions
ASP.NET Core 6.0 LTS (supported until Nov 2024)
├── All 50+ CVEs fixed
├── Active security updates
└── Modern dependency versions
Remediation path: ASP.NET Core upgrades are major undertakings. Common blockers:
- Breaking API changes in middleware
- Changes to DI container behavior
- Entity Framework Core API shifts
- Authentication/authorization attribute changes
Typical timeline: 2-4 weeks for a typical microservice, 2-3 months for a monolith.
Pattern 4: System.Net.Http & OpenSSL Padding Oracle (CVE-2018-0296)
The scenario: A legacy .NET Framework project depends on an old version of System.Net.Http:
<package id="System.Net.Http" version="4.3.1" targetFramework="net462" />
This package shipped with a specific OpenSSL build that's vulnerable to padding oracle attacks on TLS connections. An attacker on the network can:
- Intercept encrypted traffic
- Use timing analysis to decrypt cookies/tokens
- Forge authentication claims
The cascade problem:
Your app depends on:
- EntityFramework 6.4.4
- EntityFramework.SqlServer 6.4.4
- System.Data.SqlClient 4.8.5
- Microsoft.Identity.Client 4.46.0
- System.Net.Http 4.3.1 ← VULNERABLE
Updating System.Net.Http alone won't help (it's not directly referenced). You must trace the dependency tree backward and either:
- Update EntityFramework (bringing newer SQL Server packages)
- Use a compatibility shim
- Accept the risk (not recommended)
Building a Scanning Workflow for ASP.NET Core Teams
A practical ASP.NET Core scanning workflow has four steps: wire GeekWala (or dotnet audit as a fallback) into your pull-request CI, triage results into same-day, within-sprint, and next-quarter tiers based on EPSS and KEV status, follow a fixed update checklist per fix, and run daily scheduled scans on long-lived production projects.
Step 1: Initial Scan Setup
Create a simple GitHub Actions workflow that scans on every PR:
name: Scan NuGet Dependencies
on: [pull_request, push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# GeekWala API scan
- name: Scan NuGet dependencies with GeekWala
run: |
jq -n --arg file_name packages.lock.json --rawfile content packages.lock.json \
'{file_name: $file_name, content: $content}' \
| curl -sf -X POST https://www.geekwala.com/api/v1/vulnerability-scan/run \
-H "Authorization: Bearer ${{ secrets.GEEKWALA_API_TOKEN }}" \
-H "Content-Type: application/json" \
-d @- \
| jq '.data'
# Fallback to dotnet audit
- name: Run dotnet audit
run: dotnet audit
Step 2: Interpretation & Triage
When GeekWala returns results, triage based on EPSS + KEV status:
These tiers use the default ladder from the 3-Signal triage guide.
- Tier 1 (patch immediately): KEV = true or EPSS above 0.9. Example: Newtonsoft.Json RCE, log4net RCE. SLA: same day (24 hours). If EPSS is above 0.9 but no patch exists yet, mitigate (WAF rule, feature flag) and monitor daily.
- Tier 2 (patch within 1–2 weeks): EPSS 0.3–0.9 and KEV = false. Example: info disclosure, auth bypass (no active exploit yet). SLA: within 1 week at EPSS 0.7–0.9, within 2 weeks at EPSS 0.3–0.7.
- Tier 3 (patch within 30 days): EPSS 0.1–0.3 and KEV = false.
- Tier 4 (monitor): EPSS below 0.1 and KEV = false, or when the complexity of the patch is very high. Example: obscure edge-case vulnerability. SLA: next quarterly release.
Step 3: Update Strategy
For Tier 1 vulnerabilities, use this update checklist:
□ Run dotnet add package PackageName --version X.Y.Z
□ Run full test suite (unit + integration)
□ Check for breaking API changes (common in major versions)
□ If Entity Framework changed: check migrations
□ If ASP.NET Core changed: test middleware registration
□ If authentication changed: test login flow
□ Commit with message: "Security: Patch CVE-2022-24765 (Newtonsoft.Json RCE)"
□ Tag as [security-hotfix] in PR title
□ Fast-track review (no lengthy approval process)
Step 4: Continuous Monitoring
Set up daily scans for long-lived projects:
# Scheduled job (runs daily at 2 AM UTC)
0 2 * * * /usr/local/bin/geekwala-scan-project.sh
Best Practices and Common Pitfalls
Once a vulnerable NuGet package is confirmed, teams have three real options: upgrade to the patched version, force-override a transitive resolution when the direct dependency hasn't shipped a fix yet, or — only when the vulnerable code path is genuinely unreachable — document and suppress it instead of silently ignoring the finding.
A fixed version exists and is compatible
Bump the direct or transitive dependency to the patched release. Preferred path — resolves the root cause.
No compatible fix yet, but a patched transitive version is available
Use your package manager's override or force-resolution mechanism (e.g. npm/pnpm overrides, Maven dependencyManagement, or NuGet Central Package Management overrides) to force the resolved version without waiting on the direct dependency's maintainer.
The vulnerable code path is not reachable in your usage
Document the exploitability assessment as a VEX (Vulnerability Exploitability eXchange) statement — not-affected, with the justification recorded, not just silently ignored.
Upgrade first, override when you must move faster than upstream, and reserve accept-with-VEX for genuinely unreachable code paths — not as a way to close the ticket.
✅ DO: Centralize Versions with Directory.Packages.props
<!-- Directory.Packages.props in repository root -->
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="log4net" Version="2.0.15" />
<PackageVersion Include="Serilog" Version="3.0.1" />
</ItemGroup>
Benefits:
- Single source of truth for all project versions
- Easier to audit (one file to scan)
- Simpler to patch (update once, all projects inherit)
- Reduces version mismatch bugs
✅ DO: Use Semantic Versioning Constraints (When Appropriate)
<!-- Allow patch updates automatically -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.*" />
<!-- Allow minor + patch (typically safe) -->
<PackageReference Include="Serilog" Version="3.*" />
<!-- Pin exactly for stability -->
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="6.0.11" />
Scanning implication: GeekWala does not resolve these constraints against NuGet.org, so scan packages.lock.json to check the exact versions that actually restored.
❌ DON'T: Leave packages.config Unscanned
If you have any legacy .NET Framework projects:
// In your CI pipeline
if (File.Exists("packages.config"))
{
Console.WriteLine("⚠️ Legacy packages.config detected!");
Console.WriteLine("Migrate to PackageReference (or export an SBOM) so GeekWala can scan it");
}
packages.config files are often forgotten because the project is "legacy" and "not actively maintained." But vulnerabilities in legacy code are especially dangerous because attackers know they'll be neglected.
❌ DON'T: Ignore Transitive Dependencies
When you see:
Newtonsoft.Json 11.0.2 -> 13.0.3 (requires major version bump)
Don't assume it's safe because you "don't directly use Newtonsoft.Json APIs." Transitive dependencies can be exploited without your explicit code calling them. A deserialization vulnerability in a transitive dependency is just as dangerous as one in a direct dependency.
❌ DON'T: Patch Without Testing
Even a "safe" patch can introduce subtle bugs:
// Before upgrade (Newtonsoft.Json 11.0.2)
var settings = new JsonSerializerSettings { };
var data = JsonConvert.DeserializeObject<MyClass>(json, settings);
// After upgrade (13.0.3)
// TypeNameHandling defaults to None now (safer)
// But if your code relied on implicit type resolution, it breaks
Always run your full test suite after patching dependencies.
✅ DO: Use NuGet.config for Suppression (Carefully)
<!-- NuGet.config -->
<configuration>
<config>
<add key="nuget.org/v3/index.json" value="https://api.nuget.org/v3/index.json" allowInsecureConnections="false" />
</config>
<!-- Suppress only if you have explicit justification -->
<packageManagement>
<packageSource>
<suppressed>
<package id="Vulnerable.Package" version="1.0.0" />
</suppressed>
</packageSource>
</packageManagement>
</configuration>
Suppression use case: You've confirmed the vulnerable code path is unreachable in your app, and an upgrade would introduce a breaking change. Document why:
<!-- Justification for CVE-2021-XXXXX suppression -->
CVE-2021-XXXXX affects LegacyLibrary.dll when used with X509 certificates
on Windows XP. Our application:
- Only runs on Windows Server 2016+
- Does not use X509 certificates
- Patched version breaks API compatibility with our code
Decision: Suppress until next major release cycle (Q3 2026)
Reviewed by: @security-team
Date: 2026-02-25
-->
Never suppress security vulnerabilities silently.
Frequently Asked Questions
Should I upgrade to the latest version of every dependency?
Not necessarily. The latest version might have:
- Breaking API changes (especially true for major version bumps)
- Different performance characteristics (newer isn't always faster)
- Unrelated features you don't need (increased surface area)
Instead, upgrade to the earliest version that fixes the vulnerability AND maintains compatibility with your code. For example:
Current: Newtonsoft.Json 11.0.2 (vulnerable to RCE)
Latest: Newtonsoft.Json 13.0.3
Your app only uses basic JSON serialization (no type handling).
Safe upgrade: 13.0.1 (first version to fix CVE-2022-24765)
Test it. If no breaking changes, you can upgrade to 13.0.3 later for features.
How often should I scan my NuGet dependencies?
Minimum: Weekly automated scans (via CI/CD). Recommended: Daily automated scans for production applications. Emergency: Immediate ad-hoc scans when a critical vulnerability is announced.
If you're running ASP.NET Core in production, a new critical CVE can be announced any day. The longer you wait to scan, the longer you're exposed.
What's the difference between EPSS and CVSS scores?
CVSS (Common Vulnerability Scoring System): Measures the severity of a vulnerability (how bad it is if exploited). Range: 0.0-10.0.
- 0-3.9: Low
- 4.0-6.9: Medium
- 7.0-8.9: High
- 9.0-10.0: Critical
Example: Newtonsoft.Json RCE has CVSS 9.8 (critical).
EPSS (Exploit Prediction Scoring System): Predicts the likelihood of active exploitation in the next 30 days. Range: 0.0–1.0.
- 0.0–0.1: Unlikely to be exploited
- 0.1–0.4: Possible
- 0.4+: Likely to be exploited soon
Example: Same Newtonsoft.Json RCE has EPSS 0.87, meaning an 87% chance of exploitation in the next month.
Why both matter: A critical vulnerability (CVSS 9.8) that's not being exploited yet (EPSS 0.02) might be lower priority than a medium vulnerability (CVSS 6.5) being actively exploited today (EPSS 0.92). Learn more: Understanding EPSS.
Can I scan NuGet packages in private repositories?
Yes, and no feed credentials are needed: GeekWala never downloads your packages. It matches the names and versions in your .csproj or packages.lock.json against public advisories. The flip side is that a package published only on your private feed has no public advisory, so it will show no findings — vulnerabilities in your own internal packages need your own tracking.
What if there's no patch available for a vulnerability?
This happens. An open-source library might be unmaintained, or the vulnerability might be in an old version that the maintainer no longer supports.
Your options:
- Fork and patch: Create a private fork, apply a fix, deploy your patched version
- Switch libraries: Evaluate a maintained alternative
- Mitigate in code: If the vulnerability requires specific conditions, can you eliminate those conditions?
- Accept the risk: Document why, set a review date, monitor for active exploitation
Example: A library is vulnerable to XXE attacks. You can mitigate by:
var xmlSettings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null // Disable external entity resolution
};
using var reader = XmlReader.Create(stream, xmlSettings);
var doc = XDocument.Load(reader);
If you mitigate the root cause, the vulnerability is no longer exploitable in your context—but still flag it as "mitigated, not patched" in your scan results.
How do I know if a vulnerability affects my specific code?
Not all vulnerabilities affect all projects using a library. For example, Newtonsoft.Json's RCE only triggers if you explicitly enable TypeNameHandling = TypeNameHandling.All.
To determine impact:
- Check the CVE details: Read the full advisory
- Audit your usage: Search your codebase for the vulnerable code pattern
- Check configuration: Is the dangerous setting enabled in your config?
- Test the POC: If a proof-of-concept exists, run it against your app
Example decision tree:
Newtonsoft.Json 11.0.2 detected (CVE-2022-24765)
│
├─ Search codebase: "TypeNameHandling.All" → NOT FOUND
├─ Search config: "TypeNameHandling" → NOT FOUND
└─ Check JsonSerializerSettings defaults → TypeNameHandling.None (safe)
Result: VULNERABILITY PRESENT BUT NOT EXPLOITABLE
Action: Still upgrade (defense in depth), but not emergency-level
Next Steps: Start Scanning Your .NET Projects
Your NuGet dependencies are a critical attack surface. dotnet audit is a good start, but it doesn't tell you which vulnerabilities are actually being exploited or likely to be exploited soon. GeekWala closes that gap with EPSS-ranked, KEV-flagged findings and a concrete upgrade path for each one.
For each vulnerability, GeekWala gives you:
- Exploitation risk (current EPSS score, refreshed daily)
- Active exploitation status (CISA KEV)
- Recommended upgrade path
- API integration for CI/CD automation
Start with your most critical projects (production microservices, customer-facing applications) and work backward.
Stop patching by CVSS severity. Start patching by exploitation probability.
Scan your .NET project with GeekWala → — upload your .csproj or packages.lock.json and get EPSS scores, CISA KEV status, and prioritized remediation guidance in under a minute. No account needed.
Related Reading
GeekWala guides:
- What is EPSS? Exploit Prediction Scoring Explained
- CISA KEV: What "Known Exploited Vulnerabilities" Means for Your Project
- npm audit vs GeekWala: Why CVSS Scores Alone Are Misleading
- Python Dependency Security: Scanning PyPI Vulnerabilities
- Rust Vulnerability Scanning: What cargo audit Misses
- Java Dependency Security: Scanning Maven Vulnerabilities
- Go Vulnerability Scanning: What govulncheck Misses
- 7 Dependency Vulnerability Scanners Compared
Official Microsoft resources:


