{"id":"GHSA-4jqp-9qjv-57m2","summary":"Keylime Missing Authentication for Critical Function and Improper 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:** \u003e= 7.12.0, \u003c= 7.13.0\n\n**Fixed versions:** 7.12.2, \u003e= 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) -\u003e 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 \u003cverifier_ip\u003e -j ACCEPT\niptables -A INPUT -p tcp --dport 8891 -s \u003ctenant_ip\u003e -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```","aliases":["CVE-2026-1709","PYSEC-2026-74"],"modified":"2026-06-06T00:45:49.404160714Z","published":"2026-02-06T22:34:44Z","database_specific":{"github_reviewed_at":"2026-02-06T22:34:44Z","nvd_published_at":null,"cwe_ids":["CWE-295","CWE-306"],"severity":"CRITICAL","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/keylime/keylime/security/advisories/GHSA-4jqp-9qjv-57m2"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-1709"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2026:2224"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2026:2225"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2026:2298"},{"type":"WEB","url":"https://access.redhat.com/security/cve/CVE-2026-1709"},{"type":"WEB","url":"https://bugzilla.redhat.com/show_bug.cgi?id=2435514"},{"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"}],"affected":[{"package":{"name":"keylime","ecosystem":"PyPI","purl":"pkg:pypi/keylime"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.12.0"},{"fixed":"7.12.2"}]}],"versions":["7.12.0","7.12.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-4jqp-9qjv-57m2/GHSA-4jqp-9qjv-57m2.json"}},{"package":{"name":"keylime","ecosystem":"PyPI","purl":"pkg:pypi/keylime"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.13.0"},{"fixed":"7.13.1"}]}],"versions":["7.13.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-4jqp-9qjv-57m2/GHSA-4jqp-9qjv-57m2.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H"}]}