Like leaving the master key under a doormat that only the building's own maintenance crew would think to check
CVE-2026-114148 is a local privilege escalation in Microsoft .NET on Linux caused by incorrect file ownership metadata baked into official distribution tarballs. Affected artifacts include ASP.NET Core runtime and targeting-pack tarballs for .NET 8.0.0–8.0.32 and 9.0.0–9.0.21, plus source-build tarballs for .NET 8.0.100–8.0.112, 9.0.100–9.0.122, 10.0.100–10.0.113, 10.0.400–10.0.401, and .NET 11 through RC2. When an administrator extracts these tarballs as root (which preserves numeric ownership by default), certain runtime files end up owned by a non-root UID embedded in the archive. Any local user whose UID matches—or who can otherwise write to those files—can replace or patch .NET runtime binaries and libraries. The next time a higher-privileged process (e.g., an ASP.NET Core service running as a service account) loads the runtime, the attacker’s code executes at that elevated privilege level. Fixed in .NET 8.0.33, 9.0.22, 10.0.14, and 11.0 RC3. Linux only (ARM, ARM64, x64).
Microsoft’s CNA assigned a CVSS 3.1 base score of 7.8 HIGH (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H), which is technically accurate for the raw local-access vector with full CIA impact. However, this score overstates the real-world risk for most enterprise fleets. The vulnerability only applies to Linux hosts where .NET was installed via tarball extraction—a minority deployment method. Most organizations use Docker images (mcr.microsoft.com/dotnet/*), distribution packages (apt/yum/dnf), or snap packages, none of which carry the flawed ownership metadata. The attack also requires the adversary to already have local shell access on the target host. Combining these constraints, the practical population at risk is a small fraction of the .NET Linux installed base, making a MEDIUM assessment more appropriate for fleet-level prioritization.
4 steps from start to impact.
Obtain local shell on target host
- Valid local user account on the Linux host
- SSH, console, or container exec access
- Requires prior compromise or insider access
- Hosts running .NET from tarballs may not expose SSH externally
- MFA on SSH and bastion host architectures block casual lateral movement
Locate vulnerable .NET tarball installation
/usr/share/dotnet or a custom DOTNET_ROOT) and checks file ownership using find or stat. If the runtime was extracted from an affected tarball as root, certain files will be owned by a non-root UID baked into the archive. The attacker confirms their UID matches or the files are world-writable.- Read access to the .NET installation directory
- .NET installed from an affected tarball version
- Tarball was extracted as root (default tar behavior preserves ownership for root)
- Attacker UID matches the incorrect UID in the tarball, or files are otherwise writable
- Most enterprise .NET Linux deployments use Docker or package managers, not tarballs
- The non-root UID in the tarball must coincidentally match the attacker's local UID
- Custom install paths may not be easily discoverable
- Extraction with --no-same-owner (some install scripts do this) neutralizes the flaw
Replace or patch .NET runtime files
libhostfxr.so, libcoreclr.so, managed DLLs in the shared/ tree) with trojanized versions. The payload could be a reverse shell, credential harvester, or persistence implant. Because the attacker owns the files, the modification is silent to standard permission checks.- Confirmed write access to runtime files
- Payload compatible with the .NET hosting layer or runtime loader
- File integrity monitoring will immediately flag modifications
- SELinux or AppArmor in enforcing mode may block writes even with correct ownership
- Attacker needs .NET internals knowledge to craft a loadable payload
Privileged process loads trojanized runtime
- A higher-privileged process uses the same .NET runtime installation
- The process is restarted or newly launched after the file modification
- Well-configured services use dedicated low-privilege service accounts, limiting blast radius
- Container isolation limits lateral impact if .NET runs inside a container
- Process restart cadence may be hours or days, delaying exploitation
chown -R root:root /usr/share/dotnet (or your custom DOTNET_ROOT path) on every Linux host where .NET was installed from a tarball. This directly eliminates the vulnerable condition by correcting the file ownership, regardless of .NET version. No noisgate mitigation SLA applies to MEDIUM verdicts—go straight to the 365-day remediation window, but this one-liner is trivial and should be applied proactively in your next change window.apt install dotnet-runtime-8.0) or Docker images (mcr.microsoft.com/dotnet/aspnet:8.0). These distribution methods set correct root ownership during installation, permanently eliminating this entire vulnerability class. This is a strategic hardening measure within the 365-day remediation window./usr/share/dotnet (and custom DOTNET_ROOT paths) for unauthorized file modifications. This converts the silent privilege escalation into a detectable, alertable event even if the ownership flaw remains unpatched. Deploy within your standard tooling rollout cadence.sestatus or aa-status.- Network firewalls, WAF, or IDS/IPS: This is a purely local file-ownership vulnerability with zero network component. Network-layer controls are completely irrelevant to detection or prevention.
- Containerization without image rebuild: If the container image was built using an affected tarball, the incorrect ownership propagates into the container filesystem. Simply running .NET in a container does not remediate the flaw; you must fix the base image or update the tarball used during image build.
- Windows Update or Microsoft Update: This CVE exclusively affects Linux tarball distributions. Windows .NET installations use MSI/MSIX packaging with correct permissions and are not vulnerable.
- Extracting tarballs as a non-root user: While this technically avoids preserving the bad ownership (non-root cannot chown), it is not a practical control because .NET typically needs to be installed in system-wide directories owned by root.
The supporting signals.
| In-the-wild exploitation | Not observed. No reports of active exploitation from any source. Not listed on CISA KEV. No threat actor campaigns identified. |
|---|---|
| Proof of concept | None public. No PoC repositories found on GitHub, pocindex.io, ExploitDB, or Nuclei templates. Exploitation is conceptually simple (file replacement after ownership check) but no weaponized tooling exists. |
| EPSS | Not yet scored. CVE was disclosed 2026-10-25 (1 day ago); the FIRST EPSS API returns no data. Expected to be low given local-only attack vector and absence of public PoC. |
| KEV status | Not listed on CISA KEV as of 2026-10-26. |
| CVSS vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 7.8 HIGH (Microsoft CNA). Temporal metrics E:U/RL:O/RC:C reduce the temporal score to approximately 6.8. Key: local access, low complexity, low privilege, no user interaction, unchanged scope, full CIA impact. |
| Affected versions | ASP.NET Core tarballs (.NET 8 and 9): runtime and targeting-pack, versions 8.0.0–8.0.32 and 9.0.0–9.0.21. Source-build tarballs (.NET 8/9/10/11): 8.0.100–8.0.112, 9.0.100–9.0.122, 10.0.100–10.0.113, 10.0.400–10.0.401, 11.0.100-preview.1 through RC2. Linux only (ARM, ARM64, x64). |
| Fixed versions | .NET 8.0.33 (SDK 8.0.133), 9.0.22 (SDK 9.0.123), 10.0.14 (SDK 10.0.114/10.0.402), 11.0 RC3. Refreshed tarballs at dotnet.microsoft.com. |
| Distro backports | Linux distribution packages (Debian, Ubuntu, Fedora, RHEL) that repackage .NET with root:root ownership during their packaging process are not affected. The RaspberryPiDotnetRepository confirmed non-vulnerability because it manually reassigns ownership during packaging. |
| Scanning/exposure | Not network-scannable. Shodan, GreyNoise, Censys, and FOFA are irrelevant—this is a local file-ownership issue with no network-facing indicator. Detection requires host-level file auditing or asset inventory of .NET installation methods. |
| Disclosure | Disclosed 2026-10-25 via out-of-band security update by Microsoft. No external researcher credited; appears internally discovered. Advisory: dotnet/announcements#495. |
Sources.
- Microsoft Security Advisory CVE-2026-114148
- .NET October 2026 Out-of-Band Security Updates (Microsoft DevBlog)
- .NET October 2026 OOB security updates (dotnet/core)
- .NET 10.0 Update - October 25, 2026 (Microsoft Support)
- SecurityOnline - .NET Brotli and Tarball Security Flaws
- .NET October 2026 OOB updates (dotnet/announcements #496)
- RaspberryPiDotnetRepository - CVE-2026-114148 ownership analysis
Why this verdict
- Local access required (AV:L): The attacker must already have a local shell on the Linux host. This is a post-initial-compromise escalation vector, not an entry point. Every host the attacker targets requires a separate prior foothold, creating compounding difficulty across a fleet. This alone represents a significant downward pressure from the raw CVSS 7.8.
- Tarball-only deployment method narrows the population dramatically: The vast majority of enterprise .NET-on-Linux deployments use Docker images (
mcr.microsoft.com/dotnet/*), distro packages (apt/yum/dnf), or snap installs. Manual tarball extraction is primarily used by distro maintainers (who repackage with correct ownership), IoT devices, and ad-hoc developer setups. Estimated fraction of .NET Linux installs using raw tarballs: <10–15%. - Ownership-match constraint adds friction: The exploit requires (a) the tarball to have been extracted as root (preserving ownership), AND (b) the attacker's local UID to match the incorrect UID embedded in the tarball metadata, or the files to be otherwise world-writable. This is a non-trivial coincidence that filters out many otherwise-reachable environments.
- Role multiplier: .NET runtime is application middleware, not a canonical high-value-role component (not a hypervisor, IdP, PAM, CA, backup engine, or edge appliance). (a) *Low-value role (dev sandbox, workstation):* impact contained to dev environment, MEDIUM at most. (b) *Typical role (ASP.NET Core production server installed from tarball):* successful exploitation grants control of the web app's service account, potentially accessing databases and secrets—host-level blast radius, but limited to the subset of production hosts using tarball installs. (c) *High-value role (CI/CD build agent using source-build tarball):* could theoretically enable supply-chain compromise of built artifacts. However, source-build tarballs are consumed by distro packagers who repackage with correct ownership, and CI/CD agents overwhelmingly use SDK Docker images. This high-value role represents <1% of the .NET installed base, failing to clear the HIGH floor threshold.
- No exploitation evidence or weaponization: Zero public PoCs, zero in-the-wild exploitation reports, zero KEV listing. The temporal CVSS metric E:U (Unproven) confirms this. While the attack is conceptually straightforward (file replacement), the absence of any exploitation activity 1 day post-disclosure—combined with the local-only, tarball-only constraints—suggests low attacker ROI relative to other escalation primitives.
Why not higher?
Promoting to HIGH would require either remote exploitability or evidence that a significant fraction (≥1%) of .NET Linux tarball installs occupy high-value roles where the blast radius reaches domain, fleet, or supply-chain scale. Neither condition is met. Local access is a hard prerequisite, the tarball installation method is a minority deployment path, and the high-value-role scenarios (CI/CD supply chain) affect well under 1% of the installed base because distro packagers—the primary source-build consumers—repackage with correct ownership. No PoC or exploitation exists to suggest imminent weaponization that would override these friction factors.
Why not lower?
Dropping to LOW would underweight the genuine privilege-escalation potential on hosts that ARE affected. Where .NET was installed from a tarball with preserved ownership, any local user whose UID matches can escalate to the privilege level of .NET application processes with low complexity (AC:L) and no user interaction (UI:N). The CIA impact is full (C:H/I:H/A:H) on those hosts. This is a real, exploitable local privesc with concrete impact—not a theoretical or informational finding.
Crowdsourced verification payload.
Run on each target Linux host where .NET may have been installed from a tarball. Execute as any user with read access to the .NET install directory: bash cve-2026-114148-check.sh /usr/share/dotnet (pass your custom DOTNET_ROOT if non-default). No root privileges required for the check.
#!/usr/bin/env bash
# CVE-2026-114148 Checker - .NET Tarball Ownership Flaw (Linux only)
# Usage: bash cve-2026-114148-check.sh [/path/to/dotnet]
# Exit: 0=PATCHED 1=VULNERABLE 2=UNKNOWN
set -euo pipefail
DR="${1:-${DOTNET_ROOT:-/usr/share/dotnet}}"
if [ ! -d "$DR" ]; then
echo "UNKNOWN - directory $DR does not exist; .NET may not be installed or uses a different path."
exit 2
fi
echo "=== CVE-2026-114148 Check ==="
if [ -x "$DR/dotnet" ]; then
VER=$("$DR/dotnet" --version 2>/dev/null || echo "unknown")
echo "[INFO] .NET SDK version: $VER"
echo "[INFO] Installed runtimes:"
"$DR/dotnet" --list-runtimes 2>/dev/null || echo " (could not list runtimes)"
else
echo "[WARN] No executable dotnet binary found at $DR/dotnet"
fi
echo ""
echo "[CHECK] Scanning $DR for files not owned by root ..."
USER_BAD=$(find "$DR" -not -user root 2>/dev/null | head -30 || true)
GROUP_BAD=$(find "$DR" -not -group root 2>/dev/null | head -30 || true)
if [ -n "$USER_BAD" ] || [ -n "$GROUP_BAD" ]; then
echo "VULNERABLE - non-root-owned files detected in $DR"
echo ""
if [ -n "$USER_BAD" ]; then
echo "--- Files with non-root USER ownership ---"
echo "$USER_BAD" | head -10 | while IFS= read -r f; do
ls -lan "$f" 2>/dev/null || true
done
fi
if [ -n "$GROUP_BAD" ]; then
echo "--- Files with non-root GROUP ownership ---"
echo "$GROUP_BAD" | head -10 | while IFS= read -r f; do
ls -lan "$f" 2>/dev/null || true
done
fi
echo ""
echo "Remediation: sudo chown -R root:root $DR"
exit 1
fi
echo "PATCHED - all files in $DR are owned by root:root."
exit 0