T09 · Insecure Skill Coding Practices
- Location
scripts/chain_analyzer.py:75- Finding
Unsafe Deserialization of Local Option-Chain Cache Files
- Content
View full analysis
str: """Get cache file path""" return os.path.join(self.cache_dir, f"{cache_key}.pkl") def _load_from_cache(self, cache_key: str) -> Optional[Dict]: """Load data from cache if valid""" cache_path = self._get_cache_path(cache_key) if not os.path.exists(cache_path): return None try: with open(cache_path, 'rb') as f: cached = pickle.load(f) # Check TTL if time.time() - cached.get('timestamp', 0) > self.cache_ttl: return None return cached.get('data') except (FileNotFoundError, PermissionError, pickle.PickleError, IOError): return None def _save_to_cache(self, cache_key: str, data: Dict): """Save data to cache""" cache_path = self._get_cache_path(cache_key) try: with open(cache_path, 'wb') as f: pickle.dump({'timestamp': time.time(), 'data': data}, f) except (FileNotFoundError, PermissionError, pickle.PickleError, IOError) as e: logger.warning(f"Failed to save cache: {e}") ``` ### Technical Analysis Python pickle is an executable serialization format. During `pickle.load()`, serialized reduction instructions can import modules and invoke arbitrary callables. Consequently, validity checks performed after deserialization, including the cache timestamp check, cannot protect against a malicious payload because code execution occurs while the file is being loaded. The cache is persistent under `~/.openclaw/options_cache` by default, and cache filenames are derived from ticker-based cache keys. `ChainFetcher` does not independently validate those keys before constructing paths. Although `quant_scanner.py` validates tickers in one CLI path, `ChainFetch ...[truncated 1563 chars]- Remediation
View remediation
