github fabriziosalmi/certmate v2.48.5
v2.48.5 (a second SMTP recipient can be typed, and the places that take a name ask about it)

8 hours ago

v2.48.5 (a second SMTP recipient can be typed, and the places that take a name ask about it)

A patch release. One fix visible to people: in Settings, the SMTP "To Addresses" field removed the comma and space as they were typed, so a second recipient was joined to the first. The rest is the layer under it: the storage and delete methods and the role denial are held to rules the rest of the application already followed, ten functions nothing called are removed, five dependency updates are taken with their locks, and the guards around them (the lock check, the skips, the fault-tolerance tests) were made to say what they check. The API contract stays at 2.44: no route, field or status code changes.


Read this before upgrading

Nothing needs to change on your side. No route, setting or file format differs from 2.48.4.


Security

  • The methods that take a name ask about it themselves (#1214). The certificate manager's delete_certificate, the four name-taking methods of the local storage backend, and the storage manager that dispatches to every backend now validate the name they are given, as the manager's other entry points and the route validators already did. The refusal follows each method's own contract (ValueError where its siblings raise it, False or None where a storage method already answers failure that way). Legitimate names, wildcards included, go through unchanged.
  • The role denial scrubs what it logs (#1214). _log_rbac_denial now scrubs its values as the scope denial next to it does. A denial names the user and the action and carries no credential.

Fixed

  • A second recipient can be typed into the SMTP "To Addresses" field (#1208, #1207). Typing a@example.com, b@example.com key by key left a@example.comb@example.com in the field, and that was saved as one recipient. The field is bound to a list through an accessor that drops empty parts, so a trailing comma or space became nothing, and Alpine wrote the list back into the field after every key, taking the separator out again. Pasting worked. The field now carries x-model.unintrusive: while it has the focus the page does not write into it, and the list is still updated at every key. A stored pair is still shown as a, b.

Changed

  • Dependencies, with their locks regenerated (#1210, #1211, #1217, #1219). azure-identity 1.26.0, boto3 1.43.108, botocore 1.43.109, google-cloud-dns 0.37.2, python-dotenv 1.2.4, sqlalchemy 2.1.4 (the floor in requirements.txt becomes 2.1.3), ansible-core 2.21.4 for the Galaxy publishing job, tldextract 5.4.0, and @alpinejs/csp 3.17.4 (the vendored static/js/alpine.min.js re-copied byte for byte) with @modelcontextprotocol/sdk 1.32.0 in mcp/. The Azure Key Vault storage floors (azure-keyvault-secrets, azure-keyvault-certificates) become 4.11.3. tldextract 5.4.0 bundles the same Public Suffix List snapshot as 5.3.2, and 44 names resolve identically on both.
  • Ten functions that nothing called are removed (#1212), 110 lines. Each name occurred once in the whole tracked tree, its own definition.

Tests

  • A requirement the lock does not meet is caught (#1209). The check that a bump does not merge without the lock compared exact pins only; a floor, a ceiling or an exclusion was read as absent. It now compares every requirement, and reports a line it cannot compare (a marker, a URL) instead of skipping it. A floor raised above the locked version used to pass every check while the image stayed on the old one.
  • The skips that said nothing are gone (#1213). 28 of the unit suite's 57 skips were one test parametrized over files it did not apply to, and an empty parameter set. The files that do not constrain cryptography are now listed with the reason, and a test fails when the list and the files disagree.
  • A function nothing calls fails a test (#1212): tests/test_no_function_is_left_that_nothing_calls.py, with controls.
  • Nine fault-tolerance tests reach the fault they are about (#1218). Each was run with its fault made unreachable in the code; the original tests still passed. They now fail in that case (9 of 9).
  • The PEM scrubber is held to growing linearly, not to a number of seconds (#1216), the same change #1191 made to the other test of its kind.
  • A scheduled check that fails reaches someone (#1220). The weekly run (Mondays 06:00 UTC) went red on four of its last six runs without anyone being told. A new job opens an issue when ca-endpoints, wiki or wiki-endpoints fails, comments while it stays red and closes it when the check passes. advisories is deliberately not reported this way. A test fails when a scheduled-only job is in neither list.

How it was checked

  • The SMTP field, in a browser. Chrome headless, real key presses, main beside the branch: 11 scenarios (typed lists of two and three addresses, a deleted separator, a paste, a stored pair, a trailing comma, clearing the field, Save with the focus in the field). main gets 6 of 11 right, this release 11 of 11. The other form tried (x-model.lazy) ends right but leaves the list stale at every key.
  • The names. Every public method of the certificate manager that takes a domain, found by introspection, is called with a name that is a path against a sandbox, and the tree before and after is compared. Each rule removed in turn fails its tests.
  • The locks. scripts/lockfile.py check agrees on all five pairs, ranges included; the regeneration resolves for both published architectures and agrees on hashes.
  • Alpine 3.17.4. 530 of 530 template expressions through the package's own parser; 65 recorded browser scenarios identical on main and the branch; the same scenarios with Alpine made to throw differ, so they do see it.
  • The release gate runs on the release commit: the suite, the browser tests, and real certificates from Let's Encrypt staging (mandatory here, since boto3, google-cloud-dns and azure-identity are packages the issuance path imports).

Not verified

  • Other browsers. Every browser measurement in this release is Chromium.
  • The scheduled reporter against GitHub. It runs on the Monday schedule only, so its first real run is the next one. The script and the workflow's structure are tested; the call to GitHub is not.
  • test_add_cloudflare_account. It submits the add-account form and asserts nothing about the result; it runs only with a Cloudflare token and is left as it is.

Don't miss a new certmate release

NewReleases is sending notifications on new releases.