Skip to content
This repository was archived by the owner on Jul 7, 2026. It is now read-only.

Releases: Netflix/lemur

v1.9.3

Choose a tag to compare

@PJ1288 PJ1288 released this 06 Jul 22:20
726506d
  • Fixed missing authorization check (GHSA-4h97-p9wq-chqj_) on POST /certificates/<id>/export for plugins
    with requires_key = False (e.g. java-truststore-jks). The ownership check was previously skipped
    entirely for these plugins with no compensating control. Since such plugins never receive the real private
    key, any authenticated user may still use them regardless of ownership; plugins with requires_key = True
    continue to require ownership and log a key_view audit event, and only they are passed cert.private_key.
  • Fixed missing authorization on the replaces field (GHSA-cfh6-pv5c-38jv_), where any authenticated
    caller could reference an arbitrary certificate by ID on certificate create, upload, and edit requests,
    silencing its expiration notifications and retargeting its rotation without the owning team's knowledge.
    authorize_certificate_replacement now requires the caller to own or hold a role on every certificate
    named in replaces, consistent with the existing check for direct revoke/edit. Enforcement can be
    disabled via ENFORCE_REPLACES_AUTHORIZATION (defaults to True) for deployments that need to
    temporarily preserve the old behavior while they grant the appropriate role to affected workflows.
  • Fixed plaintext credential exposure via the destinations API (GHSA-6c8m-q6g9-vrw3_). Sensitive
    destination plugin options (e.g. SFTP password and private key passphrase) were returned in plaintext
    to any authenticated caller via GET /destinations, GET /destinations/<id>, and
    GET /certificates/<id>/destinations. Sensitive option values are now redacted for non-admin
    callers; admins retain the ability to view and edit them.
  • Fixed incomplete fix for ACME acme_url SSRF (GHSA-v5rc-cpwc-cfpr). The 1.9.2 fix for
    GHSA-v2wp-frmc-5q3v
    validated acme_url against ACME_DIRECTORY_HOST_ALLOWLIST only at
    authority creation time. Any user with a role on an existing ACME authority could still overwrite
    its stored acme_url with an internal/IMDS address via PUT /api/1/authorities/<id>, since the
    update path stored options verbatim with no re-validation. The next certificate issuance via that
    authority would then cause Lemur's backend to fetch the attacker-controlled URL. acme_url is now
    also validated against the allowlist on authority update.
  • Fixed SSRF via ACME client following server-controlled URLs (GHSA-xpmj-wjcp-6pww_). In addition to
    the acme_url allowlist check above, the ACME client itself no longer trusts hostnames supplied by
    the directory/order/authorization/finalize responses returned by the ACME server; outbound requests are
    now pinned to the configured, allowlisted directory host, closing a second SSRF vector where a malicious
    or compromised ACME server could redirect Lemur's backend to arbitrary internal URLs mid-issuance.
  • Fixed missing authorization check on sub-CA creation (GHSA-g7p5-89mh-248h_). When
    ADMIN_ONLY_AUTHORITY_CREATION is disabled, POST /api/1/authorities with
    type=subca never verified that the caller holds AuthorityPermission on the
    supplied parent authority, letting any authenticated non-read-only user mint a sub-CA
    chained off any internal root Lemur holds the private key for and issue trusted leaf
    certs under it. AuthoritiesList.post now enforces AuthorityPermission on the
    parent authority before delegating to the issuer plugin, matching the check already
    used when updating an existing authority.
  • Fixed arbitrary certificate revocation at the CA (GHSA-pxmc-2ffp-8j67_). Certificate identity was tracked
    only by Lemur's internal database row, not by the actual CA-side certificate. Any authenticated user could
    upload a duplicate record for a certificate they didn't own (matching an existing authority_id and
    serial) and then revoke it via PUT /api/1/certificates/<id>/revoke, causing the CA to revoke the
    real certificate belonging to another user. POST /api/1/certificates/upload now requires
    AuthorityPermission on the specified authority, and rejects uploads whose (authority_id, serial)
    pair already matches an existing certificate with a 409 response. PUT /api/1/certificates/<id>/revoke
    now also checks authorization and endpoint attachment against every certificate row sharing
    (authority_id, serial) with the one being revoked, not just the row named in the request, closing the
    gap for any duplicate rows that already exist.

