Skip to content

v2.142

Choose a tag to compare

@github-actions github-actions released this 02 May 21:20
· 204 commits to main since this release

What's Changed

Security

  • 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.
  • 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.
  • mTLS login route gated behind trusted-proxy check. Same protection as EST/SCEP — header-based mTLS is rejected unless the request originates from a trusted proxy.
  • 2FA backup codes are now hashed at rest (Argon2id) and consumed atomically; plaintext codes are returned only at generation time and never stored.
  • Approval quorum is race-safe and idempotent. Concurrent approvals on the same request can no longer over-approve; double-submits are deduplicated.
  • 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.
  • 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).
  • SSO/IdP, ACME proxy and webhook URL fields all share the same SSRF helper (validate_url_not_cloud_metadata) — cloud metadata is blocked everywhere.
  • CSV bulk user-import capped at 5 MB / 10 000 rows with 413 on overflow.
  • Runtime HSM pip install disabled by default, returns 403 with a hint to set UCM_ALLOW_RUNTIME_PIP=1 or install the dependency via the system package manager.
  • 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).
  • ACME account private keys encrypted at rest with the application key.
  • 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.
  • ProxyFix is opt-in via security.trusted_proxies — prevents unauthenticated X-Forwarded-For spoofing on direct deployments.
  • Filesystem session directory is now created/enforced at mode 0o700 and the application refuses to boot if it has group/world-readable bits.
  • EST audit lines use the trusted-proxy-aware client IP instead of the raw socket address.

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.
  • 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 i18n + 461 frontend + 1613 backend tests gate every commit.
  • RC validated end-to-end on Debian (pve:8445), Fedora (fedor:8443) and Docker (pve:8444): smoke API 8/8 and Playwright use-cases 10/10 on all three targets.

📜 Recent release history (last 2 versions)

[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.
  • 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.

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.

[2.140] - 2026-04-27

Fixed

  • Certificate SAN database columns now derived from the final SAN list (#94). When a CN is auto-promoted to an rfc822Name SAN at issuance, the san_email / san_dns / san_ip / san_uri columns are now written from the canonical SAN list instead of the raw form payload, so DB queries match the X.509 extension. Migration 027_backfill_san_email re-parses existing certificate PEMs and backfills any rows that were out of sync (idempotent on SQLite and PostgreSQL). Thanks @Hemsby.
  • Certificate and CA files written to disk on creation (#95). Added SQLAlchemy after_insert listeners on the Certificate and CA models that immediately materialize .crt / .key files under data/certs/ and data/cas/ for every creation path (UI, CSR signing, ACME, SCEP, import). The startup file-regeneration scan is kept as a safety net. File-write errors are logged but never abort the database transaction. Thanks @Hemsby.

Full history: CHANGELOG.md


Installation

Docker (Recommended)

# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.142

# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.142

# Run
docker run -d -p 8443:8443 \
  -e SECRET_KEY=$(openssl rand -hex 32) \
  --name ucm neyslim/ultimate-ca-manager:2.142

Debian/Ubuntu

wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.142/ucm_2.142_all.deb
sudo dpkg -i ucm_2.142_all.deb
sudo apt-get install -f

Fedora/RHEL

wget 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

Silent/Automated Install

# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.142_all.deb

Default Credentials

  • Username: admin
  • Password: changeme123

Change the password immediately after first login!

Documentation