CVE-2026-71308

CVE-2026-71308 is a high-severity missing authorization vulnerability in lemur (pip), affecting versions >= 0.5.0, <= 1.9.2. It is fixed in 1.9.3.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Lemur: Unchecked replaces[] lets any user silence notifications and hijack auto-rotation for arbitrary certificates

Repo under test: https://github.com/Netflix/lemur

The certificate create and upload endpoints accept a replaces[] (alias replacements) array that is resolved to live Certificate ORM objects with no ownership or CertificatePermission check on the referenced certificates. The SQLAlchemy Certificate.replaces append listener then immediately sets victim.notify = False and populates victim.replaced. From that point the victim certificate is excluded from auto-reissue, its expiration notifications are silenced, and the periodic certificate_rotate Celery task deploys the attacker's certificate (endpoint.certificate.replaced[0]) onto every endpoint serving the victim certificate.

Any authenticated non-read-only user can therefore silently substitute their own certificate onto production load balancers and Kubernetes secrets they hold no role on, while suppressing the legitimate certificate's lifecycle automation.

Affected route

POST /api/1/certificates
POST /api/1/certificates/upload
PUT /api/1/certificates/<id>

Affected code

Root cause

AssociatedCertificateSchema.get_object calls fetch_objects(Certificate, data) and returns the ORM rows verbatim. No caller on the create/upload/edit path iterates the resolved replaces list to enforce CertificatePermission before the model assigns them, and the Certificate.replaces append event listener mutates the victim row (notify = False) as a side effect of ORM collection assignment. The direct revoke endpoint does enforce CertificatePermission, but this replaces path achieves an equivalent or worse outcome while bypassing it entirely.

Validated evidence

Static trace, confirmed by code inspection (validation status: CONFIRMED):

  • replaces is accepted in CertificateInputSchema / CertificateUploadInputSchema and resolved via fetch_objects(Certificate, ...) with no per-object authorization.
  • grep -n CertificatePermission lemur/certificates/views.py shows the check is applied to PUT/DELETE/revoke/export paths but never to the replaces payload of POST /certificates or POST /certificates/upload.
  • The Celery certificate_rotate task and cli.rotate() consume Endpoint.replaced.any() unconditionally and deploy replaced[0] with commit=True.

Proof of concept / reproducer

Status: reconstructed from source report (static control-flow trace; not executed against a live CA).

Preconditions: attacker is an authenticated Lemur user holding any role other than read-only (default StrictRolePermission config). <VICTIM_CERT_ID> is any certificate id readable via GET /api/1/certificates.

# 1. Upload an attacker-controlled cert that "replaces" the victim
curl -sS -X POST "<TARGET_BASE_URL>/api/1/certificates/upload" \
  -H "Authorization: Bearer <AUTH_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "attacker-replacement",
        "owner": "[email protected]",
        "body": "-----BEGIN CERTIFICATE-----\n<ATTACKER_CERT_PEM>\n-----END CERTIFICATE-----",
        "privateKey": "-----BEGIN PRIVATE KEY-----\n<ATTACKER_KEY_PEM>\n-----END PRIVATE KEY-----",
        "replaces": [{"id": <VICTIM_CERT_ID>}]
      }'

# 2. Observe victim.notify is now false and victim is queued for rotation
curl -sS "<TARGET_BASE_URL>/api/1/certificates/<VICTIM_CERT_ID>" \
  -H "Authorization: Bearer <AUTH_TOKEN>" | jq '.notify, .replaced'

# 3. On the next certificate_rotate Celery beat tick, the attacker cert is
#    deployed to every endpoint that was serving <VICTIM_CERT_ID>.

Static-trace validation command from the source report:

grep -n 'replaces' lemur/certificates/schemas.py lemur/certificates/views.py lemur/schemas.py \
  && grep -n 'CertificatePermission' lemur/certificates/views.py

Source artifact: audit/harnesses/public-repo-threat-model-harness/results/netflix-lemur-100run-mythos-20260627T051129Z/findings.jsonl (run_083, finding cluster lemur-replaces-unauth, 7/100 runs).

Impact

An authenticated insider or holder of a stolen low-privilege token can, without holding any role on a target certificate:

  1. Upload a self-signed or attacker-minted certificate listing arbitrary high-value production certificate IDs in replaces.
  2. Immediately disable expiration notifications and auto-reissue for those production certificates.
  3. On the next scheduled certificate_rotate Celery run, have the attacker's certificate pushed to every endpoint (AWS ELB/CloudFront/ACM, Kubernetes, SFTP, etc.) currently serving the victim certificate, while the legitimate certificate is detached.

Minimum impact is fleet-wide TLS denial of service equivalent to mass revocation. Where internal clients trust the substituted chain (or combined with the sub-CA finding LEMUR-BUG-07), it escalates to TLS interception. This directly violates the invariant that a user may only modify or revoke a certificate if they are its owner, a member of an owning role, or an administrator.

The application does not perform an authorization check before performing a sensitive operation. Typical impact: unauthorized access to restricted functionality or data.

CVE-2026-71308 has a CVSS score of 8.1 (High). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.9.3); upgrading removes the vulnerable code path.

Affected versions

lemur (>= 0.5.0, <= 1.9.2)

Security releases

lemur → 1.9.3 (pip)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Before persisting replaces/replacements on certificate create, upload, and edit, iterate each referenced certificate and enforce the same CertificatePermission(owner_role, cert.roles) check used by the revoke endpoint (views.py:1677-1685); reject with 403 if the caller is not creator/owner/role-member/admin for any target. Additionally, move the value.notify = False side effect out of the SQLAlchemy append listener so an authorization failure cannot leave a victim certificate partially mutated, and emit an audit_log entry whenever a certificate is marked as replaced.

Frequently Asked Questions

  1. What is CVE-2026-71308? CVE-2026-71308 is a high-severity missing authorization vulnerability in lemur (pip), affecting versions >= 0.5.0, <= 1.9.2. It is fixed in 1.9.3. The application does not perform an authorization check before performing a sensitive operation.
  2. How severe is CVE-2026-71308? CVE-2026-71308 has a CVSS score of 8.1 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of lemur are affected by CVE-2026-71308? lemur (pip) versions >= 0.5.0, <= 1.9.2 is affected.
  4. Is there a fix for CVE-2026-71308? Yes. CVE-2026-71308 is fixed in 1.9.3. Upgrade to this version or later.
  5. Is CVE-2026-71308 exploitable, and should I be worried? Whether CVE-2026-71308 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-71308 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-71308? Upgrade lemur to 1.9.3 or later.

Other vulnerabilities in lemur

Stop the waste.
Protect your environment with Kodem.