T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/cache_manager.py:130- Finding
Redis Key Enumeration Bypasses the Enforced Namespace
- Content
View full analysis
list[str]: if not pattern.startswith(KEY_PREFIX) and "*" not in pattern: pattern = f"{KEY_PREFIX}*" if pattern == "*" else f"{KEY_PREFIX}*{pattern}*" r = _client() try: return list(r.scan_iter(match=pattern, count=count)) except redis.RedisError as e: raise CacheError(str(e)) ``` ### Technical Analysis The function intends to constrain key enumeration to the `mema:` namespace. However, prefix normalization only occurs when the supplied pattern both lacks the `mema:` prefix and contains no `*` wildcard. Consequently, any pattern containing `*` bypasses namespace enforcement. This includes the default pattern `"*"`, as well as attacker-controlled values such as `other:*` or `session:*`. These patterns are passed directly to Redis through `scan_iter(match=pattern)`, allowing the caller to enumerate key names outside the namespace assigned to this Skill. This behavior contradicts the documented requirement to strictly enforce the `mema:` prefix. Although the affected command does not directly retrieve the values of non-`mema:` keys, Redis key names can disclose application structure, tenant identifiers, session identifiers, service names, or other sensitive metadata. Materializing the complete iterator as a list also increases memory-consumption risk when a broad pattern matches a large database. ### Attack Path 1. The attacker or untrusted caller obtains permission to invoke the cache manager against a Redis database shared with other applications. 2. The caller runs one of the following commands: ```bash python3 scripts/cache_manager.py scan '*' ``` or: ```bash python3 scripts/cache_manager.py scan 'other:*' ``` 3. `scan_keys()` detects ...[truncated 1093 chars]- Remediation
View remediation
1000: raise KeyValidationError("Count must be between 1 and 1000") if pattern == "*": pattern = f"{KEY_PREFIX}*" elif not pattern.startswith(KEY_PREFIX): raise KeyValidationError(f"Scan pattern must start with {KEY_PREFIX}") r = _client() try: return r.scan_iter(match=pattern, count=count) except redis.RedisError as e: raise CacheError(str(e)) ``` Additional hardening measures: 1. Reject every caller-supplied scan pattern that does not begin with the literal `mema:` prefix. 2. Convert the default `"*"` pattern explicitly to `mema:*`. 3. Stream results from `scan_iter()` instead of converting the entire iterator to a list. 4. Place this Skill in a dedicated Redis logical database or, preferably, a separate Redis instance. 5. Configure a Redis ACL user restricted to the required `mema:*` key pattern and necessary commands. 6. Add tests covering `"*"`, `other:*`, `*:suffix`, empty patterns, and valid `mema:*` patterns. ]]>
