Skip to content

Verify MTC's certificate, add timeouts and a health check (1.2.1) - #26

Merged
Jochemp88 merged 1 commit into
mainfrom
fix/hardening
Nov 5, 2026
Merged

Jochemp88 merged 1 commit into
mainfrom
fix/hardening

Conversation

@Jochemp88

Copy link
Copy Markdown
Collaborator

What

Hardening for 1.2.1: MTC's certificate is verified again, every Tesla/MTC call has a timeout, a hanging run is stopped, and the Docker image gets a health check.

MTC certificate is verified again

MTC's server mtc.outsystemsenterprise.com presents MTC's own certificate for *.mtc.nl (also valid for mtc.nl), which fails the normal host name check. That is why verification was switched off completely (verify=False) and the warning was hidden, so the MTC password and IBAN went over an unverified connection.

Now (MTCAdapter in MTC.py):

  • the certificate chain is verified against the trusted CAs (certifi), and the certificate must be valid for mtc.nl (urllib3 assert_hostname);
  • if MTC ever installs a certificate for its real host name, the first request of a session, which carries no credentials, falls back to the normal check. The certificate is always verified; when neither check passes, the run stops.

Checked live with the credential-free calls tesla_mtc makes before logging in (module version, JavaScript files, app store URLs): all succeed with verification on. Login and submitting were not run live (no test credentials); they use the same session and adapter.

Timeouts

  • HTTP_TIMEOUT = (10, 60) (connect, read) on every Tesla call and, through the adapter, on every MTC call.
  • A claim is never sent twice: with timeouts, the existing retry loop would resend a claim when MTC does not answer after it was sent. Because claims cannot be withdrawn, a read timeout on the claim request now ends with "Claim submission failed … may have been submitted. Check MTC before running again." The next run's duplicate check finds the claim if it arrived. A connection that fails before sending is still retried.

Web interface and Docker

  • RUNNER_RUN_TIMEOUT (default 900 s, 0 = off): a run that has not finished is stopped and shown as failed, so the page and Home Assistant never stay on Running. On POSIX the whole process group is ended, so a wrapper script in RUNNER_CMD (for example one that pipes into tee) cannot keep the run open.
  • HEALTHCHECK with web/healthcheck.py (standard library, uses RUNNER_PORT and RUNNER_TOKEN): healthy/unhealthy in Docker and Synology Container Manager. The CI smoke test checks it.
  • OCI labels (title, description, source, license).

Logs and dependencies

  • The CSRF token and session cookie values are no longer logged (cookie names only, at DEBUG).
  • The startup warning about disabled certificate verification is gone.
  • tqdm pinned to 4.70.1 like the other dependencies.

Tests

19 new tests:

  • certificate checks, including the actual urllib3 pool settings, the fallback and the stop when both checks fail;
  • default and explicit timeouts, and the Tesla calls;
  • no resend after a read timeout, while a connection failure is still retried;
  • run time limit, including behind a wrapper script on Linux;
  • health check, with and without a token;
  • a guard that verify=False and disable_warnings never come back.

To check that the tests catch regressions, 11 deliberate bugs were introduced one at a time (for example "mtc.nl check removed", "claim resent after no answer", "hanging run not stopped"); every one made the tests fail.

Checked locally

  • ruff check . and pytest: 75 passed. One test (process group) is POSIX-only and runs in CI.
  • Not run locally: Docker job and Python 3.12. This pull request's own run checks them.

Docs: RUNNER_RUN_TIMEOUT and the health check in docs/web-runner.md; version 1.2.1 with a changelog entry (still Unreleased, dated at release).

🤖 Generated with Claude Code

MTC's certificate is verified again. Its server presents MTC's own *.mtc.nl
certificate under mtc.outsystemsenterprise.com, so verification used to be
switched off entirely. Now the chain is verified against the trusted CAs
and the certificate must be valid for mtc.nl (MTCAdapter). If MTC installs a
certificate for its real host name, the first, credential-free request of a
session falls back to the normal check; when neither passes, the run stops.
The password and IBAN are no longer sent over an unverified connection.

- Timeouts (10 s connect, 60 s read) on every Tesla and MTC call. When MTC
  does not answer after a claim was sent, the claim is never sent again in
  the same run, because it may have arrived and claims cannot be withdrawn.
- The web runner stops a run after RUNNER_RUN_TIMEOUT seconds (default
  900) and shows it as failed; on POSIX it ends the whole process group, so
  a wrapper script in RUNNER_CMD cannot keep the run open.
- Docker HEALTHCHECK on /status (web/healthcheck.py, honours RUNNER_TOKEN)
  and OCI image labels; the CI smoke test checks the health check.
- The CSRF token and session cookie values are no longer logged.
- tqdm pinned to 4.70.1.
- Tests for certificate checks, the fallback, timeouts, the claim that is
  not resent, the run time limit and the health check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Jochemp88
Jochemp88 merged commit 0328ab1 into main Nov 5, 2026
5 checks passed
@Jochemp88
Jochemp88 deleted the fix/hardening branch November 5, 2026 14:38
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