Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessGain code execution as the shared nginx/app user
-
DeliveryPlant symlink inside proxy_cache_path
-
ExploitTrigger cache purge (e.g. PURGE request)
-
Executionngx_walk_tree stat() follows the symlink
-
ImpactFiles 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. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – 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
Affected Packages
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
AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
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).
Primary rating from Vendor (mitre).
CVSS VectorVendor: mitre
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
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.
EUVD-2026-97159
GHSA-5fhq-3m7h-fqv8
NVD
CVE.org
EPSS
VulDB
Exploit-DB