Skip to content

fix(security): prevent PIN disclosure in inventory logs and errors - #101

Open
danoev wants to merge 1 commit into
roquerodrigo:mainfrom
danoev:codex/upstream-pin-diagnostics
Open

danoev wants to merge 1 commit into
roquerodrigo:mainfrom
danoev:codex/upstream-pin-diagnostics

Conversation

@danoev

@danoev danoev commented Oct 22, 2026 •

Copy link
Copy Markdown

get_passcodes() logs the decrypted response at DEBUG level, and malformed inventory responses can include working PINs in parser errors and chained tracebacks. This patch keeps diagnostics structural without changing the inventory protocol.

  • client.py: log response length instead of plaintext; suppress parser exception chaining at the public TTLockError boundary.
  • commands/passcode_list.py: remove packet/credential hex from rejection, length and date errors; handle short envelopes and non-ASCII credentials without exposing the underlying bytes.
  • tests/test_passcode_privacy.py: synthetic current/previous PIN fixtures check successful reads, rejected/truncated/invalid-date/non-ASCII responses and formatted tracebacks for both ASCII and hex disclosure.

Public methods, successful return values and the existing RuntimeError/ValueError parser contract remain intact. No opcode, authentication, pagination, BLE operation or PIN-write behavior changes. A malformed non-ASCII credential now raises a credential-safe ValueError instead of its UnicodeDecodeError subclass.

Validation against original upstream main 8025f57cebc7de63a66035fd19e1efb042d0208f: 469 tests passed, 99.22% coverage; Ruff, formatting and strict mypy passed. The added tests reproduced disclosure before this change. All new credentials are synthetic; no live lock or household credentials were used.

Thank you for the original TTLock BLE SDK. This is intentionally a small compatibility-preserving contribution; I am happy to respond to review and maintain it.

Independent exact-head hosted validation passed: CI and CodeQL. This uses the same single-commit diff against frozen original main; original-upstream Actions still await maintainer approval for this first contribution.

dariusz-rudzinski added a commit to dariusz-rudzinski/ttlock-ble that referenced this pull request Oct 23, 2026
Card ids are cloneable credentials, same as keypad passcodes - apply the
same treatment upstream PR roquerodrigo#101 gave get_passcodes:

- get_cards logs only the response length, not the decrypted plaintext.
- parse_card_list_response's FAILED and unexpected-length errors report
  status/length only, dropping data.hex() and plaintext.hex().
- get_cards raises TTLockError(...) from None so the chained exception
  can't carry the original error's raw bytes into a traceback.
- Added test_card_privacy.py, mirroring test_passcode_privacy.py: asserts
  a synthetic card id never appears in debug logs or in any raised
  error's string or traceback, across a successful read and FAILED/
  truncated/overlong responses.

Fingerprint code is untouched - that's a separate change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

2 participants