High severityNVD Advisory· Published Aug 1, 2025· Updated Aug 4, 2025
Copyparty is vulnerable to Regex Denial of Service (ReDoS) attacks through "Recent Uploads" page
CVE-2025-54796
Description
Copyparty is a portable file server. Versions prior to 1.18.9, the filter parameter for the "Recent Uploads" page allows arbitrary RegExes. If this feature is enabled (which is the default), an attacker can craft a filter which deadlocks the server. This is fixed in version 1.18.9.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
copypartyPyPI | < 1.18.9 | 1.18.9 |
Affected products
1Patches
12 files changed · +37 −9
copyparty/httpcli.py+22 −9 modified@@ -107,6 +107,7 @@ sendfile_py, set_fperms, stat_resource, + str_anchor, ub64dec, ub64enc, ujoin, @@ -5369,9 +5370,9 @@ def tx_ups(self) -> bool: raise Pebkac(500, "sqlite3 not found on server; unpost is disabled") raise Pebkac(500, "server busy, cannot unpost; please retry in a bit") - zs = self.uparam.get("filter") or "" - filt = re.compile(zs, re.I) if zs else None - lm = "ups %r" % (zs,) + sfilt = self.uparam.get("filter") or "" + nfi, vfi = str_anchor(sfilt) + lm = "ups %d%r" % (nfi, sfilt) if self.args.shr and self.vpath.startswith(self.args.shr1): shr_dbv, shr_vrem = self.vn.get_dbv(self.rem) @@ -5431,8 +5432,14 @@ def tx_ups(self) -> bool: q = "select sz, rd, fn, at from up where ip=? and at>? order by at desc" for sz, rd, fn, at in cur.execute(q, (self.ip, lim)): vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) - if filt and not filt.search(vp): - continue + if nfi == 0 or (nfi == 1 and vfi in vp): + pass + elif nfi == 2: + if not vp.startswith(vfi): + continue + elif nfi == 3: + if not vp.endswith(vfi): + continue n -= 1 if not n: @@ -5513,8 +5520,8 @@ def tx_rups(self) -> bool: raise Pebkac(500, "server busy, cannot list recent uploads; please retry") sfilt = self.uparam.get("filter") or "" - filt = re.compile(sfilt, re.I) if sfilt else None - lm = "ru %r" % (sfilt,) + nfi, vfi = str_anchor(sfilt) + lm = "ru %d%r" % (nfi, sfilt) self.log(lm) ret: list[dict[str, Any]] = [] @@ -5549,8 +5556,14 @@ def tx_rups(self) -> bool: q = "select sz, rd, fn, ip, at from up where at>0 order by at desc" for sz, rd, fn, ip, at in cur.execute(q): vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) - if filt and not filt.search(vp): - continue + if nfi == 0 or (nfi == 1 and vfi in vp): + pass + elif nfi == 2: + if not vp.startswith(vfi): + continue + elif nfi == 3: + if not vp.endswith(vfi): + continue if not dots and "/." in vp: continue
copyparty/util.py+15 −0 modified@@ -2396,6 +2396,21 @@ def ujoin(rd: str, fn: str) -> str: return rd or fn +def str_anchor(txt) -> tuple[int, str]: + if not txt: + return 0, "" + txt = txt.lower() + a = txt.startswith("^") + b = txt.endswith("$") + if not b: + if not a: + return 1, txt # ~ + return 2, txt[1:] # ^ + if not a: + return 3, txt[:-1] # $ + return 4, txt[1:-1] # ^$ + + def log_reloc( log: "NamedLogger", re: dict[str, str],
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-5662-2rj7-f2v6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-54796ghsaADVISORY
- github.com/9001/copyparty/commit/09910ba80784c3980947d92f45db696398c0fd83ghsax_refsource_MISCWEB
- github.com/9001/copyparty/releases/tag/v1.18.9ghsax_refsource_MISCWEB
- github.com/9001/copyparty/security/advisories/GHSA-5662-2rj7-f2v6ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.