BleachBit 6.0.3 beta

We invite you to test BleachBit 6.0.3 beta. This release includes important security fixes, hardening, bug fixes, performance improvements, and minor enhancements.

Highlights of enhancements and features:

  • Early support for macOS.
  • DNF5 interpretation (for Fedora and similar)
  • Delete top-level log files in the Claude cleaner
  • Remember GUI zoom level
  • New cleaners for Python history, fish shell, Zsh shell
  • Redesigned CI download page for nightly Windows releases
  • Speed improvements

Special thanks to XhmikosR for making many of the improvements in this release.

Since version 6.0.2:

Security

Special thanks to XhmikosR for development of all these security fixes.

This release fixes several security vulnerabilities. Most are local attacks that require an attacker to be able to create files in a location BleachBit scans or writes to; two are remote attacks through the update check. All are fixed in this release.

Affected versions: all versions prior to 6.0.3.
Fixed in: 6.0.3.
CVE identifiers: not yet filed.

Symlink / reparse point following in delete, wipe, and truncate

Several code paths that delete, overwrite (wipe), or truncate files followed a symlink or Windows reparse point before acting on it. A local attacker who could plant a symlink in a directory BleachBit cleans (for example a world-writable temp directory, or a user's home when run with elevated privileges) could redirect the operation to an arbitrary file chosen by the attacker, causing that file to be deleted, overwritten, or truncated.

Affected paths: file truncation on all platforms, file wiping on POSIX and Windows, deep-scan results, writing of configuration / JSON / LibreOffice registrymodifications.xcu output, and deletion of locale contents through a symlinked locale directory. All of these now refuse to follow a symlink or reparse point and use O_NOFOLLOW / lchown / equivalent guards where applicable.

Privilege escalation when run under sudo

When BleachBit was run via sudo and invoked external tools (such as dnf, yum, or paccache) as root, it passed the invoking user's environment through unchanged. A hostile inherited environment (LD_PRELOAD, LD_LIBRARY_PATH, PATH pointing at user-writable directories, PYTHONPATH, BASH_ENV, and similar) could redirect the privileged child process and escalate to root.

Additionally, the chownself() function followed symlinks and matched the /root prefix non-canonically, so a symlink planted in the invoking user's home could redirect an os.chown call to an attacker-chosen target, and paths such as /rootfoo were treated as the /root directory.

Both are fixed: the root environment is sanitized before spawning children, and chownself() uses lchown and canonical path comparison.

Arbitrary command / registry actions from untrusted cleaner files

CleanerML and winapp2.ini files loaded from user-writable directories (the personal cleaners directory, or any world-writable directory) could declare process actions that run arbitrary commands, or winreg actions that delete arbitrary registry keys. A lower-integrity process that could write to those directories could thus execute commands or delete registry keys in the context of the BleachBit user.

Cleaner files are now classified as trusted or untrusted based on whether they live in the system cleaners directory, and process / winreg actions from untrusted files are ignored. Cleaner files in world-writable directories are skipped entirely.

Thank you to ElvisBlue for reporting this issue (CVE requested/pending).

SQLite URI and SQL injection in cookie / history handling

When BleachBit opened a SQLite database (browser cookies, history) by path, the path was interpolated into a file: URI without percent-encoding. A ? in the filename could be misparsed as the start of the URI query string and defeat the mode=ro flag, causing a database intended to be opened read-only to be opened read/write. Table and column names were also interpolated into SQL without quoting.

Paths are now percent-encoded, identifiers are quoted, and string literals are escaped.

XML external entity (XXE) and insecure update URLs

All XML parsing entry points (CleanerML, winapp2.ini, the update check, protected-path files, and Windows cleaner definitions) accepted DTDs with internal subsets, allowing an XML entity expansion attack from a malicious cleaner or update response.

Separately, the update check and winapp2 download accepted http:// URLs and the URL came from a remote XML response. A network attacker could perform a man-in-the-middle attack and substitute a malicious winapp2.ini, which would then be loaded as a cleaner with full trusted privileges.

DTDs with internal subsets are now rejected at every parsing entry point, and update / winapp2 URLs are required to be https://.

Windows DLL search path

On Windows, the DLL search path included the current directory (and, in the frozen builds commonly used by end users, the full PATH). A malicious DLL planted next to the executable, or in a directory on PATH, would be loaded with the user's privileges.

The search path is now hardened at startup via SetDefaultDllDirectories (frozen builds) or SetDllDirectoryW("") (non-frozen), before any DLL that could be targeted is loaded.

Additional hardening

  • open_url() now restricts URLs to the http(s) schemes, preventing an attacker-supplied URL from invoking arbitrary OS URL handlers.
  • Downloaded chaff models are now verified against a pinned SHA-512 hash, preventing a man-in-the-middle from substituting model files.
  • UAC argument encoding on Windows now uses subprocess.list2cmdline, closing an argument injection in the elevation path.
  • The debug log file and download directories are now created with restrictive permissions (0600 and 0700 respectively).

All Platforms

Safer shredding, race condition and crash fixes, performance improvements, and new cleaners.
  • ea3bc57f - Refuse to shred the working directory or its parent directory when shredding arbitrary files, preventing accidental data loss from a path that collapses to the current directory (such as an empty string, `.`, or `..`)
    From a terminal, run `bleachbit --shred .` and `bleachbit --shred ..` and verify each is refused with a warning instead of shredding the current/parent directory. Also run unit test `tests/TestCleaner.py::CleanerTestCase::test_create_simple_cleaner_refuses_cwd`.
  • b7a8bd19 - Fix cleaners sometimes missing files when the auto-hide feature scanned the same folder at startup
  • 106c34a6 - Delete top-level log files in the Claude cleaner
  • 301995c5 - Add support for filtering options by operating system in CleanerML files.
  • 2d1952c0 - Improve error handling and error reporting with SQLite operations
  • f93ff721 - Fix race condition where a setting change could be saved to disk in an inconsistent state
  • 08fd3c89 - Avoid initializing GTK, which opens a socket, when using CLI, TUI, or wxWidgets
  • 8b70f96d - Fix GTK crash from logging on worker threads
  • 036dda4e - Prevent crash in case of deeply nested directory tree
  • c0464c61 - Improve robustness in case of permission error while scanning a directory
  • 91b60036 - Skip malformed file URIs (such as `file://`) that resolved to an empty path and then to the working directory, which could have caused accidental data loss when shredding files dragged from a file manager. No standard file manager produces these URIs, so this is a defensive fix.
    Run the unit test `tests/TestFileUtilities.py::FileUtilitiesTestCase::test_uris_to_paths` covering `file:`, `file://`, and `file:///`; verify `file://` yields no path and a warning is logged.
  • 1a9e275d - Fix: when using F11 to toggle full screen, the opposite state was restored on next startup
  • 54c9e516 - Fix crash in desktop notifications caused by importing importlib instead of importlib.util before calling importlib.util.find_spec
    Trigger an action that shows a desktop notification and confirm it appears without error
  • d7c36077 - Warn instead of crashing on an invalid wildcard cleaner, on CLI with foo.*
  • 6a872350 - Remember zoom level
  • 67ac349c - Add cleaner for Python command history
  • 6be435f2 - Update coverage, requests, and certifi dependencies
  • fe2cac73 - Skip files that vanish between scan and size measurement, instead of aborting
    skip
  • 29999639 - Skip files that vanish between scan and size measurement, instead of aborting
    skip
  • a781e6ed - Skip cleaner XML files that disappear during startup
  • 53b86c1d - Fix race condition where a configuration change could be lost if settings were reloaded from disk at the same time
  • aadac56f - Improve performance by avoiding redundant directory metadata checks
  • 377eea2e - Cache sorted cleaner option keys instead of re-sorting each call
  • 7639e048 - Drop redundant path normalization in children_in_directory
  • bbd6a737 - Skip islink() in whitelisted_posix when keep-list is empty
  • 895d57d7 - Index cleaner actions by option to avoid quadratic dispatch
  • 505775c6 - Compile constant regexes once instead of per call
  • 64997999 - Update requests to 2.33.0, setuptools to 83.0.0 (except on Python 3.9)
  • ae1e980c - Cleaner.py: don't overwrite Cleaner attributes in subclass
  • 40c15674 - Improve detection of space saved reportde by APT autoclean
  • aa4015eb - Code cleanup
  • 541f425e - Improve detection of size reported by pacman
  • ba4a90fd - Add defensive check for GTK typelib directory
  • 7790a71c - Fix crash in SQLite error handler (Python 3 exceptions have no .message attribute) and when handling very short file URIs
  • 18e14e13 - Add defensive checks to prevent crash in csae of two delayed cleanup operations with same priority level
  • 03794cfa - Fix dark-background detection misidentifying some GTK themes as dark
  • d4e140ec - Add defensive checks for parsing XMLs with update information
  • 73d256de - Fix parsing of same_user attribute in CleanerML files
  • b53c30cc - Fix bug causing some cleaning operations to run twice, causing redundant work
  • 0a38c4e4 - Hoist bytes_to_human prefix lists to module constants
  • b0731ebd - Batch Chrome bookmark id lookups into chunked queries
  • f08c5761 - Use a set for mozilla favicon bookmark domain lookup
  • 5256b34d - Defer path join past deep-scan filename filters
  • 4c28ce77 - Iterate CleanerML elements without a throwaway list()
  • 72078b94 - Use frozensets for Options boolean_keys and int_keys
  • f8e6bbd1 - Build cleaner tree without re-sorting options twice
  • c66eb55c - Drop executable bit from assets and menu.ui
  • 8c2b9019 - Remove Python 2 coding declarations and __future__ import
  • d0f8b472 - Use zero-arg super() and drop redundant object base class
  • 12300bd3 - Use vanilla RawConfigParser.write in clean_ini: uses less code
  • d2a125df - Drop unused local variable assignments
  • c659c847 - Drop redundant comparisons in logical_ranges_to_extents and write_zero_fill
  • 6cdffd01 - Close devnull descriptor after redirecting stdout on BrokenPipeError
  • 3c2bd0db - Initialize locals before conditional assignment
  • 3fd32029 - fnmatch_translate: fix compatibility with Python 3.14
  • 047a4f88 - Fixed the Mozilla Firefox favicons cleaner, which could fail or incorrectly identify favicons to keep.
    On a system with Mozilla Firefox, run the Mozilla cleaner's favicons operation. Verify it completes without errors and that favicons not associated with bookmarks are removed while bookmarked favicons are preserved.
  • 6add79bc - Improve performance of the keep list (whitelist)
  • 70860387 - Improve efficiency in detecting file encoding
  • 06316540 - Fix crash in the debug log handler when an empty message is written, and append the full buffered text instead of just the last fragment
  • add44f3b - Improve randomness in generating filenames when wiping
  • 96f22d98 - Narrow the scope of the .angular deepscan cleaner
  • 190bf9a7 - Support chardet version 6
  • 4686c56b - Restrict open_url() to http(s) schemes
  • 456c0550 - Verify SHA-512 of downloaded chaff models
  • bd863c07 - Harden SQLite/URI construction in Special.py against injection
  • 7a7d11ca - Do not follow symlinks anywhere in wipe_write()/wipe_contents()
  • a2d404af - Reject all insecure winapp2 and update-check URLs
  • f71cb536 - Reject DTDs across all XML parsing entry points
  • c753694e - Reject reparse points when truncating files
  • a2219f7f - Skip junctions and symlinks in deep scan
  • b33d7f0f - Block process and winreg actions from untrusted cleaners

Windows

Security hardening, file wiping fixes, junction/symlink handling, Winapp2.ini improvements, and UI consistency with Linux.
  • e2ca6ee6 - Use absolute paths for ipconfig and taskkill to prevent binary-planting attack via executable search path
    To test ipconfig, clean DNS cache. To test taskkill, clean Windows Explorer - Thumbnails.
  • 86c70f59 - Fix secure file wiping skipping some clusters that should have been overwritten
    In the prefeferences, enable Overwriting contents. Then, delete files.
  • 91b14526 - Fix secure file wiping not fully overwriting fragmented files
    In the prefeferences, enable Overwriting contents. Then, delete files.
  • e0bb73e3 - Migrate Windows CI builds from ci.bleachbit.org to download.bleachbit.org/ci/ to consolidate on one subdomain. The new Windows CI download page has many enhancements such as filtering by branch and one-click to copy checksums.
  • 766f883f - Fix failure to start application from UNC (network) paths
    Place BleachBit portable in a path such as \\server\share and start the application: it should start.
  • b7788677 - Preserve the root of folders for temporary files
    Preview System - Temporary Files, and verify c:\windows\temp and %localappdata%\temp themselves are not listed. (Their contents may be listed.)
  • 8c2f2f66 - Fix toast notification was broken
    In the Windows frozen build, trigger a cleaning operation that takes longer than 10 seconds (e.g., deep scan), then switch focus away from the BleachBit window (e.g. focus another application) before it finishes. When the operation completes, a 'Done.' toast notification should appear. Verify it does not raise an error and that no notification backend traceback is logged.
  • 61358440 - Fix cleaning of folder shortcuts (junctions) and directory symlinks being skipped when the target folder contained files
    On Windows, create a junction or directory symlink pointing at a non-empty folder (e.g. put a file in the target), then run a cleaner that matches the junction/symlink path. Confirm the junction/symlink itself is removed while the target folder and its contents are left untouched. Repeat with an empty target folder: the junction/symlink should still be removed, and the (empty) target folder should remain.
  • b60a27e9 - Fix slashes in amule, Adobe Flash, Vuze, VLC
    Test the four cleaners.
  • db590127 - Fix Pale Moon base variable on Windows
    Clean Pale Moon
  • 8c186cc4 - Fixed winapp2.ini ExcludeKey with the *.* pattern, which should exclude the whole folder but was not working. The normal Winapp2.ini file does not contain this pattern, so the bug does not normally affect users.
    On Windows, create a folder with an extensionless file (e.g. 'deleteme') and a file with an extension (e.g. 'deleteme.log'). Define a winapp2.ini cleaner with FileKey1=|deleteme* and ExcludeKey1=PATH||*.*. Run the cleaner; both files should remain because *.* excludes the whole folder. Without the ExcludeKey, the extensionless file should be deleted.
  • 3ebef8af - When cleaning system.tmp, preserve new GLib D-Bus nonce files to not allow multiple instances of the application to be open.
    Preview System - Temporary Files, and there should be no new gdbus-nonce-file-XXXXXX files listed.
  • b32bfee5 - Handle interrupted console output
    Run `bleachbit.exe -p system.tmp | more` and type the letter Q. There should not be a traceback.
  • e9c1b974 - Move the menu from application icon on left side to hamburger on right side (now consistent with Linux)
    Verify the hamburger menu is usable.
  • c8d69146 - Clean Windows clipboard in TUI or wx GUI without requiring GTK
    Put text in the clipboard. Verify it can be pasted. Then, clean the clipboard. Verify it can no longer be pasted.
  • 194be82a - Write the GTK error report to a unique temporary file
  • 625a7f8f - Improve speed of importing Winapp2.ini cleaners
    In the preferences, enable Winapp2.ini cleaners. Restart the application, and browse and preview the Winapp2.ini cleaners to verify they imported correctly.
  • 9c9418ae - Skip unknown winapp2 options instead of aborting the section
  • 869d6c61 - Ensure that file wiping releases system resources in case of error
  • 6a026160 - Cache the Windows temporary directory for the keep list (whitelist)
    See other test: 'roots of folders for temporary files'
  • 4699d86f - Call match directly on precompiled winapp2 regexes
  • f8a412e1 - Cache the Windows version
    Used in Winapp2.ini import process, but low risk change.
  • c7b0535c - Hoist loop invariants in winapp2.ini parsing
    Low risk change.
  • e4a61e8e - Skip the unused world-writable stat on Windows
    Low risk change regarding importing CleanerML.
  • 50696597 - Refuse to follow a symlink when opening a file for wiping
  • dfcb7540 - Cap wildcard count in winapp2.ini glob patterns
  • d5b9fb76 - Use subprocess.list2cmdline for UAC argument encoding
  • d55f4245 - Harden Windows DLL search path against preloading attacks

POSIX

Improved reliability and compatibility across POSIX systems with better clipboard shredding, process handling, shell cleaners, error handling, and performance.
  • 9a362856 - Gracefully handle missing sqlite3: show message instead of crashing on startup
    Start BleachBit on a system without sqlite3. FreeBSD is a system that normally does not include sqlite.
  • 52d957a2 - Fix UnicodeDecodeError reading clipboard target names when shredding files from clipboard
    On Linux, select a file in a file manager, copy file to clipboard, and in BleachBit press CTRL+V to paste and shred it.
  • 1f170f14 - Fix shredding files from the clipboard, which failed to detect files in some cases
    Copy files in a file manager, then in BleachBit use the clipboard shred feature to verify the file paths are detected and shredded.
  • e818be82 - Handle spaces in process names, like for Google Chrome, from /proc and ps aux on POSIX systems without psutil installed
    Run BleachBit on Linux or macOS without psutil. Naturally observing process names with spaces seems most common on macOS.
  • d4ea92a9 - Add cleaner for fish shell
  • 7395b5d2 - Add cleaner for Zsh shell
  • 4fcbba35 - Fix error when file disappears when cleaning system temporary files
  • 5b678e8e - Suppress asyncio deprecation warnings with Python 3.14
  • 1a5742b4 - Add defensive check to prevent crash when the LOGNAME environment variable contains digit-like Unicode characters that are not valid decimal numbers
    On Linux, run: LOGNAME=$'\u00b2' python3 -c 'from bleachbit.General import get_real_uid; print(get_real_uid())'. Before the fix it raises ValueError; after, it falls through to os.getuid().
  • 28dd391a - Improve performance of open-files cache
  • 9dbdf23c - Fall back to PATH when a POSIX tool is not in a standard directory
  • ca9153bb - Do not delete locale contents through a symlinked locale directory
  • 21c85902 - Extract _open_nofollow_fd() and reuse it in truncate_file() and wipe_write()
  • c4ce96c8 - Create the debug log file with 0600 permissions
  • 4fe5c2e6 - Refuse to write config/JSON/registrymodifications.xcu output through a symlink
  • c17b54c0 - Create download directories with 0o700 permissions
  • 9452fc08 - Skip cleaner files in world-writable files or directories
  • e951fb3e - Sanitize PATH and drop code-loading env vars for subprocesses when root
  • 3a413af8 - Use absolute path for POSIX tools
  • c25efed7 - Harden chownself() against symlinks and non-canonical /root paths
  • 67c444b7 - Validate SUDO_UID before use

Linux

Fixed memory, process, filesystem, package-manager, profile-detection, whitelist, and Chromium-cleaning issues while improving DNF support.
  • 562bd818 - Report disk usage covered by DNF4 (instead of 0B). Improve accuracy of disk usage recovered by DNF autoremove (instead of estimation).
    Run DNF preview (without BleachBit) and note the expected size. Then, clean DNF with BleachBit and verify the size matches.
  • 49ce41c4 - Use XDG_CONFIG_HOME to find Firefox profile folders
  • 1b248c02 - Fix memory wiping on Linux with systemd
    Clean System - Memory on a Linux system with systemd. Example: Ubuntu 26.04
  • edba5e55 - Do not count SwapCached as free memory
    Run `python3 bleachbit.py --clean system.memory --debug` and note the `Physical free memory is X` line. Separately compute the expected value from the MemFree and Cached lines of `/proc/meminfo` (e.g. `awk '/^(MemFree|Cached):/{s+=$2} END{print s*1024}' /proc/meminfo`). The reported value should match and should NOT include the SwapCached line, which previously inflated it.
  • 5deea38a - Fix crash when enumerating running processes on Linux caused by non-numeric /proc entries such as /proc/self and /proc/thread-self
    On Linux, run a preview or operation that enumerates running processes and confirm it does not crash
  • 72f22fd2 - Handle vanishing file while checking open files
  • b57347f6 - Escape literal dots in the keep-list (whitelist) regexes to improve precision of pattern matching
  • d64da3ce - Relay error from DNF5 (package manager on Fedora, RHEL, and similar distributions)
  • 89f7891f - Fix DNF4 freed space parsing to use IEC units
  • 0c9d1b7e - Fix apt_autoclean and locale encoding regexes
  • 9c6639f7 - Fix incorrect debug message during swap cleaning
  • 0c963dc1 - Fix file descriptor leaks when an error occurs while reading /proc/swaps or wiping file contents
  • b235ca0e - Fix DNF clean without root permission
  • 8608ac50 - Fix overcleaning Chromium if installed from snap

macOS

Added early macOS-specific cleaner support and improved compatibility, path handling, username detection, synchronization, and automated testing.
  • ae425231 - Add early support for macOS-specific cleaners
  • 16a2fb9a - Switch macOS path protection to case-insensitive
  • af25daad - Create .zshrc to pass test_expanduser()
  • 2b4cccb8 - Fix get_real_username() on macOS
  • 7739d843 - Fix sed call in Makefile for BSD
  • 03e4209a - Add GitHub Actions workflow for macOS
  • 07fa7588 - Filter urllib3 warning about OpenSSL vs LibreSSL
  • 007fb58f - Fix sync() for macOS
  • afa8b4b6 - Fix low-level code to run on macOS
  • a68b2983 - Use absolute path for vm_stat on macOS

BSD

Improved FreeBSD support and testing infrastructure while improving portability in dependency installation, shell detection, Makefiles, and SQL.
  • 44e4715c - Add script to test FreeBSD 15 in VM from Linux
  • 222f3e0f - Use portable shell detection in Makefiles
  • 9ddda025 - Add support for FreeBSD in script that installs dependencies
  • bd22dceb - Use single quotes for string literals in SQL

Developers

Modernized CI/CD across Windows, macOS, and Linux with faster builds and tests, stronger security analysis, improved warnings coverage, refactoring, and translation testing
  • 2537230e - Set PYTHONWARNINGS in local Docker with Python 3.14 environment: catch more warnings during testing
  • 051614a5 - Fix DeprecationWarning in GTK GUI when PYTHONWARNINGS=error is set
    Set PYTHONWARNINGS=error and run GTK GUI
  • c9357cd6 - Use fast build mode for Windows builds, which disables English-only installer and size optimizations for CI builds found on download.bleachbit.org/ci/
  • 4db395c4 - Windows build: run UPX compression as parallel batches
  • 10391fe6 - CI: parallelize windows-test admin suite with pytest-xdist
  • 2554f303 - Skip building English-only installer to upload to https://download.bleachbit.org/ci/ except for tags (releases)
  • 66b1afd8 - Test also Ubuntu 26.04, swap Python 3.12 for 3.13
  • 24a0a758 - Streamline usage of "IS_*" system constants across the codebase
  • 6c36b05f - Add zimzor workflow, a static analysis tool for CI/CD systems
  • f536e6a0 - Fix potential code injection in CI during translation update
  • be17f0da - Optimize Windows pip caching and suppress version check
  • 25b610cf - CI: switch from AppVeyor to GitHub Actions for Windows
  • 8eaf5820 - Refactor some functions from FileUtilities and ProtectedPath to PathUtils
  • 5a43044a - Improve security of GitHub workflows
  • dd409c20 - Add CodeQL workflow for finding bugs
  • 0bb842bc - Add macOS support to script for installing dependencies
  • 181a7bb6 - Add translation (.po) tests
  • b9d10179 - Add pytest-rerunfailures to retry flaky clipboard test

For more info, see also commit log (since 6.0.2), list of closed issues (fixed in 6.0.3).

Downloads

⚠️ Notice: This release is currently being published. Downloads may not be available yet. Please check back in 15 minutes.

Downloads are available at download.bleachbit.org and SourceForge.

Linux users can download .deb or .rpm packages, while Windows users can download a digitally signed installer or a portable package.

After testing

If something is broken, please file a bug report.

Blog tags: