
Cloud Vulnerability DB
A community-led vulnerabilities database
With default flags, a pattern that contains several * wildcards takes polynomial time, O(n^k) for k stars, to reject a crafted file name. The pattern is an ordinary developer constant such as *_*_*_*_*.csv; only the string being matched comes from the attacker. A 255-byte file name (the maximum on common filesystems) takes 73 s with fnmatch.fnmatch() and 86 s with glob.globmatch(). The standard library's fnmatch handles the same input in under a millisecond.
This is different from GHSA-84v8-qmgq-9g88: that advisory covers extglob patterns, while this case needs no flags and no attacker-controlled pattern.
Every * is translated to a lazy .*? (_STAR, wcmatch/_wcparse.py:212; _PATH_STAR [^/]*?, :218), which is emitted in _handle_star (:1405-1424):
*_*_*_*_*.csv -> ^(?s:(?=.)(?![.]).*?_.*?_.*?_.*?_.*?\.csv)$When the subject consists of many _ and does not end in .csv, the regex engine tries every way of splitting it between the stars. CPython fixed the same problem in its own fnmatch (bpo-40480) by making every star segment except the last one atomic.
import time, fnmatch as std
from wcmatch import fnmatch, glob
for pat, n in [('*_*_*_*.csv', 255), ('*_*_*_*.csv', 400), ('*_*_*_*_*.csv', 150),
('*_*_*_*_*.csv', 200), ('*_*_*_*_*.csv', 255)]:
name = '_' * n
t = time.perf_counter(); fnmatch.fnmatch(name, pat); w = time.perf_counter() - t
t = time.perf_counter(); std.fnmatchcase(name, pat); s = time.perf_counter() - t
print(f'{pat:15} len={n} wcmatch={w:.3f}s stdlib={s:.5f}s')
t = time.perf_counter(); glob.globmatch('uploads/' + '_' * 255, 'uploads/*_*_*_*_*.csv')
print(f'globmatch {time.perf_counter() - t:.2f}s')wcmatch 11.1, CPython 3.13, macOS:
*_*_*_*.csv len=255 wcmatch=1.412s stdlib=0.00001s
*_*_*_*.csv len=400 wcmatch=8.599s stdlib=0.00004s
*_*_*_*_*.csv len=150 wcmatch=5.333s stdlib=0.00003s
*_*_*_*_*.csv len=200 wcmatch=22.415s stdlib=0.00007s
*_*_*_*_*.csv len=255 wcmatch=72.732s stdlib=0.00047s
globmatch 85.75sglob.glob('*_*_*_*.csv', root_dir=d) on a real directory that contains one file named '_' * 255 takes 1.7 s.
Applications that match untrusted names against multi-star patterns can be blocked on a single CPU core for minutes per name. Examples: upload handlers, archive or object-store key filters, and glob/WcMatch scans of directories where other users can create files. No authentication is needed.
Emit every star segment except the last one as an atomic group, as the standard library does. On Python 3.11 and later use (?>.*?_); on 3.10 use the lookahead/backreference form from fnmatch._join_translated_parts. For example:
^(?s:(?=.)(?![.])(?>.*?_)(?>.*?_)(?>.*?_)(?>.*?_).*?\.csv)$This rejects the 255-byte name in under 1 ms. On my spot-check inputs it gives the same results as the current regex. The same change applies to _PATH_STAR.
Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."