Skip to main content

ngx_cache_purge EUVDEUVD-2026-97159

| CVE-2026-108981 LOW
UNIX Symbolic Link (Symlink) Following (CWE-61)
2026-10-12 mitre GHSA-5fhq-3m7h-fqv8
3.6
CVSS 3.1 · Vendor: mitre
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Gain code execution as the shared nginx/app user
  2. Delivery
    Plant symlink inside proxy_cache_path
  3. Exploit
    Trigger cache purge (e.g. PURGE request)
  4. Execution
    ngx_walk_tree stat() follows the symlink
  5. Impact
    Files outside the cache deleted

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling UNIX symlink resolution
Exploitation Conditions

Requires that nginx and the served application (e.g., WordPress) run under the SAME OS user account, AND that the attacker can create a symbolic link inside the configured proxy_cache_path directory - which in practice means the attacker already holds code execution or arbitrary file-write as that shared user. A cache purge operation (e.g., a proxy_cache_purge PURGE request, purge_all, or wildcard purge) must then be triggered to walk the cache tree. Limiting factors: local access only (no remote vector), the shared-user deployment is not nginx's default isolation posture, and against version 3.0.4 the only remaining avenue is a TOCTOU race that must be won during the walk. These constraints make opportunistic or remote exploitation impractical.

Impact

All exploitation signals point to a genuinely LOW real-world priority. The vendor-supplied CVSS vector (AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L, base 3.6) describes a local, high-complexity, authenticated flaw with only limited integrity and availability impact and no confidentiality impact - consistent with the description, which requires an attacker to already be able to create a symlink inside the cache path (i.e., to already hold code execution as the same user nginx runs as). No EPSS score was provided, there is no CISA KEV listing, and no public exploit was identified at time of analysis, so there is no evidence of active or opportunistic exploitation. The signals are therefore internally consistent rather than conflicting: this is a defense-in-depth hardening fix, not a high-urgency item. Two caveats security teams should note explicitly: (1) the 'Information Disclosure' tag in the metadata conflicts with both the description ('file deletion') and the CVSS C:N - the actual impact is destructive (integrity/availability), not disclosure; and (2) the vendor states that 3.0.4 only fixes the arbitrary-earlier-symlink case and does NOT resolve an applicable TOCTOU race condition, so even patched installations retain a residual, harder-to-win race window - verify this limitation with the vendor before considering the issue fully closed.

Exploit ScenarioDerived

An attacker who has already compromised a WordPress (or other) application running under the same OS user as nginx plants a symbolic link (e.g., 'evil -> /var/www') inside the proxy_cache_path directory. When a cache purge operation runs (such as a PURGE request using purge_all), nginx's ngx_walk_tree() stat()s the link, follows it as if it were a real cache subdirectory, and deletes files that live outside the cache. No public exploit code was identified at time of analysis; exploitation requires local same-user access and, against 3.0.4, winning a TOCTOU race.

Monitor Track and reassess. Why: LOW severity (CVSS 0.1-3.9).
Patch available 0.1% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 12, 2026

Symlink following in the nginx third-party module ngx_cache_purge before 3.0.4 allows a local attacker to cause deletion of files outside the configured proxy_cache_path: the module's purge walks (purge_all, wildcard purge, or a plain proxy_cache_purge PURGE request) trust nginx's ngx_walk_tree(), which classifies directory entries with stat() and therefore descends into planted symlinks. Exploitation is narrow - it requires that nginx and a served application such as WordPress run under the same OS user account and that the attacker already has that user's file-write or code-execution capability to plant the link - and no public exploit code or confirmed in-the-wild activity was identified at time of analysis, with the assessed CVSS of 3.6 (AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L) reflecting a genuinely low-priority, local-only, high-complexity issue. Version 3.0.4 blocks symlinks found inside the cache tree but does not close an applicable TOCTOU race condition, so the shared-user deployment remains the decisive risk factor.

RemediationAI

Vendor-released patch: 3.0.4 - upgrade ngx_cache_purge to the 3.0.4 release (https://github.com/nginx-modules/ngx_cache_purge/releases/tag/3.0.4), or cherry-pick the upstream fix from PR #72 / commit a6da1352f52a8a02dd6828e88c39ed42fddcee96, which installs ngx_http_purge_file_cache_pre_tree() as the tree pre-handler and refuses to descend into any symlink below the cache root. Note that 3.0.4 does not close the TOCTOU race, so the module should still be treated as unsafe where the cache directory is writable by an untrusted principal. Because exploitation requires the attacker to plant a symlink as the nginx/app user, the highest-value compensating control is deployment isolation: run nginx workers under a dedicated account distinct from the application user (e.g., separate nginx and php-fpm users), which removes the attacker's ability to write into the cache path at all - the trade-off is that this breaks the common shared-user 'just works' WordPress permission recipe and may require re-chowning content and cache directories. Additionally, chmod the proxy_cache_path so only the nginx user has write access and no group/other write bits are set; restrict who can trigger purges by binding the PURGE location to a trusted source (allow/deny or an authentication layer) so an untrusted principal cannot force a tree walk; and if a shared-user layout is unavoidable, place the cache path on a filesystem mounted nosuid,nodev and consider applying an ACL or mount option that does not permit following links out of the cache tree. If the module is not actually needed, disabling it (removing the proxy_cache_purge directives and rebuilding without ngx_cache_purge) eliminates the vector entirely with the obvious trade-off of losing targeted cache invalidation.

Affected VersionsENISA

ngx_cache_purge 2.4.0 ≤2.5.6
ngx_cache_purge 3.0.0 <3.0.4

Affected Packages

euvd ngx_cache_purge fix: 3.0.4

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

The flaw is CWE-61 (Symlink Following / link following) in the ngx_cache_purge nginx module, tracked against CPE cpe:2.3:a:denji:ngx_cache_purge:*:*:*:*:*:*:*:* (all releases prior to 3.0.4). Purge operations build an ngx_tree_ctx_t and hand it to nginx core's ngx_walk_tree(); in the affected versions the pre_tree_handler was set to ngx_http_purge_file_cache_noop, so the walk performed no per-node validation. ngx_walk_tree() distinguishes files from directories using stat(), which resolves symbolic links, meaning a directory entry in the cache path such as 'evil -> /somewhere/else' is treated as a legitimate cache directory and its contents are enumerated and deleted as part of the purge. Because nginx itself only ever creates regular directories and files inside a cache path, any symlink below the cache root is foreign. The upstream fix in PR #72 / commit a6da1352f52a8a02dd6828e88c39ed42fddcee96 replaces the noop handler with ngx_http_purge_file_cache_pre_tree(), which calls ngx_link_info() (lstat semantics) and ngx_is_link(), logs a warning, and returns NGX_DECLINED to skip the link; the handler is applied at every call site (process_queue, delete_variants, cache_purge_all, cache_purge_partial). Importantly, the cache root itself is never passed to this handler, so a cache path that is itself a symlink keeps working - the fix targets only links found below the root. The check-then-walk pattern leaves a TOCTOU window: an attacker able to swap a real directory for a symlink between the pre_tree check and the subsequent stat()/descent can still redirect deletions, which 3.0.4 explicitly does not resolve.

Know when Ngx Cache Purge gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (mitre) PRIMARY 3.6 LOW
AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
vuln.today AI 3.6 LOW

Attacker needs local same-user access to plant the symlink (AV:L, PR:L) and must win a same-user/timing condition (AC:H); impact is file deletion (I:L/A:L), with no data read (C:N).

3.1 AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
4.0 AV:L/AC:H/AT:P/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N

Primary rating from Vendor (mitre).

CVSS VectorVendor: mitre

Attack Vector
Local
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
Low

DescriptionCVE.org

ngx_cache_purge before 3.0.4 can allow file deletion via a symlink attack in certain situations where nginx and a served application (e.g., WordPress) run under the same user account. The attacker must be able to create a symlink inside the cache path. Version 3.0.4 fixes this for the case of a symlink created at an arbitrary earlier time, but does not resolve an applicable TOCTOU race condition. (The ngx_cache_purge module follows symlinks while walking the cache directory tree during purge operations. The module relies on nginx's ngx_walk_tree(), which relies on stat() and therefore follows symlinks.)

Threat Intelligence Overview

EPSS Score
0.1%
Top 98% exploitable
Prevalence
Medium
popular third-party nginx caching module, common in nginx/WordPress stacks
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity LOW
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
LOW severity (CVSS 0.1-3.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Defer
Exploitation· derived
None
System Exposure· derived
Small
Automatable· derived
No
Human Impact· derived
Low

Priority Score

18
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +18
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy