惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
Scott Helme
Scott Helme
P
Palo Alto Networks Blog
S
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
量子位
G
Google Developers Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
NISL@THU
NISL@THU
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
AWS News Blog
AWS News Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
Security Archives - TechRepublic
Security Archives - TechRepublic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Secure Thoughts
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
P
Proofpoint News Feed
V
V2EX
Martin Fowler
Martin Fowler
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
SecWiki News
SecWiki News
罗磊的独立博客
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
The Last Watchdog
The Last Watchdog

alexwlchan’s notes

Disable the new message animations in WhatsApp Finding high-churn folders that bother Backblaze Always-on SSH agent forwarding with my Git pushes Managing the caption of a photo with AppleScript (but not PhotoKit) Goodhart’s and Campbell’s Law are different Notes from The Cornishman No. 176 (Spring 2026) Notes from The Cornishman No. 176 (Spring 2026) GitUp can’t diff text files larger than 8MB Home Testing the width of a page on a mobile device using Playwright Disable AirPods charging notifications Start a Caddy server in a subprocess during a Python session Filter a list of JSON object based on a list of tags HOME_GET_ME_HOME is a Citymapper Shortcuts action The FileExistsError exception exposes a filename attribute The red-lined bubble snail Useful type hints for Python How to truncate the middle of long command output AirPlay Receiver can interfere with Flask apps What’s the main prefix in SQLite queries? The file(1) command can read SQLite databases My randline project is tested by Crater Drawing an image with Liquid Glass using SwiftUI Previews Road signs in the Soviet union don’t have circular heads Setting up golink in my personal tailnet Create a file atomically in Go Get a map of IP addresses for devices in my tailnet The SQLite command line shell will count your unclosed parentheses Use SQL triggers to prevent overwriting a value Testing date formatting with date-fns-tz and different timezones The “strangler” pattern is named after a tree, not an act of violence Place with the same name, but different etymology
Why can’t Python connect to example.com?
A mistrusted certificate and Authority Information Access · 2026-03-28 · via alexwlchan’s notes

The Python SSL libraries only know about the certificates sent by the server and in my local store. They can’t retrieve missing certificates.

I’ve been experimenting with Python HTTP libraries, and I ran into an unexpected error connecting to example.com:

>>> import certifi, ssl, urllib.request
>>> ssl_context = ssl.create_default_context(cafile=certifi.where())
>>> urllib.request.urlopen("https://example.com", context=ssl_context)
Traceback (most recent call last):
  […]
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1081)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  […]
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1081)>

I get similar errors if I use httpx or requests.

If you look up this error, the usual advice is to make sure you’re using certifi, you have the latest version installed, run Install Certificates.command, and so on. Everything looks fine on my system, and I can connect to other websites just fine:

>>> certifi.__version__
'2026.02.25'
>>> certifi.where()
'/tmp/tmp.ZzvjQtkeZT/.venv/lib/python3.14/site-packages/certifi/cacert.pem'
>>> urllib.request.urlopen("https://alexwlchan.net", context=ssl_context)
<http.client.HTTPResponse object at 0x1056722f0>

I can also open example.com in my web browser, but not in Python – what’s up?

I found a certifi issue filed by Clément Beaujoin which describes this exact issue:

As of February 14, 2026, many automated tests and features relying on example.com began failing with ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1016).

This is caused by example.com (Cloudflare) transitioning to a new certificate chain that roots into AAA Certificate Services, which was officially distrusted by major certificate stores (including certifi) in early February 2026. Because Python’s requests/urllib3 does not support AIA (Authority Information Access) to fetch missing intermediates, the verification fails in environments with updated root stores, even though browsers (which support AIA) show the site as secure.

Alex Gaynor, one of the maintainers, explained this isn’t something certifi is going to change:

If example.com is not shipping the necessary intermediates, that’s a bug in their TLS serving configuration impacting all non-browser clients, not something we’re going to work around.

This explanation sounds right to me, but I wanted to understand more. Is there a way to print the certificate chain sent by the server, so I can see the missing intermediate and the AIA that tells my client where to fetch the missing intermediates? How could I have worked this out myself?

I tried running various openssl commands and Python scripts that were supposedly printing the certificate chain, but I don’t understand TLS well enough to really know what’s going on.

I was able to see that certifi no longer trusts AAA Certificate Services, and when. I tried older versions of certifi, and example.com loads with 2025.1.31 but not with 2025.4.26. Then I looked at the diff for 2025.4.26, and I can see a certificate with the same name being removed:

128-# Issuer: CN=AAA Certificate Services O=Comodo CA Limited

129-# Subject: CN=AAA Certificate Services O=Comodo CA Limited

130-# Label: "Comodo AAA Services root"

131-# Serial: 1

I also found a CPython issue where Authority Information Access is mentioned where the topic is discussed, and Alex explained that it’s unlikely to be added to Python:

No, and at this point [the issue] should probably be wontfix’d (IMO), as AIA chasing is relatively out of favor compared to intermediate preloading.

I still don’t really understand HTTPS or TLS certificates and I’m not sure how to fix this if I encounter another misconfigured website – but I only use example.com for testing, so for now I can just pick another website to test instead.

Why wasn’t this caught by my tests?

I use vcrpy to test my HTTP code, but it doesn’t do anything with TLS certificates, just unencrypted HTTP responses. I didn’t catch this until I tried regenerating my recorded cassettes, and discovered that the HTTPS certificate issues meant I could no longer do so.

Perhaps I need a procedure for regenerating vcrpy cassettes when I upgrade my dependencies, or on a fixed schedule?