- Fixed ACME
acme_urlSSRF (GHSA-v2wp-frmc-5q3v_) where a user-supplied directory URL was fetched
server-side with no validation, allowing IMDS and internal network access.acme_urlis now validated
againstACME_DIRECTORY_HOST_ALLOWLISTat authority creation time. Default allowlist covers Let's Encrypt
prod/staging and GTS; operators extend it via config for internal or additional ACME CAs. - Enhanced private key export audit log (
GHSA-v2wp-frmc-5q3v_) to recordaccess_via(creator vs. rbac),
creator_id, andcurrent_owneron every/certificates/<id>/keyfetch, making post-ownership-transfer
creator access visible in the audit trail. - Fixed JWT algorithm confusion vulnerability (
GHSA-r9gp-7f88-9r54_) where the JWT verifier accepted the
algorithm name from the unverified token header instead of pinning it server-side. The server now reads
the accepted algorithm list fromLEMUR_TOKEN_ALGORITHMS(defaults to["HS256"], which is the only
algorithm Lemur has ever used to issue tokens). Deployments that have not changed the default are fully
backward-compatible with no config change required. - Fixed post-authentication SSRF (
GHSA-54vg-pfh7-jq95_) where CRL Distribution Point and OCSP responder URLs
extracted from uploaded certificate extensions were used as network destinations without validation. Both
crl_verifyandocsp_verifynow reject RFC1918, loopback, and link-local destinations before issuing
outbound requests. Operators may optionally configureLEMUR_TRUSTED_CRL_HOSTSandLEMUR_TRUSTED_OCSP_HOSTS
allowlists. The module-levelcrl_cacheis now bounded to 1000 entries to prevent unbounded cache growth. - Fixed plaintext password storage vulnerability (
GHSA-q437-g7fv-2jvv_) where
users.service.update()wrote new passwords to the database without hashing. The
before_updateSQLAlchemy event listener was missing, so the bcrypt hash applied
on insert was bypassed on every admin-driven password reset viaPUT /api/1/users/<id>.
Passwords are now hashed before update. Any reset password should be treated
as compromised and rotated. Runlemur rehash_passwordsafter upgrading to
detect and re-hash any cleartext passwords already in the database. - Fixed privilege escalation (
GHSA-x3vf-mgxj-7785_) where any member of a role could rewrite that role's membership
list, rename the role, or add arbitrary users viaPUT /api/1/roles/<id>. The endpoint now requires admin
permission, consistent with the existingDELETE /api/1/roles/<id>handler. - Corrected the GHSA-qcqw-jwxc-2hqg fix from 1.9.1. The original fix changed
LEMUR_STRICT_ROLE_ENFORCEMENTto
defaultTrue, which broke normal user operations (certificate issuance, notification management, etc.) for
any deployment where users are assigned custom group roles rather than the built-inadminoroperator
roles. By design, Lemur allows any authenticated user to perform write operations; theread-onlyrole is an
explicit opt-in restriction for users who should only have read access. The correct fix targets only that case:
StrictRolePermissionnow explicitly denies identities carrying theread-onlyrole, regardless of the flag
value, while permitting all other authenticated users.LEMUR_STRICT_ROLE_ENFORCEMENTis reverted to default
False; setting it toTruerestricts write access toadminandoperatoronly, as before.
ADMIN_ONLY_AUTHORITY_CREATIONremainsTrue(authority creation is an admin action).
Note that by design, any authenticated user (not assignedread-only) retains write access
to notifications, certificate upload, and domain management. Operators in higher-risk environments
should evaluateLEMUR_STRICT_ROLE_ENFORCEMENT = Trueto restrict these operations toadmin
andoperatorusers. See theLEMUR_STRICT_ROLE_ENFORCEMENTdocumentation for details.
.. _GHSA-v2wp-frmc-5q3v: GHSA-v2wp-frmc-5q3v
.. _GHSA-54vg-pfh7-jq95: GHSA-54vg-pfh7-jq95
.. _GHSA-r9gp-7f88-9r54: GHSA-r9gp-7f88-9r54
.. _GHSA-q437-g7fv-2jvv: GHSA-q437-g7fv-2jvv
.. _GHSA-x3vf-mgxj-7785: GHSA-x3vf-mgxj-7785