T09 · Insecure Skill Coding Practices
- Location
lib/token_manager.py:139- Finding
Token caching cannot actually be disabled
- Content
View full analysis
Vulnerability Details
File Location:
lib/token_manager.py, lines 139-170 and 220-232
Vulnerability Type: Security control bypass resulting in persistent plaintext bearer-token storage
Risk Level: MediumTechnical Analysis
The
EZVIZ_TOKEN_CACHE=0setting only prevents reading an existing token from the cache. On a cache miss—or whenever caching is explicitly disabled—get_cached_token()still invokesrefresh_token(), which unconditionally loads and writes the global token cache.Relevant code:
python # Check environment variable for cache override if use_cache is None: env_cache = os.environ.get("EZVIZ_TOKEN_CACHE", "1").strip().lower() use_cache = (env_cache not in ["0", "false", "no", "disable"]) cache_key = generate_cache_key(app_key, app_secret) # Try to load from cache first if use_cache: all_cache = load_token_cache() if cache_key in all_cache: cached = all_cache[cache_key] expire_time = cached.get("expire_time", 0) current_time = get_current_timestamp() if current_time + TOKEN_BUFFER_TIME < expire_time: return { "success": True, "access_token": cached["access_token"], "expire_time": expire_time, "from_cache": True } # Cache miss or expired, get new token return refresh_token(app_key, app_secret, cache_key)The refresh path then writes the token regardless of the selected cache policy:
python # Save to global cache all_cache = load_token_cache() all_cache[cache_key] = { "cache_key": cache_key, "access_token": access_token, "expire_time": expire_time, "created_at": get_current_timestamp(), "app_key_prefix": app_key[:8] + "..." if len(app_key) > 8 else app_key } if save_token_cache(all_cache): print(f"[INFO] Token saved to global cache")This directly contra ...[truncated 1807 chars]
- Remediation
View remediation
Remediation Suggestions
Propagate the selected cache policy into the refresh operation and completely skip cache reads and writes when caching is disabled. For example:
python def get_cached_token(app_key, app_secret, use_cache=None): if use_cache is None: value = os.environ.get("EZVIZ_TOKEN_CACHE", "1").strip().lower() use_cache = value not in {"0", "false", "no", "disable"} cache_key = generate_cache_key(app_key, app_secret) if use_cache: # Perform the existing cache lookup. ... return refresh_token( app_key, app_secret, cache_key=cache_key, save_to_cache=use_cache, ) def refresh_token(app_key, app_secret, cache_key=None, save_to_cache=True): ... if save_to_cache: all_cache = load_token_cache() all_cache[cache_key] = { "cache_key": cache_key, "access_token": access_token, "expire_time": expire_time, "created_at": get_current_timestamp(), } save_token_cache(all_cache)Add an automated test that sets
EZVIZ_TOKEN_CACHE=0, performs a mocked successful refresh, and verifies that neither the cache directory nor cache file is created. Remove any previously cached token when an operator switches to no-cache mode, or clearly document that existing entries must be cleared separately.