.. _GHSA-4h97-p9wq-chqj: GHSA-4h97-p9wq-chqj
.. _GHSA-cfh6-pv5c-38jv: GHSA-cfh6-pv5c-38jv
.. _GHSA-6c8m-q6g9-vrw3: GHSA-6c8m-q6g9-vrw3
.. _GHSA-v5rc-cpwc-cfpr: GHSA-v5rc-cpwc-cfpr
.. _GHSA-v2wp-frmc-5q3v: GHSA-v2wp-frmc-5q3v
.. _GHSA-xpmj-wjcp-6pww: GHSA-xpmj-wjcp-6pww
.. _GHSA-g7p5-89mh-248h: GHSA-g7p5-89mh-248h
.. _GHSA-pxmc-2ffp-8j67: GHSA-pxmc-2ffp-8j67

v1.9.2

Choose a tag to compare

@PJ1288 PJ1288 released this 10 Jun 18:50
4afd730
  • Fixed ACME acme_url SSRF (GHSA-v2wp-frmc-5q3v_) where a user-supplied directory URL was fetched
    server-side with no validation, allowing IMDS and internal network access. acme_url is now validated
    against ACME_DIRECTORY_HOST_ALLOWLIST at 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 record access_via (creator vs. rbac),
    creator_id, and current_owner on every /certificates/<id>/key fetch, 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 from LEMUR_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_verify and ocsp_verify now reject RFC1918, loopback, and link-local destinations before issuing
    outbound requests. Operators may optionally configure LEMUR_TRUSTED_CRL_HOSTS and LEMUR_TRUSTED_OCSP_HOSTS
    allowlists. The module-level crl_cache is 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_update SQLAlchemy event listener was missing, so the bcrypt hash applied
    on insert was bypassed on every admin-driven password reset via PUT /api/1/users/<id>.
    Passwords are now hashed before update. Any reset password should be treated
    as compromised and rotated. Run lemur rehash_passwords after 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 via PUT /api/1/roles/<id>. The endpoint now requires admin
    permission, consistent with the existing DELETE /api/1/roles/<id> handler.
  • Corrected the GHSA-qcqw-jwxc-2hqg fix from 1.9.1. The original fix changed LEMUR_STRICT_ROLE_ENFORCEMENT to
    default True, which broke normal user operations (certificate issuance, notification management, etc.) for
    any deployment where users are assigned custom group roles rather than the built-in admin or operator
    roles. By design, Lemur allows any authenticated user to perform write operations; the read-only role is an
    explicit opt-in restriction for users who should only have read access. The correct fix targets only that case:
    StrictRolePermission now explicitly denies identities carrying the read-only role, regardless of the flag
    value, while permitting all other authenticated users. LEMUR_STRICT_ROLE_ENFORCEMENT is reverted to default
    False; setting it to True restricts write access to admin and operator only, as before.
    ADMIN_ONLY_AUTHORITY_CREATION remains True (authority creation is an admin action).
    Note that by design, any authenticated user (not assigned read-only) retains write access
    to notifications, certificate upload, and domain management. Operators in higher-risk environments
    should evaluate LEMUR_STRICT_ROLE_ENFORCEMENT = True to restrict these operations to admin
    and operator users. See the LEMUR_STRICT_ROLE_ENFORCEMENT documentation 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

v1.9.1

Choose a tag to compare

