Skip to content

Release Notes v2.141 v2.142

NeySlim edited this page May 2, 2026 · 1 revision

Release Notes — v2.141 → v2.142

Consolidated release notes for stable releases v2.141 (2026-04-29) and v2.142 (2026-05-02).

For older versions see Release Notes v2.128 → v2.140 and the full CHANGELOG.


[2.142] - 2026-05-02

Major security hardening sweep (16 fix(security): commits) plus a large modular refactor of backend services and frontend pages. No breaking API changes. Two operator-visible behaviour changes:

  • HSM dependency installer now returns 403 unless UCM_ALLOW_RUNTIME_PIP=1 is set in the environment.
  • Filesystem session directory is enforced at 0o700 at boot — a loose-permissions directory makes the application refuse to start.

Security

EST / SCEP / mTLS

  • EST /cacerts, /simpleenroll, /simplereenroll, /serverkeygen, /csrattrs now enforce est_enabled on every request and short-circuit with 503 EST disabled instead of falling through to the SPA. The /serverkeygen body is also size-capped and stricter about content negotiation. See EST Protocol.
  • EST and SCEP mTLS client certificates are only honoured when the request comes from a trusted reverse proxy (security.trusted_proxies). Direct hits without TLS termination by UCM no longer accept proxy-injected client cert headers. See EST Protocol, SCEP Server.
  • mTLS login route gated behind the same trusted-proxy check. Header-based mTLS is rejected unless the request originates from a trusted proxy. See mTLS Authentication.
  • SCEP CSRs no longer copy arbitrary KU/EKU bits — only a whitelist (digitalSignature, keyEncipherment, serverAuth, clientAuth) is honoured.
  • SCEP RFC 8894 P0/P1/P2 hardening — stricter PKCS#7 parsing, transaction-ID validation, signed/encrypted response envelope checks; iOS/macOS enrollment fixes (#102).

Authentication & secrets

  • 2FA backup codes are now hashed at rest (Argon2id) and consumed atomically; plaintext codes are returned only at generation time and never stored. See WebAuthn Support.
  • Approval quorum is race-safe and idempotent. Concurrent approvals on the same request can no longer over-approve; double-submits are deduplicated. See Approval Workflows.
  • ACME account private keys encrypted at rest with the application key. See ACME Support.
  • Password change endpoint ignores client-supplied force_change (only operators can clear that flag).
  • CSRF token entropy increased; password hash algorithm tightened; database migration identifiers validated against an allow-list.

Network / SSRF

  • Outbound webhooks revalidate the resolved IP at delivery time (DNS-rebinding window closed) and reject cloud-metadata IPs (169.254.169.254, GCP / Azure / Alibaba equivalents) and loopback. RFC1918 / .lan / .local targets remain allowed by design (UCM is on-prem). See Notifications.
  • SSO / IdP, ACME proxy and webhook URL fields all share the same SSRF helper (validate_url_not_cloud_metadata) — cloud metadata is blocked everywhere.
  • ProxyFix is opt-in via security.trusted_proxies — prevents unauthenticated X-Forwarded-For spoofing on direct deployments.
  • EST audit lines use the trusted-proxy-aware client IP instead of the raw socket address. See Audit Logs.

DoS / resource caps

  • On-demand CRL generation is serialised per-CA with a per-CA lock and 503 Retry-After: 5 under contention — closes a CPU/IO DoS vector when many clients hit /cdp/<ca>.crl simultaneously. See CRL CDP.
  • CSV bulk user-import capped at 5 MB / 10 000 rows with 413 Payload Too Large on overflow. See User Management.
  • Filesystem session directory created/enforced at mode 0o700 and the application refuses to boot if it has group/world-readable bits. See Installation Guide.

Operational opt-in

  • Runtime HSM pip install disabled by defaultPOST /api/v2/hsm/install-dependencies returns 403 with a hint to set UCM_ALLOW_RUNTIME_PIP=1 or install the dependency via the system package manager (apt install python3-pkcs11, dnf install python3-PyKCS11, etc.). See HSM Support.

