Problem
CacheManager.clear_pattern(pattern) builds self.key_prefix + pattern and passes the result to backend.clear_pattern() as a glob. Glob metacharacters in the manager's own key_prefix are therefore live:
CacheManager(key_prefix="cache[1]:").clear_pattern("*") does not match the manager's own keys, because [1] is read as a character class.
CacheManager(key_prefix="a?:").clear_pattern("*") also clears keys of a manager whose prefix is ab:.
clear() and clear_prefix() are not affected: they filter get_all_keys() with plain string matching.
The backend's own key prefix is already matched literally on Redis (#106). This issue covers only the manager-level prefix. It is a correctness issue, not a security one: key_prefix is set by the developer, not by a request.
Why this is not a one-line fix
Escaping syntax differs per backend. Redis globs use backslashes (\*). The memory backend uses fnmatch, which has no backslash escape and needs [*]. CacheManager does not know which backend it is talking to.
Options
- Add a non-abstract
escape_pattern(text) -> str to BaseCacheBackend, overridden by Redis and memory, and use it in CacheManager.clear_pattern. This is clean and keeps server-side SCAN MATCH filtering, but it adds public backend surface.
- Implement
CacheManager.clear_pattern as get_all_keys(), then keep the keys that start with key_prefix and whose remainder fnmatches pattern, then delete_many(). This needs no backend change, but Redis loses server-side filtering and fnmatch semantics differ slightly from Redis globs.
Low priority: it only bites with an unusual key_prefix. Not breaking under either option.
Problem
CacheManager.clear_pattern(pattern)buildsself.key_prefix + patternand passes the result tobackend.clear_pattern()as a glob. Glob metacharacters in the manager's ownkey_prefixare therefore live:CacheManager(key_prefix="cache[1]:").clear_pattern("*")does not match the manager's own keys, because[1]is read as a character class.CacheManager(key_prefix="a?:").clear_pattern("*")also clears keys of a manager whose prefix isab:.clear()andclear_prefix()are not affected: they filterget_all_keys()with plain string matching.The backend's own key prefix is already matched literally on Redis (#106). This issue covers only the manager-level prefix. It is a correctness issue, not a security one:
key_prefixis set by the developer, not by a request.Why this is not a one-line fix
Escaping syntax differs per backend. Redis globs use backslashes (
\*). The memory backend usesfnmatch, which has no backslash escape and needs[*].CacheManagerdoes not know which backend it is talking to.Options
escape_pattern(text) -> strtoBaseCacheBackend, overridden by Redis and memory, and use it inCacheManager.clear_pattern. This is clean and keeps server-sideSCAN MATCHfiltering, but it adds public backend surface.CacheManager.clear_patternasget_all_keys(), then keep the keys that start withkey_prefixand whose remainderfnmatchespattern, thendelete_many(). This needs no backend change, but Redis loses server-side filtering andfnmatchsemantics differ slightly from Redis globs.Low priority: it only bites with an unusual
key_prefix. Not breaking under either option.