From 0f00478fe46cec173dd6cfd7c01f541b8265a5f7 Mon Sep 17 00:00:00 2001 From: Max Rekunchak Date: Sun, 12 Jul 2026 02:02:05 +0300 Subject: [PATCH] Fix DOWNLOADER_CLIENT_TLS_CIPHERS=None to enable Twisted default ciphers Closes #7499 When DOWNLOADER_CLIENT_TLS_CIPHERS is set to None, acceptableCiphers was still passed to CertificateOptions (as None), causing Twisted to fall back to OpenSSL's DEFAULT cipher list instead of using its own curated, stricter defaults. Fix: omit the acceptableCiphers kwarg entirely when tls_ciphers is None, letting Twisted use its own internal defaults. Changes: - contextfactory.py: conditionally include acceptableCiphers kwarg - tls.py: remove deprecated DEFAULT_CIPHERS attribute (no callers) - tests: update test_none to assert acceptableCiphers is not in kwargs --- scrapy/core/downloader/contextfactory.py | 7 ++++++- scrapy/core/downloader/tls.py | 7 ------- tests/test_core_downloader.py | 6 ++++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py index a934cbbc7..f09f5a919 100644 --- a/scrapy/core/downloader/contextfactory.py +++ b/scrapy/core/downloader/contextfactory.py @@ -120,8 +120,13 @@ class _ScrapyClientContextFactory(BrowserLikePolicyForHTTPS): def _get_cert_options_kwargs(self) -> dict[str, Any]: kwargs: dict[str, Any] = { "fixBrokenPeers": True, - "acceptableCiphers": self.tls_ciphers, } + # Pass acceptableCiphers to Twisted only when explicitly set. + # When None (user set DOWNLOADER_CLIENT_TLS_CIPHERS=None), + # omit the kwarg so Twisted uses its own curated cipher list + # instead of falling back to OpenSSL's DEFAULT. + if self.tls_ciphers is not None: + kwargs["acceptableCiphers"] = self.tls_ciphers if self.tls_min_version or self.tls_max_version: kwargs.update( _get_cert_options_version_kwargs( diff --git a/scrapy/core/downloader/tls.py b/scrapy/core/downloader/tls.py index c5cf1156d..6433365ba 100644 --- a/scrapy/core/downloader/tls.py +++ b/scrapy/core/downloader/tls.py @@ -43,13 +43,6 @@ _openssl_methods: dict[str, int] = { def __getattr__(name: str) -> Any: - if name == "DEFAULT_CIPHERS": - warnings.warn( - "scrapy.core.downloader.tls.DEFAULT_CIPHERS is deprecated.", - ScrapyDeprecationWarning, - stacklevel=2, - ) - return AcceptableCiphers.fromOpenSSLCipherString("DEFAULT") deprecated = { "METHOD_TLS": "TLS", "METHOD_TLSv10": "TLSv1.0", diff --git a/tests/test_core_downloader.py b/tests/test_core_downloader.py index fdd5edc27..e87a08b36 100644 --- a/tests/test_core_downloader.py +++ b/tests/test_core_downloader.py @@ -215,11 +215,13 @@ class TestContextFactoryCiphers(TestContextFactoryBase): @coroutine_test async def test_none(self, server_url: str) -> None: - """A None value enables the Twisted default ciphers.""" + """When DOWNLOADER_CLIENT_TLS_CIPHERS=None, acceptableCiphers is + not passed to CertificateOptions, so Twisted uses its own curated + cipher list instead of falling back to OpenSSL DEFAULT.""" crawler = get_crawler(settings_dict={"DOWNLOADER_CLIENT_TLS_CIPHERS": None}) factory = build_from_crawler(_ScrapyClientContextFactory, crawler) assert factory.tls_ciphers is None - assert factory._get_cert_options_kwargs()["acceptableCiphers"] is None + assert "acceptableCiphers" not in factory._get_cert_options_kwargs() await self._assert_factory_works(server_url, factory)