#1152665 trixie-pu: package libnginx-mod-http-cache-purge/1:2.5.3-3+deb13u1

#1152665#5
Date:
2026-10-31 05:25:50 UTC
From:
To:
[ Reason ]
This update backports the upstream fix for CVE-2026-108981
https://bugs.debian.org/1151200

Full and wildcard cache purges follow directory symlinks inside the
cache tree. A symlink pointing outside the cache directory can therefore
cause a purge to delete files outside that directory, subject to the
nginx worker's filesystem permissions.

[ Impact ]
Without this update, affected installations remain exposed to unintended
deletion of files outside the configured cache directory.

[ Tests ]
The upstream fix adds Test::Nginx regression tests for full purges and
empty-prefix wildcard purges, checking that files outside the cache tree
remain intact. Those tests were not included in this backport because
the newer t/basic.t test suite is not present in version 2.5.3.

[ Risks ]
The change is small and limited to the two recursive purge walks present
in version 2.5.3. It adds a pre-descent check using ngx_link_info()
(lstat), skips directory symlinks and logs a warning. Directories whose
metadata cannot be read are also skipped, with an error logged.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
* Add debian/patches/CVE-2026-108981.patch, backporting upstream commit
  a6da1352f52a8a02dd6828e88c39ed42fddcee96.



diff -Nru libnginx-mod-http-cache-purge-2.5.3/debian/changelog libnginx-mod-http-cache-purge-2.5.3/debian/changelog
--- libnginx-mod-http-cache-purge-2.5.3/debian/changelog	2025-04-11 12:26:56.000000000 +0000
+++ libnginx-mod-http-cache-purge-2.5.3/debian/changelog	2026-10-20 19:23:58.000000000 +0000
@@ -1,3 +1,11 @@
+libnginx-mod-http-cache-purge (1:2.5.3-3+deb13u1) trixie; urgency=high
+
+  * d/p/CVE-2026-108981.patch: backport upstream fix to skip directory
+    symlinks during full and wildcard cache purges, preventing deletion of
+    files outside the cache directory (CVE-2026-108981).
+
+ -- Jan Mojžíš <janmojzis@debian.org>  Tue, 20 Oct 2026 21:23:58 +0200
+
 libnginx-mod-http-cache-purge (1:2.5.3-3) unstable; urgency=medium

   * d/control: update my email to janmojzis@debian.org
