T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/bokatvattid.py:34
- Finding
- Authentication Token Disclosure Through Debug Logging<![CDATA[ ## Vulnerability Details **File Location**: `scripts/bokatvattid.py`, lines 34–45 **Vulnerability Type**: Sensitive session token exposure through debug output **Risk Level**: Medium ### Vulnerable Code ```python def _post(url, params): # Form-encoded POST: credentials stay in the request body, never in a URL # (query strings end up in server/proxy access logs; bodies normally do not). body = urllib.parse.urlencode(params).encode("utf-8") req = urllib.request.Request(url, data=body, method="POST", headers={"Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded"}) with urllib.request.urlopen(req, timeout=20) as r: d = json.loads(r.read().decode("utf-8")) if os.environ.get("BOKA_DEBUG"): print(json.dumps(d, ensure_ascii=False)[:2000], file=sys.stderr) return d ``` The affected function is used by the authentication flow at lines 137–143: ```python def login(pin, building, apartment): d = _post(LEGACY, {"method": "checkLogin2", "buildingid": building, "pincode": pin, "apartmentnumber": apartment, "lang": "1"}) if d.get("error") not in (0, "0"): raise BokaError("Inloggning misslyckades: %s (fel PIN/lägenhet?)" % d.get("message", "")) b = d["body"] return b["Token"], str(b["ApartmentID"]) ``` ### Technical Analysis The generic `_post()` function serializes and prints the raw decoded server response whenever the `BOKA_DEBUG` environment variable contains any nonempty value. This function also processes the `checkLogin2` authentication response, whose body contains the authenticated session token and apartment identifier. Although the PIN is placed in the HTTPS request body rather than the URL, the resulting session token is subsequently exposed through stderr. Stderr may be captured by terminal recorders, CI systems, agent runtimes, process supervisors, or centr ...[truncated 2064 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never log raw authentication responses. Suppress response-body logging entirely for `checkLogin2` and any other method returning credentials. 2. Implement recursive redaction before logging. At minimum, redact case-insensitive keys such as `Token`, `token`, `pincode`, `pin`, `userid`, `ApartmentID`, and `apartmentnumber`. 3. Prefer an allowlist-based debug format that logs only non-sensitive fields such as the HTTP endpoint hostname, API method, status, error code, and response shape. 4. Parse the debug flag explicitly so only intentional values enable it: ```python DEBUG = os.environ.get("BOKA_DEBUG", "").strip().lower() in {"1", "true", "yes"} ``` 5. Avoid printing complete booking or account response objects when debugging. Apply the same redaction policy to both `_post()` and `_get()` to prevent future endpoints from introducing similar disclosures. 6. Add automated tests that use representative authentication responses and assert that tokens, PINs, apartment identifiers, and user IDs never appear in captured stdout or stderr. 7. Document that debug output is sanitized and ensure operational logging systems apply restricted access, short retention periods, and secret-scanning controls. ]]>