@jtschladen jtschladen released this 28 May 17:19
f478458
  • Fixed authorization bypass (GHSA-qcqw-jwxc-2hqg) where StrictRolePermission and AuthorityCreatorPermission
    granted access to any authenticated user on default Lemur installs. Both LEMUR_STRICT_ROLE_ENFORCEMENT and
    ADMIN_ONLY_AUTHORITY_CREATION now default to True (fail-closed). Existing installs that explicitly set
    either flag to False are unaffected.

v1.9.0

Choose a tag to compare

@jtschladen jtschladen released this 28 Apr 00:10
f59087a

This release contains fixes for two security vulnerabilities (GHSA-3r34-vq8m-39gh, GHSA-vr7c-r5gj-j3w5).

  • Fixed a bug where the old certificate was not removed from an endpoint after rotation.
  • Added GcsDestinationPlugin, which allows uploading certificates to Google Cloud Storage.
  • Fixed a bug where rotation notifications did not include endpoint context.
  • Fixed AttributeError when running lemur CLI commands without a config file.
  • Added ENABLE_AUTOROTATION_FILTER: a configurable, plugin-independent callback that can be used to skip enabling autorotate based on your specific business logic. For example, you could disallow enabling autorotate on certs with notifications disabled.
  • Added REISSUE_FILTER: a configurable, plugin-independent callback that can be used to reject reissuance requests based on your specific business logic. For example, you could disallow reissuing certs on abandoned ELBs.
  • Added AWS_ELB_IGNORE_TAGS to allow multiple ELB tags to be ignored.
  • Added support for ignoring CloudFront distributions and IAM certificates via the AWS_CLOUDFRONT_IGNORE_TAGS and AWS_IAM_IGNORE_TAGS config options.
  • Added ENABLE_AUTO_ROTATE_ALL_AUTHORITIES configuration to allow all authorities to be considered for destination autorotate task.
  • Added CERTIFICATE_UPDATE_REQUEST_VALIDATION: a configurable, plugin-independent callback that can be used to reject requests based on your specific business logic. For example, you could disallow certs with rotate set and no destinations to reduce volume of unused certs.
  • Added CERTIFICATE_CREATE_REQUEST_VALIDATION: a configurable, plugin-independent callback that can be used to reject requests based on your specific business logic. For example, you could disallow certs with rotate set and no destinations to reduce volume of unused certs.
  • Added CERTIFICATE_EXPORT_KEY_REQUEST_VALIDATION: a configurable, plugin-independent callback that can be used to reject private key export requests based on your specific business logic. For example, you could block specific API keys from exporting private keys for migrated certificates.
  • Added the disable_autorotate_without_endpoint celery task, along with a customizable DISABLE_AUTOROTATION_FILTER function you can use to determine when to disable autorotate. By default, nothing will be changed by this task when scheduled.
  • Added a new API endpoint /certificates/{certificate_id}/description for updating just the description field of a certificate, avoiding the need to provide the full certificate object for simple description updates.
  • Removed support for Postgres 12, Postgres 15, Python 3.9, and Ubuntu 20.04. Added support for Postgres 16.

v1.8.2

Choose a tag to compare

@jmcrawford45 jmcrawford45 released this 11 Jun 16:44
83ec6d5

What's Changed

Full Changelog: v1.8.1...v1.8.2

v1.8.1 Release

Choose a tag to compare

@jtschladen jtschladen released this 20 May 21:19
cd18f14

See the CHANGELOG for more details.

v1.8.0 Release

Choose a tag to compare

@jtschladen jtschladen released this 20 May 17:10
a7d008d

See the CHANGELOG for more details.

v 1.7.0 release

Choose a tag to compare

@jmcrawford45 jmcrawford45 released this 17 Jan 19:18
35b9982

See the CHANGELOG for more details.

v 1.6.0 release

Choose a tag to compare

@jmcrawford45 jmcrawford45 released this 23 Oct 21:10
59653f0

See the CHANGELOG for more details.

v1.5.0 Release

Choose a tag to compare

@jmcrawford45 jmcrawford45 released this 05 Jul 22:37
e82582f

See the CHANGELOG for more details.