Skip to content

SSL validation for outgoing requests in core and used libs not correct

High
MartinHjelmare published GHSA-m3pm-rpgg-5wj6 Feb 18, 2025

Package

Home Assistant Core

Affected versions

< 2024.1.6

Patched versions

2024.1.6

Description

Summary

Problem: Potential man-in-the-middle attacks due to missing SSL certificate verification in the project codebase and used third-party libraries.

Details

In the past, aiohttp-session/request had the parameter verify_ssl to control SSL certificate verification. This was a boolean value. In aiohttp 3.0, this parameter was deprecated in favor of the ssl parameter. Only when ssl is set to None or provided with a correct configured SSL context the standard SSL certificate verification will happen.

When migrating integrations in Home Assistant and libraries used by Home Assistant, in some cases the verify_ssl parameter value was just moved to the new ssl parameter. This resulted in these integrations and 3rd party libraries using request.ssl = True, which unintentionally turned off SSL certificate verification and opened up a man-in-the-middle attack vector.

Example:

When you scan the libraries used by the integrations in Home Assistant, you will find more issues like this.

The general handling in Home Assistant looks good, as homeassistant.helpers.aoihttp_client._async_get_connector handles it correctly.

PoC

  1. Check that expired.badssl.com:443 gives an SSL error in when connecting with curl or browser.
  2. Add the integration adguard with the setting host=expired.badssl.com, port=443, use-ssl=true, verify-ssl=true.
  3. Check the logs - you get a HTTP 403 response.

Expected behavior:

  1. The integration log shows an ssl.SSLCertVerificationError.

The following code shows the problem with ssl=True. No exception is raised when ssl=True (Python 3.11.6).

import asyncio
from ssl import SSLCertVerificationError

import aiohttp

BAD_URL = "https://expired.badssl.com/"


async def run_request(verify_ssl, result_placeholder: str):
    async with aiohttp.ClientSession() as session:
        exception_fired: bool = False
        try:
            await session.request("OPTIONS", BAD_URL, ssl=verify_ssl)
        except SSLCertVerificationError:
            exception_fired = True
        except Exception as error:
            print(error)
        else:
            exception_fired = False
        print(result_placeholder.format(exception_result=exception_fired))


# Case 1: ssl=False --> expected result: No exception
asyncio.run(run_request(False, "Test case 1: expected result: False - result: {exception_result}"))

# Case 2: ssl=None --> expected result: Exception
asyncio.run(run_request(None, "Test case 2: expected result: True - result: {exception_result}"))

# Case 3: ssl=True --> expected result: No Exception
asyncio.run(run_request(True, "Test case 3: expected result: False - result: {exception_result}"))

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L

CVE ID

CVE-2025-25305

Weaknesses

No CWEs

Credits