Skip to content

fix(redis): match the key prefix and clear_path path literally in SCAN - #139

Merged
allen0099 merged 1 commit into
masterfrom
fix/redis-scan-escaping
Sep 25, 2026
Merged

allen0099 merged 1 commit into
masterfrom
fix/redis-scan-escaping

Conversation

@allen0099

Copy link
Copy Markdown
Owner

Closes #106

Problem

AsyncRedisCacheBackend built its SCAN MATCH patterns by interpolating key_prefix and the clear_path() path directly, so glob metacharacters in them were live:

  • clear_path("/files/[draft]") read [draft] as a character class and missed the cached HTTP entry for that path. The memory backend cleared it.
  • A key_prefix containing ? or * let clear(), get_all_keys() (and so get_cache_data()) and clear_pattern() reach keys under other prefixes on the same server.

Change

  • New _escape_glob() backslash-escapes *?[]\ for Redis glob patterns.
  • The key prefix is escaped in clear, get_all_keys, clear_path and clear_pattern.
  • The path is escaped in clear_path.
  • clear_pattern(pattern) now always builds the pattern as escaped prefix + pattern. A pattern that already repeats the prefix has it stripped first, so both call forms keep working. Only the caller's pattern stays a live glob.
  • The Redis section of docs/BACKENDS.md gains a note on this, and there is a CHANGELOG entry under Fixed.

Not breaking.

Out of scope

CacheManager.clear_pattern() still puts its own key_prefix (cache: by default) into the pattern it hands to the backend, so glob characters in a custom manager prefix remain live. The escaping syntax differs per backend (Redis uses backslashes, the memory backend's fnmatch uses [*]), so fixing that needs its own design.

Tests

The new live Redis tests in tests/backends/test_redis.py fail on the old code and pass with this change:

  • clear_path on a path containing []*?\ removes its exact and query-param entries and leaves look-alike keys that the unescaped pattern would have matched.
  • A backend with prefix cachex-test?*: does not list or delete keys of a cachex-testX-other: backend through get_all_keys, clear_pattern (with and without the prefix) or clear.

Full suite with live Redis and Memcached: 761 passed. The docs build passes with --strict.

SCAN MATCH patterns interpolated key_prefix and the clear_path path raw, so
glob characters in them were live: clear_path("/files/[draft]") missed the
entry for that path, and a prefix with ? or * reached other prefixes' keys.
Escape *?[]\ in both; only the clear_pattern argument stays a glob.

Closes #106
@allen0099
allen0099 merged commit 393996f into master Sep 25, 2026
10 checks passed
@allen0099
allen0099 deleted the fix/redis-scan-escaping branch September 26, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redis SCAN patterns do not escape the key prefix or path

1 participant