Added

  • utils/trusted_proxy.py — shared is_request_from_trusted_proxy() / client_ip() / reject_untrusted_proxy_headers() helpers used by EST, SCEP, mTLS login and audit logging.
  • utils/ssrf_protection.py — single source of truth for validate_url_not_cloud_metadata and validate_host_not_cloud_metadata, used by webhooks, SSO, ACME proxy, OPNsense import.
  • utils/safe_commit.py, utils/require_json_body, utils/parse_request_pagination, utils/safe_call, utils/audit_event — small composable helpers applied across api/v2/* to remove boilerplate and silence intermittent rollback bugs.
  • useCRUDPage frontend hook covering 4 list / create / edit pages.

Changed

  • Massive backend modularisation. system.py (1556 l), certificates.py (2220 l), cas.py (1245 l), ssh_cas.py (1607 l), database_admin (817 l), discovery_service, pdf_generator, scep_service (981 l), acme_service (1456 l → 7 mixins ≤ 350 l), trust_store (1487 l), ca_service (788 l), restore_mixin, notification_service, audit_service, crl_service, ssh_cert_service, msca_service, account.py, acme.py, tools.py, acme_client.py, users.py, settings.py, opnsense_import and models/__init__.py were split into focused submodules. Behaviour is unchanged; module size, test isolation and review surface improve.
  • Frontend modularisation. CAsPage, CertificatesPage, DiscoveryPage, ACMEPage, SettingsPage and SsoProviderForm split into per-section sub-components under pages/<feature>/.
  • All api/v2/* db.session.commit() calls now go through safe_commit() — consistent rollback + error logging on every write path.

Fixed

  • PKCS12 / PFX export now honours the include_chain flag (#100). Previously the CA chain was always included, regardless of the request.
  • Dashboard chart cards no longer overflow the grid and System Health gained an internal scrollbar (#99).
  • iOS / macOS SCEP enrollment regressions (#102).

Internal

  • ~20 test files de-duplicated against conftest.py; pre-commit gate runs i18n sync + 461 frontend + 1613 backend tests on every commit.
  • RC validated end-to-end on Debian (DEB), Fedora (RPM) and Docker: smoke API 8/8 and Playwright use-cases 10/10 on all three targets.

[2.141] - 2026-04-29

Fixed

  • Admin lockout prevented on database backend switch (#96). Switching the database backend (SQLite ↔ PostgreSQL) no longer locks the admin out. Boolean and JSON columns are now coerced correctly when migrating rows from SQLite to PostgreSQL, the migration runs per-table in its own transaction so a single bad row no longer aborts the whole switch, and the active admin session survives the cutover. See Database Backend.
  • PostgreSQL backups via pg_dump. The Docker image now ships postgresql-client, so PostgreSQL-backed instances can produce native pg_dump backups during backend migrations and scheduled backups. See Backup & Restore.

Changed

  • In-app help covers v2.128 → v2.140 features in English plus all 8 translated languages (fr, de, es, it, ja, pt, uk, zh).
  • README features and roadmap refreshed for v2.128 → v2.140.

Internal

  • CI: backend test collection no longer fails on missing SECRET_KEY / JWT_SECRET_KEY — workflow now exports test-mode env vars before pytest runs.

Upgrade notes

  • Dockerdocker pull neyslim/ultimate-ca-manager:2.142 (or :latest).
  • DEBwget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.142/ucm_2.142_all.deb && sudo dpkg -i ucm_2.142_all.deb.
  • RPMwget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.142/ucm-2.142-1.fc43.noarch.rpm && sudo dnf install ./ucm-2.142-1.fc43.noarch.rpm.

Operator-visible behaviour changes

  1. HSM dependency installer — if you were relying on the in-app Install dependencies button on the HSM settings page, set UCM_ALLOW_RUNTIME_PIP=1 in the service environment or install the package via your system package manager. Recommended path on production: install via APT/DNF and leave the env var unset.
  2. Session directory perms — UCM refuses to start if its session directory (typically /var/lib/ucm/sessions/ or /opt/ucm/data/sessions/ for source installs) has group/world-readable bits. The package post-install scripts already set this correctly. Manual installs should run chmod 0700 <session-dir>.
  3. mTLS / EST / SCEP behind reverse proxy — if you terminate TLS on a reverse proxy and rely on X-SSL-Client-* (or equivalent) headers, declare the proxy CIDR(s) under security.trusted_proxies in System Config. Direct deployments (UCM terminates TLS itself) need no change.
  4. PKCS12 export include_chain — automation that always received the chain regardless of the flag may now receive a leaf-only PKCS12 if it explicitly sends include_chain=false.

No database migration is required beyond the standard auto-migration on first boot.

Clone this wiki locally