T09 · Insecure Skill Coding Practices
- Location
main.py:272- Finding
User-Controlled Cache Path Allows Arbitrary File Overwrite
- Content
View full analysis
None: if not path: return try: with open(path, "w", encoding="utf-8") as f: json.dump(cache, f, ensure_ascii=False, indent=2) except Exception: return ``` ```python cache_path = location.get("cache_path") or DEFAULT_CACHE_PATH provider = location.get("lookup_provider") or DEFAULT_LOOKUP_PROVIDER key = location.get("lookup_key") or os.environ.get("BAZI_GEOCODE_KEY", "") timeout = location.get("lookup_timeout", DEFAULT_LOOKUP_TIMEOUT) try: timeout = float(timeout) except Exception: timeout = DEFAULT_LOOKUP_TIMEOUT norm = normalize_city_name(name) global _CITY_INDEX if _CITY_INDEX is None or lookup_path != DEFAULT_CITY_MAP_PATH: _CITY_INDEX = build_city_index(load_city_map(lookup_path)) if lookup_mode in ("local", "auto"): if norm in _CITY_INDEX: lon, lat, canonical = _CITY_INDEX[norm] return lon, lat, canonical cache = load_cache(cache_path) if norm in cache: try: lon, lat = cache[norm]["longitude"], cache[norm]["latitude"] return float(lon), float(lat), cache[norm].get("name", norm) except Exception: pass if lookup_mode in ("online", "auto"): try: coords = geocode_online(name, provider, key, timeout) except Exception: coords = None if coords: lon, lat = coords cache[norm] = {"longitude": lon, "latitude": lat, "name": name} save_cache(cache_path, cache) ``` ### Technical Analysis The `location.cache_path` field comes directly from the JSON payload and is passed to `save_cache()` without path validation, directory confinement, ownership checks, or symbolic-link protection. The sink opens the selected path in write mode, which t ...[truncated 2327 chars]- Remediation
View remediation
