{"id":"CVE-2026-1709","aliases":["GHSA-4jqp-9qjv-57m2","PYSEC-2026-74"],"url":"https://o3.security/vulnerability/CVE-2026-1709","summary":"Keylime: keylime: authentication bypass allows unauthorized administrative operations due to missing client-side tls authentication","details":"### Impact\n\nThe Keylime registrar does not enforce mutual TLS (mTLS) client certificate authentication since version 7.12.0. The registrar's TLS context is configured with `ssl.CERT_OPTIONAL` instead of `ssl.CERT_REQUIRED`, allowing any client to connect to protected API endpoints without presenting a valid client certificate.\n\n**Who is impacted:**\n  - All Keylime deployments running versions 7.12.0 through 7.13.0\n  - Environments where the registrar HTTPS port (default 8891) is network-accessible to untrusted clients\n\n**What an attacker can do:**\n  - **List all registered agents** (`GET /v2/agents/`) - enumerate the entire agent inventory\n  - **Retrieve agent details** (`GET /v2/agents/{uuid}`) - obtain public TPM keys, certificates, and network locations (IP/port) of any agent\n  - **Delete any agent** (`DELETE /v2/agents/{uuid}`) - remove agents from the registry, disrupting attestation services\n\nNote: The exposed TPM data (EK, AK, certificates) consists of public keys and certificates. Private keys remain protected within TPM hardware. The HMAC secret used for challenge-response validation is stored in the database but is not exposed via the API.\n\n**Affected versions:** >= 7.12.0, <= 7.13.0\n\n**Fixed versions:** 7.12.2, >= 7.13.1\n\n### Patches\n\nA patch for the affected released versions is available. It removes the line that override the configuration of `ssl.verify_mode`, leaving the `CERT_REQUIRED` value set by `web_util.init_mtls()`:\n\n```diff\ndiff --git a/keylime/web/base/server.py b/keylime/web/base/server.py\nindex 1d9a9c2..859b23a 100644\n--- a/keylime/web/base/server.py\n+++ b/keylime/web/base/server.py\n@@ -2,7 +2,6 @@ import asyncio\n import multiprocessing\n from abc import ABC, abstractmethod\n from functools import wraps\n-from ssl import CERT_OPTIONAL\n from typing import TYPE_CHECKING, Any, Callable, Optional\n\n import tornado\n@@ -252,7 +251,6 @@ class Server(ABC):\n         self._https_port = config.getint(component, \"tls_port\", fallback=0)\n         self._max_upload_size = config.getint(component, \"max_upload_size\", fallback=104857600)\n         self._ssl_ctx = web_util.init_mtls(component)\n-        self._ssl_ctx.verify_mode = CERT_OPTIONAL\n\n     def _get(self, pattern: str, controller: type[\"Controller\"], action: str, allow_insecure: bool = False) -> None:\n         \"\"\"Creates a new route to handle incoming GET requests issued for paths which match the given\n```\n\nUsers should upgrade to the patched version once it is released.\n\n### Workarounds\n\nIf upgrading is not immediately possible, apply one of the following mitigations:\n\n#### 1. Network isolation (Recommended)\n\nRestrict access to the registrar HTTPS port (default 8891) using firewall rules\nto allow only trusted hosts (verifier, tenant):\n\n##### Example using iptables\n```\niptables -A INPUT -p tcp --dport 8891 -s <verifier_ip> -j ACCEPT\niptables -A INPUT -p tcp --dport 8891 -s <tenant_ip> -j ACCEPT\niptables -A INPUT -p tcp --dport 8891 -j DROP\n```\n\n#### 2. Reverse proxy with mTLS enforcement\n\nDeploy a reverse proxy (nginx, HAProxy) in front of the registrar that enforces client certificate authentication:\n\n##### Example nginx configuration\n```\nserver {\n    listen 8891 ssl;\n    ssl_certificate /path/to/server.crt;\n    ssl_certificate_key /path/to/server.key;\n    ssl_client_certificate /path/to/ca.crt;\n    ssl_verify_client on;  # Enforce client certificates\n\n    location / {\n        proxy_pass https://localhost:8892;  # Internal registrar port\n    }\n}\n```","published":"2026-02-06T19:13:27.695Z","modified":"2026-10-28T02:30:22.848576800Z","cvss":{"score":9.4,"severity":"CRITICAL","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"keylime","fixedVersion":"7.12.2"},{"ecosystem":"PyPI","name":"keylime","fixedVersion":"7.13.1"}],"fix":null,"references":[{"type":"WEB","url":"https://access.redhat.com/downloads/content/package-browser/"},{"type":"WEB","url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-1709.json"},{"type":"ADVISORY","url":"https://access.redhat.com/errata/RHSA-2026:2224"},{"type":"ADVISORY","url":"https://access.redhat.com/errata/RHSA-2026:2225"},{"type":"ADVISORY","url":"https://access.redhat.com/errata/RHSA-2026:2298"},{"type":"ADVISORY","url":"https://access.redhat.com/security/cve/CVE-2026-1709"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/1xxx/CVE-2026-1709.json"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-1709"},{"type":"REPORT","url":"https://bugzilla.redhat.com/show_bug.cgi?id=2435514"},{"type":"WEB","url":"https://github.com/keylime/keylime/security/advisories/GHSA-4jqp-9qjv-57m2"},{"type":"PACKAGE","url":"https://github.com/keylime/keylime"},{"type":"WEB","url":"https://github.com/pypa/advisory-database/tree/main/vulns/keylime/PYSEC-2026-74.yaml"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:22.848576800Z"}}