CVE-2026-44788 is a medium-severity (CVSS 5.9) Path Traversal vulnerability in SharpCompress. A fix is available for SharpCompress — see the affected versions and patch details below.
SharpCompress: Directory traversal via directory entries in WriteToDirectory (zip slip variant)
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-44788.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
How urgent is this, really
CVE-2026-44788 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.
Where this sits among everything scored
Of 378,156 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.
Real-World Exposure
SharpCompressReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects NuGet packages — download data is not available via public APIs for these ecosystems.
Description
Summary
A path traversal vulnerability in IArchive.WriteToDirectory() allows a malicious archive to create directories outside the intended extraction root. For TAR archives, this can be escalated to arbitrary file writes by chaining with a symlink entry, giving a full write primitive on the target filesystem subject to the permissions of the running process.
Details
The vulnerable code is in the directory-entry branch of WriteToDirectoryInternal (sync, IArchiveExtensions.cs:48–61) and WriteToDirectoryAsyncInternal (async, IAsyncArchiveExtensions.cs:70–84):
var dirPath = Path.Combine(destinationDirectory, entry.Key);
Directory.CreateDirectory(Path.GetDirectoryName(dirPath + "/"));
No Path.GetFullPath() normalisation and no bounds check are applied before the Directory.CreateDirectory call. Two .NET Path.Combine behaviours make this exploitable:
- Relative traversal:
Path.Combine("/safe/extract", "../../evil")→ the OS resolves..segments on the raw path, placing the directory outside the extraction root. - Absolute path override:
Path.Combine("/safe/extract", "/tmp/evil")→ returns"/tmp/evil"— the base is discarded entirely for rooted paths.
File entries are not directly affected — they route through ExtractionMethods.WriteEntryToDirectory which applies the correct guard (GetFullPath + StartsWith, see ExtractionMethods.cs:54–65). The directory-entry branch is a separate fast-path that was added without that guard.
Affected archive formats: ZIP and TAR (non-solid). Solid archives and 7-Zip use the reader path which calls the secure method.
Escalation to arbitrary file writes (TAR only)
Path.GetFullPath on .NET does not resolve symlinks — it only normalises . and .. segments. This means the file-entry guard in ExtractionMethods.WriteEntryToDirectory can be bypassed via symlink chaining in TAR archives when the caller supplies a SymbolicLinkHandler:
archive.WriteToDirectory("/safe/extract", new ExtractionOptions
{
ExtractFullPath = true,
SymbolicLinkHandler = (linkPath, linkTarget) =>
File.CreateSymbolicLink(linkPath, linkTarget) // naive — no validation of linkTarget
});
Attack sequence in a single TAR archive:
-
Symlink entry —
link→../evil_outside/TheSymbolicLinkHandlercreates/safe/extract/linkpointing outside the extraction root. -
File entry —
link/secret.txtExtractionMethods.WriteEntryToDirectorycomputes:destdir = Path.GetFullPath("/safe/extract/link")→"/safe/extract/link"— textually inside root, check passes ✓File.Open("/safe/extract/link/secret.txt")— OS follows symlink, file is written to/evil_outside/secret.txt
The library does not validate linkTarget before passing it to the caller's handler, and the XML docs do not warn that it may be a traversal path. The idiomatic handler implementation above is therefore silently exploitable.
ZIP does not support symlinks in SharpCompress (ZipEntry.LinkTarget always returns null), so this escalation is TAR-only.
| Attack | ZIP | TAR |
|---|---|---|
| Directory traversal (escape extraction root) | Yes | Yes |
| Escalate to arbitrary file writes via symlink chain | No | Yes (if caller provides SymbolicLinkHandler) |
Recommended fix — apply the same pattern from ExtractionMethods.WriteEntryToDirectory to both affected files:
var fullDestDir = Path.GetFullPath(destinationDirectory);
if (!fullDestDir.EndsWith(Path.DirectorySeparatorChar))
fullDestDir += Path.DirectorySeparatorChar;
var dirPath = Path.GetFullPath(Path.Combine(fullDestDir, entry.Key));
if (!dirPath.StartsWith(fullDestDir, PathComparison))
throw new ExtractionException(
"Entry is trying to create a directory outside of the destination directory.");
Directory.CreateDirectory(dirPath);
Additionally, the library should validate LinkTarget before invoking the caller's SymbolicLinkHandler, or document clearly that callers must validate it themselves.
PoC
A self-contained .NET console app is available at:
https://github.com/svenclaesson/poc-sharpcompress-traversal
git clone https://github.com/svenclaesson/poc-sharpcompress-traversal
cd poc-sharpcompress-traversal
dotnet run
The PoC crafts a ZIP with three directory entries (../../escaped_relative/, /tmp/escaped_absolute/, safe_subdir/) using System.IO.Compression (stdlib), then extracts with SharpCompress. Output shows [ESCAPED] for the two malicious entries and [ok] for the legitimate one, on both sync and async APIs.
Tested against SharpCompress 0.47.4 (latest NuGet).
Impact
This is a path traversal / zip slip vulnerability (CWE-22). Any application that calls archive.WriteToDirectory() on an untrusted archive is affected — which covers the primary documented extraction API.
For ZIP archives the impact is limited to arbitrary directory creation, which can be used to stage privilege escalation (e.g. cron drop-ins, XDG config paths, service spool directories) or shadow expected paths to alter application behaviour.
For TAR archives, callers that implement a SymbolicLinkHandler — which is the only way to faithfully restore a TAR — are exposed to a full arbitrary file write primitive via the symlink chaining described above.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| .NETNuGet | SharpCompress | all versions | 0.48.0dotnet add package SharpCompress --version 0.48.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for SharpCompress, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update SharpCompress to 0.48.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-44788 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-44788 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-44788. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is CVE-2026-44788 in your dependencies?
O3 Security finds CVE-2026-44788 across NuGet dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.