T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/report.py:27
- Finding
- NewsData API Key Is Stored and Exposed in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `scripts/report.py:27-34`, `scripts/report.py:108-112`, and `scripts/report.py:331-350` **Vulnerability Type**: Plaintext secret storage and disclosure **Risk Level**: Medium ### Vulnerable Code ```python def load_config() -> dict: if CONFIG_FILE.exists(): cfg = json.loads(CONFIG_FILE.read_text()) merged = {**DEFAULT_CONFIG, **cfg} return merged return DEFAULT_CONFIG.copy() def save_config(cfg: dict): CONFIG_DIR.mkdir(parents=True, exist_ok=True) CONFIG_FILE.write_text(json.dumps(cfg, indent=2)) ``` ```python def fetch_news(country: str = "us", api_key: str = "") -> dict: """News headlines. Uses NewsData.io if API key provided, else a fallback.""" if api_key: data = api_get(f"https://newsdata.io/api/1/latest?apikey={api_key}&country={country}&language=en&size=5") ``` ```python def cmd_config(city=None, crypto=None, news_country=None, news_key=None, show=False): cfg = load_config() if show: print(json.dumps(cfg, indent=2)) return if city: cfg["city"] = city if crypto: cfg["crypto"] = [c.strip().lower() for c in crypto.split(",")] if news_country: cfg["news_country"] = news_country if news_key: cfg["news_api_key"] = news_key save_config(cfg) print("Configuration updated.") print(json.dumps(cfg, indent=2)) ``` ### Technical Analysis The user-supplied NewsData API key is stored directly in the JSON configuration file under `~/.daily-report/config.json`. The code does not explicitly enforce restrictive permissions on either the configuration directory or file, so effective access depends on the user's environment and process umask. The full configuration is also printed by `config --show` and after every configuration update. Because the configuration includes `news_api_key`, the credential can be exposed through terminal history capture, CI/CD logs, scheduled-job ...[truncated 2214 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Avoid storing the API key in the regular preferences file.** - Read it from a dedicated environment variable such as `NEWSDATA_API_KEY`. - For interactive installations, use an operating-system credential store or secrets manager. 2. **Enforce restrictive permissions if file storage must remain supported.** - Create the configuration directory with mode `0700`. - Create or replace the secret-bearing file with mode `0600`. - Verify and repair existing permissions before reading the credential. - Use an atomic write procedure that preserves restrictive permissions. 3. **Redact secrets from all output.** - Replace `news_api_key` with a value such as `"***REDACTED***"` in `config --show`. - Do not print the full configuration after an update. - Display only the names of changed non-secret settings or indicate that a key is configured. 4. **Improve transport-level secret handling.** - Prefer a provider-supported authorization header instead of a URL query parameter. - If NewsData requires a query parameter, ensure request URLs are never written to application logs, exceptions, tracing systems, or telemetry. - Keep HTTPS certificate verification enabled. 5. **Support credential rotation.** - Document how users can revoke and replace a potentially exposed NewsData key. - Recommend rotating any key that has already appeared in shared terminal, CI, or cron logs. ]]>
