Skip to content

security: stop credential leaks in logs, restrict API hosts, remove dead private key - #69

Open
Sylph wants to merge 2 commits into
hasscc:mainfrom
Sylph:pr/security
Open

Sylph wants to merge 2 commits into
hasscc:mainfrom
Sylph:pr/security

Conversation

@Sylph

@Sylph Sylph commented Oct 20, 2026

Copy link
Copy Markdown

Why

Static security review of this integration surfaced four credential/network issues, all fixed here with tests. The most concrete: the request_api entity service accepts any absolute URL (api_url() returned it as-is), and every request attaches the session token — so any automation (or anyone who can call services) could make Home Assistant POST your CatLink session token to a third-party server and echo the response back (throw: true). Combined with params-dict mutation, the token also leaked into every device-action log line.

What

  1. api_url() host allowlist — https only, host must be an official *.catlinks.cn domain or the user-configured api_base host. Relative paths (every internal call site) behave exactly as before.
  2. request() no longer mutates the caller's params dict — it previously injected token/sign/noncestr in place, so every device command that logs its params ([rdt, pms] in devices/base, litterbox, c08, feeder, purepro) wrote the live session token to the HA log.
  3. Credential-safe logging — failed-login log no longer dumps the (encrypted) password params; request-failure log no longer dumps token-bearing params; API response debug log prints returnCode only, not full bodies.
  4. Removed RSA_PRIVATE_KEY from const.py — dead code, nothing references it, but a private key committed to a public repo is a red flag for anyone scanning the codebase.
  5. README — replaced the wget -O - https://get.hacs.vip | ... bash - install methods (remote code execution) with release-download instructions, plus a note warning against the old pattern.

Tests

  • New: absolute untrusted-URL blocked, http blocked, trusted host allowed, caller-dict non-mutation regression.
  • tests/test_platforms.py: fixes a pre-existing broken assertion (it hardcoded five domains and omitted number, added in fix: Add 'number' to component types list #59) — same change as in the entity-domain PR, identical content so the merges won't conflict.

Full suite on this branch: 226 passed (Python 3.13, pytest-homeassistant-custom-component per requirements_test).

Sylph added 2 commits October 20, 2026 14:25
…d private key

- api_url(): require https + official catlinks.cn hosts (or the configured
  api_base host). Closes a credential-exfiltration path: the request_api
  entity service accepted any absolute URL and would send the session
  token to it (SSRF with creds).
- request(): never mutate the caller's params dict - the injected
  token/sign were leaking into every device-action log that printed its
  params ([rdt, pms] in base/litterbox/c08/feeder/purepro).
- Failed-login, request-failure and response logs no longer dump
  credentials/tokens/params/bodies (returnCode + message only).
- const.py: remove unused RSA_PRIVATE_KEY (dead code, but a private key
  committed to a public repo is a red flag).
- README: replace the 'wget -O - https://get.hacs.vip | bash' install
  methods with plain download instructions (remote code execution).
- tests: host-allowlist cases + caller-dict non-mutation regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant