
Disabled TLS Certificate Verification for HashiCorp Vault KMS in confluent-kafka
Severity: High, CVSS 3.1 7.4
Vector (v3.1): CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
Affected: confluent-kafka >= 2.8.0, <= 2.14.2
Fixed in: 2.15.0
CWE: CWE-295 (Improper Certificate Validation)
Component: confluent_kafka/schema_registry/rules/encryption/hcvault/hcvault_client.py
Reported by: Rahul Karne
CNA: VulnCheck
The HashiCorp Vault KMS client in confluent-kafka hardcodes verify=False when constructing its hvac.Client, disabling TLS certificate verification for Vault HTTPS connections made through the Schema Registry field-encryption rules.
The vulnerable code is located in:
confluent_kafka/schema_registry/rules/encryption/hcvault/hcvault_client.py
The affected client is initialized as follows:
self._client = hvac.Client(
url=vault_url,
token=token,
namespace=ns,
verify=False
)
Because verify=False is unconditional, the client accepts untrusted TLS certificates, including self-signed or attacker-controlled certificates.
A network-positioned attacker capable of intercepting or redirecting the application's Vault traffic can impersonate the Vault server, capture Vault authentication credentials, and return forged Vault/KMS responses.
The affected HCVault integration exposes configuration for Vault tokens, namespaces, and AppRole credentials, but affected versions provide no supported CA-bundle configuration or equivalent mechanism to restore certificate verification.
An attacker with a network man-in-the-middle position between the application and HashiCorp Vault can:
X-Vault-Tokenrole_idsecret_idThis can compromise the confidentiality and integrity of data protected by the Vault-backed KMS workflow.
confluent-kafka is the official Confluent Python client for Apache Kafka.
The vulnerability specifically affects deployments using:
Schema Registry encryption rules
↓
HCVault KMS integration
↓
hcvault:// key URI
The affected population is therefore narrower than all confluent-kafka users.
However, the affected functionality is security-sensitive because these deployments rely on HashiCorp Vault for cryptographic key management and field-level encryption.
HcVaultKmsClient.__init__() parses an hcvault:// key URI, determines the Vault base URL, and creates an hvac.Client.
In affected versions, including 2.14.2, the relevant code is:
self._client = hvac.Client(
url=vault_url,
token=token,
namespace=ns,
verify=False
)
if role_id and secret_id and self._client is not None:
self._client.auth.approle.login(
role_id=role_id,
secret_id=secret_id
)
The hvac library ultimately relies on the Python requests TLS stack.
Setting:
verify=False
instructs the client not to validate the remote server's TLS certificate.
As a result, certificates that would normally be rejected can be accepted, including certificates that are:
This affects both supported authentication paths.
When token authentication is used, the Vault token is sent through the:
X-Vault-Token
HTTP header.
If an attacker successfully impersonates the Vault endpoint, the attacker-controlled server can receive this token.
When AppRole authentication is used, the client sends:
role_id
secret_id
to:
/v1/auth/approle/login
A successful MITM can therefore capture both AppRole credentials.
The affected HCVault driver reads configuration including:
token.id
namespace
approle.role.id
approle.secret.id
as well as relevant VAULT_* environment variables.
However, affected versions do not expose configuration allowing operators to:
As a result, applications using the affected integration cannot restore TLS verification through the normal package configuration.
The package explicitly disables TLS server-certificate verification instead of relying on the secure default.
The vulnerable construction is effectively:
hvac.Client(..., verify=False)
rather than:
hvac.Client(..., verify=True)
or simply:
hvac.Client(...)
where verification is enabled by default.
Disabling certificate verification removes server authentication from the TLS connection.
Although the connection remains encrypted, the client has no reliable mechanism for determining whether it is communicating with the legitimate Vault server.
This creates the condition required for a network man-in-the-middle attack.
Successful exploitation requires:
The application uses an affected version of confluent-kafka:
2.8.0 through 2.14.2.The application uses Schema Registry encryption rules with the HCVault KMS integration.
The configured KMS key uses the:
hcvault://
scheme.
Possible examples include:
No application-level privileges or victim interaction are required once the necessary MITM position exists.
poc_confluent_kafka.py demonstrates the issue against a locally unpacked confluent-kafka 2.14.2 wheel.
The PoC uses:
HcVaultKmsClient implementation.The proof of concept contains five modes.
| Mode | Description |
|---|---|
cert | Generates a self-signed certificate and key for the local mock Vault. |
server | Starts the mock HTTPS Vault on https://localhost:8443 and displays received requests. |
control | Secure control using verify=True; should reject the self-signed certificate with CERTIFICATE_VERIFY_FAILED. |
token | Loads the vulnerable HcVaultKmsClient and demonstrates that it accepts the untrusted certificate. |
approle | Exercises the vulnerable AppRole authentication path and demonstrates exposure of role_id and secret_id. |
Install the PoC dependencies:
pip install hvac cryptography
Place the unpacked vulnerable wheel next to the PoC:
confluent_kafka-2.14.2-cp310-cp310-win_amd64/
└── confluent_kafka/
└── schema_registry/
└── ...
The PoC imports HcVaultKmsClient directly from the unpacked 2.14.2 package.
It stubs unrelated dependencies such as tink, allowing the vulnerable Vault-client construction to be tested without requiring a complete Kafka or KMS environment.
Use two terminals.