Release Notes — Version 4.1.0
Release Date: 2026-06-11
Type: Security + bugfix release
Severity: High (SCEP)
Upgrade priority: Recommended (urgent if the SCEP endpoint is exposed)
TL;DR — what you must do on upgrade
- If you run the SCEP endpoint, upgrade promptly. Before this release,
PKIOperationenrollment was unauthenticated whenever no challenge password
had been issued (the state at every boot), so any client that could reach
/scepcould obtain a certificate signed by your local CA, for any hostname.
After upgrading, enrollment requires a challenge password by default. To keep
the old open-enrollment behavior, setSCEP_ALLOW_OPEN_ENROLLMENT=true
(not recommended); to restrict which names the CA will sign, set
SCEP_ALLOWED_DOMAINS(comma-separated domain suffixes). - No data migration is required. All other changes are backward compatible.
Security fixes
- SCEP enrollment fails closed. A valid challenge password is now always
required unlessSCEP_ALLOW_OPEN_ENROLLMENTis explicitly enabled. - SCEP CSR identity validation. Every CN/SAN must be a valid hostname or IP,
andSCEP_ALLOWED_DOMAINScan restrict issuance to configured domain
suffixes. The CA no longer signs for arbitrary subjects. - All settings secrets are masked in
GET /api/settings,/running, and
/export(previouslyntfy.token,ntfy.password, andwebhook.headers
leaked). - Settings writes are allowlisted to the settings-form schema, blocking
prototype pollution and arbitrary-key injection viaPOST /api/settingsand
/import. /api/executeuninstall-canow requiresconfirm: trueand enabled
authentication, matching/api/uninstall-ca.- Enterprise CA OpenSSL config injection via newline/metacharacters in
CN/UPN/SAN is rejected. - SCEP
GetCACapsno longer advertises weak SHA-1 / DES3.
Bug fixes
/api/executeno longer throwsReferenceErrorforinstall-ca,
uninstall-ca,caroot, andlist, and returns the real command output.- SCEP certificate generation no longer always throws (enterprise CA call
signature fixed). - Test Email, Verify SMTP, Check Expiry, and Start/Stop Monitoring buttons now
issue POST instead of GET and work again. GET /api/certificatesno longer merges same-named certificates from
different folders into one entry.GET /api/rate-limit/statusno longer returns 500.- The
FORCE_HTTPSredirect builds a correct target instead of string-replacing
the port, and answers 400 (instead of crashing) on a missing Host header. - Certificate monitoring reports a real failure for an invalid cron expression
instead of falsely reporting success;PUT /api/monitoring/configvalidates
the cron expression before applying it. validateRequestreturns 400 (not 500) for non-string values; async route
errors flow through the centralized error handler; the settings UI shows the
real error message.
Added
- A
node:testsuite (npm test) with 63 tests covering the fixes above. SCEP_ALLOW_OPEN_ENROLLMENTandSCEP_ALLOWED_DOMAINSconfiguration.
Images
- GHCR:
ghcr.io/jeffcaldwellca/mkcertweb:4.1.0(built automatically by CI on
thev4.1.0tag). - Docker Hub:
jeffcaldwellca/mkcertweb:4.1.0(published via
./docker-build-push.sh).