diff -Nru libnginx-mod-http-cache-purge-2.5.3/debian/patches/CVE-2026-108981.patch libnginx-mod-http-cache-purge-2.5.3/debian/patches/CVE-2026-108981.patch
--- libnginx-mod-http-cache-purge-2.5.3/debian/patches/CVE-2026-108981.patch	1970-01-01 00:00:00.000000000 +0000
+++ libnginx-mod-http-cache-purge-2.5.3/debian/patches/CVE-2026-108981.patch	2026-10-20 19:23:58.000000000 +0000
@@ -0,0 +1,120 @@
+From a6da1352f52a8a02dd6828e88c39ed42fddcee96 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Hasan=20=C3=87ALI=C5=9EIR?= <hasan.calisir@psauxit.com>
+Date: Sat, 10 Oct 2026 18:22:46 +0300
+Subject: [PATCH] ngx_cache_purge: prevent symlink traversal during cache tree
+ walks (#72)
+Origin: upstream, https://github.com/nginx-modules/ngx_cache_purge/commit/a6da1352f52a8a02dd6828e88c39ed42fddcee96
+Bug: https://github.com/nginx-modules/ngx_cache_purge/pull/72
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-108981
+Last-Update: 2026-10-20
+
+Fix a security vulnerability where cache purge operations (purge_all,
+wildcard, vary-aware exact, and background queue) follow symbolic links
+planted inside the cache directory, allowing arbitrary file deletion
+outside the cache path.
+
+Root cause:
+All four purge walks rely on ngx_walk_tree(), which classifies directory
+entries using stat() via ngx_de_info() and therefore follows symbolic links.
+A "dir -> /elsewhere" link inside the cache path was treated as a real
+directory and walked recursively.
+
+Fix:
+Implement ngx_http_purge_file_cache_pre_tree() and use it as the
+pre_tree_handler for all walks. Use ngx_link_info() (lstat) to inspect
+directories before descent, skip symbolic links, and log a warning.
+
+Add Test::Nginx regression test cases (TEST 25 for purge_all and TEST 26
+for empty-prefix wildcard purge) to t/basic.t to ensure that purge
+operations skip planted symbolic links and do not delete target files
+outside the cache directory.
+
+
+Debian trixie backport notes:
+
+Backported to 2.5.3: adjust the declaration and surrounding context, and
+update the two existing tree walks (purge_all and wildcard/partial).
+The vary-aware exact and background queue walks do not exist in 2.5.3.
+Omit the t/basic.t changes because that newer test suite is not present
+in 2.5.3.
+
+As in upstream, this prevents traversal of pre-existing directory symlinks;
+the TOCTOU race between lstat() and opendir() remains unresolved.
+---
+ ngx_cache_purge_module.c | 39 +++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/ngx_cache_purge_module.c b/ngx_cache_purge_module.c
+index 251d3fed0dd05abcb8406d1db9fb91a70afa0c8a..685cac6eb72ba8211393ac0d3a2dc9aa9404dd0c 100644
+--- a/ngx_cache_purge_module.c
++++ b/ngx_cache_purge_module.c
+@@ -122,6 +122,8 @@ char        *ngx_http_cache_purge_response_type_conf(ngx_conf_t *cf,
+ static ngx_int_t
+ ngx_http_purge_file_cache_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path);
+ static ngx_int_t
++ngx_http_purge_file_cache_pre_tree(ngx_tree_ctx_t *ctx, ngx_str_t *path);
++static ngx_int_t
+ ngx_http_purge_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path);
+
+ ngx_int_t   ngx_http_cache_purge_access_handler(ngx_http_request_t *r);
+@@ -1301,6 +1303,39 @@ ngx_http_purge_file_cache_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) {
+     return NGX_OK;
+ }
+
++/*
++ * pre_tree_handler: never descend into a symbolic link found inside the
++ * cache tree.
++ *
++ * ngx_walk_tree() classifies every directory entry with stat(), which
++ * follows symbolic links, so a planted "dir -> /elsewhere" link would be
++ * walked (and its files purged) as if it were a real cache directory.
++ * nginx itself only ever creates regular directories and files in a cache
++ * path, therefore any symbolic link below the cache root is foreign and is
++ * skipped.  The cache root itself is not passed to this handler, so a
++ * cache path that is a symbolic link keeps working.
++ */
++static ngx_int_t
++ngx_http_purge_file_cache_pre_tree(ngx_tree_ctx_t *ctx, ngx_str_t *path)
++{
++    ngx_file_info_t  fi;
++
++    if (ngx_link_info(path->data, &fi) == NGX_FILE_ERROR) {
++        ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
++                      ngx_link_info_n " \"%V\" failed", path);
++        return NGX_DECLINED;
++    }
++
++    if (ngx_is_link(&fi)) {
++        ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
++                      "ngx_cache_purge: skipping symbolic link in cache "
++                      "tree \"%V\"", path);
++        return NGX_DECLINED;
++    }
++
++    return NGX_OK;
++}
++
+ static ngx_int_t
+ ngx_http_purge_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) {
+     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
+@@ -1791,7 +1826,7 @@ ngx_http_cache_purge_all(ngx_http_request_t *r, ngx_http_file_cache_t *cache) {
+     ngx_tree_ctx_t  tree;
+     tree.init_handler = NULL;
+     tree.file_handler = ngx_http_purge_file_cache_delete_file;
+-    tree.pre_tree_handler = ngx_http_purge_file_cache_noop;
++    tree.pre_tree_handler = ngx_http_purge_file_cache_pre_tree;
+     tree.post_tree_handler = ngx_http_purge_file_cache_noop;
+     tree.spec_handler = ngx_http_purge_file_cache_noop;
+     tree.data = NULL;
+@@ -1824,7 +1859,7 @@ ngx_http_cache_purge_partial(ngx_http_request_t *r, ngx_http_file_cache_t *cache
+     ngx_tree_ctx_t  tree;
+     tree.init_handler = NULL;
+     tree.file_handler = ngx_http_purge_file_cache_delete_partial_file;
+-    tree.pre_tree_handler = ngx_http_purge_file_cache_noop;
++    tree.pre_tree_handler = ngx_http_purge_file_cache_pre_tree;
+     tree.post_tree_handler = ngx_http_purge_file_cache_noop;
+     tree.spec_handler = ngx_http_purge_file_cache_noop;
+     tree.data = key_partial;
+--
+2.47.3
+
diff -Nru libnginx-mod-http-cache-purge-2.5.3/debian/patches/series libnginx-mod-http-cache-purge-2.5.3/debian/patches/series
--- libnginx-mod-http-cache-purge-2.5.3/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
+++ libnginx-mod-http-cache-purge-2.5.3/debian/patches/series	2026-10-20 19:23:58.000000000 +0000
@@ -0,0 +1 @@
+CVE-2026-108981.patch