T09 · Insecure Skill Coding Practices
- Location
scripts/med_info.py:91- Finding
openFDA API Key Disclosure Through Unredacted HTTP Error Output
- Content
View full analysis
Vulnerability Details
File Location:
scripts/med_info.py:91-110, with related credential handling atscripts/med_info.py:249-255and output propagation atscripts/med_info.py:1796-1805
Vulnerability Type: Sensitive credential exposure in error messages
Risk Level: MediumVulnerable Code
The HTTP helper includes the original, unredacted request URL in exceptions:
python def http_get_json(url: str, headers: Optional[Dict[str, str]] = None, *, allow_404: bool = False) -> Any: _log_url(url) req = urllib.request.Request(url) req.add_header("User-Agent", USER_AGENT) if headers: for k, v in headers.items(): req.add_header(k, v) try: with urllib.request.urlopen(req, timeout=TIMEOUT_S) as resp: data = resp.read() return json.loads(data.decode("utf-8")) except urllib.error.HTTPError as e: if allow_404 and e.code == 404: # openFDA returns 404 when there are no matches. return {"results": []} try: body = e.read().decode("utf-8", errors="replace") except Exception: body = "" raise RuntimeError(f"HTTP {e.code} for {url}: {body[:500]}") from eThe optional API key is embedded in the request URL:
python def openfda_url(path: str, query: str, limit: int = 1) -> str: base = f"https://api.fda.gov{path}.json" params = {"search": query, "limit": str(limit)} api_key = os.environ.get("OPENFDA_API_KEY") if api_key: params["api_key"] = api_key return base + "?" + urllib.parse.urlencode(params)The exception text is then exposed through JSON or console output:
python except Exception as e: out["error"] = str(e) if args.print_url or args.json: out.setdefault("debug", {})["urls"] = URL_LOG if args.json: sys.stdout.write(json.dumps(out, ens ...[truncated 2547 chars]- Remediation
View remediation
Remediation Suggestions
-
Redact the URL before including it in every exception message:
python safe_url = _redact_url(url) raise RuntimeError( f"HTTP {e.code} for {safe_url}: {body[:500]}" ) from e -
Centralize sanitization so logging, normal errors, retry errors, and debug output all use the same safe URL representation.
-
If supported by openFDA, transmit the API key in a request header rather than in the query string. This reduces accidental exposure through URLs, proxies, logs, and exception text.
-
Avoid returning raw upstream response bodies unless needed. Sanitize and constrain error bodies before exposing them to users or automated logs.
-
Add regression tests using a sentinel key, such as
TEST_SECRET_DO_NOT_LOG, and simulate HTTP failures. Assert that the sentinel never appears in:- Raised exception messages
- JSON output
- Human-readable output
- Debug URL logs
- CI or application logs
-
Rotate any openFDA API key that may already have appeared in logs or captured output.
-
