Planet Python
Last update: June 06, 2026 04:44 PM UTC
June 06, 2026
Armin Ronacher
Communities of Not
June 05, 2026
Will Kahn-Greene
Bleach 6.4.0 releases -- final release
What is it?
Bleach is a Python library for sanitizing and linkifying text from untrusted sources for safe usage in HTML.
Bleach v6.4.0 released!
Bleach 6.4.0 includes two security fixes, a fix to tinycss2 dependency requirements, and some other things.
See the changes here:
https://bleach.readthedocs.io/en/latest/changes.html#version-6-4-0-june-5th-2026
Bleach v6.4.0 is the final release
I haven't used Bleach on a project in years, but I still had some time to maintain it. That changed about a year ago when I got re-orged into a new role and I haven't had time to do any Bleach work since then.
To recap, Bleach sits on top of html5lib which hasn't been actively maintained in years. It is dangerous to maintain Bleach in that context.
We vendored html5lib so we could make adjustments to the library to keep Bleach going. This is not a sustainable approach, but it was ok for the short term.
Over the years, we've talked about other options:
find another library to switch to
take over html5lib development
fork html5lib and vendor and maintain our fork
write a new HTML parser
etc
None of those are feasible for me.
Bleach has been a solo-maintained project for a while now. The world is crazy and it's much harder to build a team of trusted maintainers now than it was (or at least, it sure feels that way). I don't see any possibility of increasing the maintenance team or passing it to someone else responsibly.
Switching contexts from my regular work to Bleach is really hard. Bleach is complicated, the problem domain is complicated, and there's a lot of nuanced context. I can't just switch gears, spend 15 minutes on Bleach to do something, and then switch back to the rest of my day. I periodically get nag messages about this which are entirely valid, but there's nothing I can do about it. It doesn't feel great.
Then in 2025, Emil, a long-time Bleach contributor, built justhtml which gives us an easy migration path off of Bleach. He even took the time to write a migration guide.
Thoughts and statistics
In 2019, when I stepped down the first time, I wrote a post on stepping down.
In 2023, when I deprecated the project, I wrote a post on Bleach 6.0.0 and deprecation.
From the first commit on 2010-02-18 to today's final commit on 2026-06-05, the Bleach project lasted 16 years, 3 months — 5,951 days, or about 16.29 years.
There were 64 releases.
There were roughly 960 commits.
From 80 roughly contributors
Top 3:
Will Kahn-Greene: 462
James Socol: 182
Greg Guthe: 133
Roughly 5,040 lines of Python code excluding the vendored html5lib.
I was maintainer from October 2015 to now--that's a little under 11 years.
It feels weird to end a project that's outlived many of the Mozilla sites and Python web frameworks it was designed to protect.
What happens now?
This is the end of the project.
Bleach. Last release.
If you're still using Bleach, I think you have three options:
End your project. Maybe you don't need to be maintaining your thing anymore? Use Bleach as your reason to exit and do something different with your time on Earth.
Switch to the sanitizer API. Rework your project to use the sanitizer API.
Swap Bleach out for justhtml. Emil provided a migration guide for switching from Bleach to justhtml.
Good luck with whatever option you choose!
Thanks!
Many thanks to James who created Bleach and gave it a set of first principles that guided our choices for 16 years.
Many thanks to Greg who I worked with on Bleach for a long while and maintained Bleach for several years. Working with Greg was always easy and his reviews were thoughtful and spot-on.
Many thanks to Emil who was a contributor to Bleach for a long while and created justhtml providing Bleach users a migration path.
Many thanks to Jonathan who, over the years, provided a lot of insight into how best to solve some of Bleach's more squirrely problems.
Many thanks to Sam who was an indispensible resource on HTML parsing and sanitizing text in the context of HTML.
Many thanks to all the users and contributors of Bleach!
Where to go for more
For more specifics on this release, see here: https://bleach.readthedocs.io/en/latest/changes.html#version-6-4-0-june-5th-2026
Documentation and quickstart here: https://bleach.readthedocs.io/en/latest/
Source code and issue tracker here: https://github.com/mozilla/bleach/
Real Python
The Real Python Podcast – Episode #298: Reducing the Size of Python Docker Containers
How can you easily reduce the size of a Python Docker container? What are the exceptions you should catch in your code? Christopher Trudeau is back on the show this week with another batch of PyCoder's Weekly articles and projects.
EuroPython Society
EuroPython Society at PyCon US 2026
This year we were back at PyCon US, and this time in sunny Long Beach, California.
We had a booth again, which has quickly become one of our favourite parts of the trip. It&aposs such a great chance to meet folks from other Python communities, catch up with
Bob Belderbos
How to Update Multiple Page Elements from One htmx Request
A button submits code, tests run, feedback appears. Standard htmx. But the submissions dropdown stays stale; the new submission is in the database, just not in the dropdown. One request, two elements to update.
Seth Michael Larson
Is the Super Smash Bros. Brawl donut from Mister Donut?
June 04, 2026
Kay Hayen
Nuitka Release 4.1
This is to inform you about the new stable release of Nuitka. It is the extremely compatible Python compiler, “download now”.
The Python Coding Stack
Down The Iterator Rabbit Hole
Following the trail when you have a chain of iterators
Real Python
Quiz: How to Read User Input From the Keyboard in Python
Try your hand at reading Python keyboard input with input(), handling errors, hiding passwords, and validating with PyInputPlus.
Python Software Foundation
PSF Strategic Plan 2026 Draft: Open for Community Feedback
Adrarsh Divakaran
Building AI Agents in Python
Core Dispatch
Core Dispatch #5
Welcome back to Core Dispatch! This edition covers May 18 through June 4, 2026. As promised, Python 3.15.0 beta 2 landed on June 2. Two more milestones are close behind: 3.13.14 and 3.14.6 on June 9, followed by 3.15.0 beta 3 on June 23. There's also a healthy batch of changes landing for 3.15: an
PyCon Ireland
CFP Deadline Moved to 31 July 2026
The PyCon Ireland 2026 Call for Proposals now closes on 31 July 2026. Here is why we brought the deadline forward and what it means for you.
Bob Belderbos
"Rust Is for People Who Want to Be Punished." Now Jochen Trusts It More Than Python.
Jochen Deister is a lawyer who codes for fun. He has years of Python behind him and no intention of ever being hired to program.
Three months ago, Rust was just a name to him, the language for "the big shots" with a notoriously steep learning curve. Then he built a JSON parser from scratch in Rust, and it ran faster than the equivalent in Python on every dataset he tested, up to 3.5x faster on some. "Holy F" he reacted when he saw the results.
June 03, 2026
Real Python
How to Use GitHub Copilot Code Review in Pull Requests
Learn how to use GitHub Copilot code review on pull requests for AI-assisted feedback, one-click fixes, and project-specific custom instructions.
Quiz: How to Use GitHub Copilot Code Review in Pull Requests
Test your knowledge of GitHub Copilot code review in pull requests, including custom instructions and automatic reviews.
Django Weblog
Django security releases issued: 6.0.6 and 5.2.15
In accordance with our security release policy, the Django team is issuing releases for Django 6.0.6 and Django 5.2.15. These releases address the security issues detailed below. We encourage all users of Django to upgrade as soon as possible.
CVE-2026-6873: Signed cookie salt namespace collision in django.http.HttpRequest.get_signed_cookie
get_signed_cookie() derived the signing salt by concatenating the cookie name (key) and salt arguments. When distinct name and salt pairs produced the same concatenation, cookies could be accepted
in a context different from the one where they were signed.
Cookies are now signed with an unambiguous salt derivation. For backwards compatibility, cookies signed by older Django versions are accepted until Django 7.0.
This issue has severity "low" according to the Django security policy.
Thanks to Peng Zhou for the report.
CVE-2026-7666: Potential unencrypted email transmission via STARTTLS in the SMTP backend
When using EMAIL_USE_TLS, a failed STARTTLS handshake could leave a partially-initialized connection that would subsequently be reused for sending email without encryption. This can occur with fail_silently=True, as used by send_mail() and BrokenLinkEmailsMiddleware, among others. Connections configured with EMAIL_USE_SSL are not affected.
This issue has severity "low" according to the Django security policy.
Thanks to Kasper Dupont for the report.
CVE-2026-8404: Potential exposure of private data via case-sensitive Cache-Control directives in UpdateCacheMiddleware
django.middleware.cache.UpdateCacheMiddleware and django.views.decorators.cache.cache_page decorator incorrectly cached responses marked with private Cache-Control directives when using mixed or uppercase values (e.g. Private).
The django.views.decorators.cache.cache_control decorator and django.utils.cache.patch_cache_control() function were not affected, since they normalize directives to lowercase. This issue only affects responses where Cache-Control is set manually.
This issue has severity "low" according to the Django security policy.
Thanks to Ahmed Badawe for the report.
CVE-2026-35193: Potential exposure of private data via missing Vary: Authorization in UpdateCacheMiddleware
django.middleware.cache.UpdateCacheMiddleware and django.views.decorators.cache.cache_page decorator allowed responses to requests bearing an Authorization header (and without Cache-Control: public) to be cached. To conform with the existing mechanism for constructing cache keys, responses to these requests will now vary on Authorization.
This issue has severity "low" according to the Django security policy.
Thanks to Shai Berger for the report.
CVE-2026-48587: Potential exposure of private data via whitespace padding in Vary header
django.middleware.cache.UpdateCacheMiddleware incorrectly cached responses whose Vary header values contained leading or trailing whitespace. Because has_vary_header() failed to strip that whitespace, a response with a Vary: * header (note the trailing space) was not recognized as containing the wildcard, causing it to be stored and potentially served from the cache when it should not have been.
This issue has severity "low" according to the Django security policy.
Thanks to Navid Rezazadeh for the report.
Affected supported versions
- Django main
- Django 6.1 (currently at alpha status)
- Django 6.0
- Django 5.2
Resolution
Patches to resolve the issue have been applied to Django's main, 6.1 (currently at alpha status), 6.0, and 5.2 branches. The patches may be obtained from the following changesets.
CVE-2026-6873: Signed cookie salt namespace collision in django.http.HttpRequest.get_signed_cookie
- On the main branch
- On the 6.1 branch
- On the 6.0 branch
- On the 5.2 branch
CVE-2026-7666: Potential unencrypted email transmission via STARTTLS in the SMTP backend
- On the main branch
- On the 6.1 branch
- On the 6.0 branch
- On the 5.2 branch
CVE-2026-8404: Potential exposure of private data via case-sensitive Cache-Control directives in UpdateCacheMiddleware
- On the main branch
- On the 6.1 branch
- On the 6.0 branch
- On the 5.2 branch
CVE-2026-35193: Potential exposure of private data via missing Vary: Authorization in UpdateCacheMiddleware
- On the main branch
- On the 6.1 branch
- On the 6.0 branch
- On the 5.2 branch
CVE-2026-48587: Potential exposure of private data via whitespace padding in Vary header
- On the main branch
- On the 6.1 branch
- On the 6.0 branch
- On the 5.2 branch
The following releases have been issued
The PGP key ID used for this release is Natalia Bidart: 2EE82A8D9470983E
General notes regarding security reporting
As always, we ask that potential security issues be reported via private email
to security@djangoproject.com, and not via Django's Trac instance, nor via
the Django Forum. Please see
our security policies for further
information.
Python GUIs
Authentication and Authorization with PyQt6 or PySide6 — Secure your desktop applications with login flows, token-based auth, and role-based access control
How can I add authentication and authorization to a PyQt6 application? Is there something built into Qt to make this easier?
Bob Belderbos
How to Tell if Your Python Mock Is Actually Working
A test can pass for the wrong reason. When you're mocking a third-party API call, the test might look green because the real API happened to return an error, not because your mock did anything at all.
June 02, 2026
PyCoder’s Weekly
Issue #737: Polars 1.41, Email, Great Docs, and More (2026-06-02)
Real Python
Structuring Your Python Script
Master Python script structure with best practices for shebangs, ordered imports, formatting with Ruff, constants, and a clean entry point.
PyCharm
Top Agentic Frameworks for Building Applications 2026
In 2026, the world of AI is changing at a serious pace. The days of AI systems dealing solely in single-prompt interactions are coming to an end. Instead, these models are evolving into agentic systems – long-running, goal-driven software enabled by agentic frameworks that are becoming a critical layer in modern application architecture. This rapid […]
Real Python
Quiz: Python's Format Mini-Language for Tidy Strings
Test your understanding of Python's format mini-language and how to use format specifiers to align text, control precision, and tidy your strings.
Quiz: Structuring Your Python Script
Check your understanding of Python script structure, including shebangs, import order, ruff formatting, constants, and a clean entry point.
Python Software Foundation
No Starch Press Humble Bundle: Grab a Deal and Support the PSF!
