T09 · Insecure Skill Coding Practices
Error
- Location
- hot_cache.py:25
- Finding
- Arbitrary JSON File Access Through Agent ID Path Traversal## Vulnerability Details **File Location**: `hot_cache.py:25-105` **Vulnerability Type**: Path traversal leading to arbitrary file read, overwrite, and deletion **Risk Level**: High ```python def _file_path(agent_id: str) -> Path: return CACHE_DIR / f"{agent_id}.json" def _load(agent_id: str) -> list: path = _file_path(agent_id) if path.exists(): try: return json.load(open(path)) except: return [] return [] def _save(agent_id: str, entries: list): json.dump( entries, open(_file_path(agent_id), 'w'), indent=2, ensure_ascii=False ) def clear_agent(agent_id: str): """Clear the HOT cache for an agent.""" path = _file_path(agent_id) if path.exists(): path.unlink() return True return False ``` ### Technical Analysis The externally supplied `agent_id` is interpolated directly into a filesystem path. The code does not restrict path separators, traversal components such as `..`, or absolute paths. `pathlib` therefore permits the resulting path to escape `~/.agent-mem/hot_cache`. The unsafe path is used by three security-sensitive operations: - `_load()` reads and parses the selected JSON file. - `_save()` opens the selected file in write mode and replaces its contents. - `clear_agent()` deletes the selected file. Although the `.json` suffix limits the immediately reachable filenames, it does not prevent access to sensitive JSON files elsewhere in the account. The CLI exposes these operations through attacker-controlled `--agent` values. ### Attack Path 1. An attacker obtains the ability to invoke the HOT-cache CLI or an application endpoint that passes an agent identifier to these functions. 2. The attacker supplies an agent identifier containing an absolute path or traversal components, for example `../../other-directory/config`. 3. `_file_path()` const ...[truncated 820 chars]
- Remediation
- ## Remediation Suggestions - Validate agent identifiers against a strict allowlist such as `^[A-Za-z0-9_-]{1,64}$`. - Reject absolute paths, path separators, `.` components, and `..` components. - Resolve the destination and verify containment before every operation: ```python import re AGENT_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{1,64}$") def _file_path(agent_id: str) -> Path: if not AGENT_ID_PATTERN.fullmatch(agent_id): raise ValueError("Invalid agent ID") base = CACHE_DIR.resolve() path = (base / f"{agent_id}.json").resolve() if path.parent != base: raise ValueError("Cache path escapes the cache directory") return path ``` - Use atomic writes through a temporary file created inside `CACHE_DIR`, followed by `os.replace()`. - Create cache files with restrictive permissions such as `0600`. - Apply authorization checks so callers can access only their permitted agent IDs. - Add regression tests covering absolute paths, nested paths, URL-encoded separators, and `../` traversal.
