Pass filter='data' to extractall whenever you unpack a tar file in Python. It blocks absolute paths, paths that escape the destination, risky links, device files and special permission bits. Even so, the docs state that no filter blocks every dangerous archive feature, so untrusted archives still need inspection.
Why tar extraction needs a filter
A tar archive stores more than file contents. Each member has a path, permissions, an owner and sometimes a link target. A hostile archive can use those fields to write outside the folder you chose, create a symlink that later redirects a write, or set permission bits you did not expect.
Python 3.12 added extraction filters so you can limit those surprises. The filter runs on each member before it is written.
The three built in filters
'fully_trusted' honors all metadata exactly as stored. The docs say to use it only if you trust the archive completely or run your own verification.
'tar' honors most tar specific features but blocks the ones likely to be surprising or malicious. It strips leading slashes, refuses absolute paths and paths that end up outside the destination, and clears setuid, setgid, sticky and group or other write bits.
'data' does everything tar does and then goes further. It refuses links that point to absolute paths or outside the destination, refuses device files and pipes, and does not apply stored user and group ids. It is meant for cross platform data archives.
import tarfile
with tarfile.open("upload.tar.gz") as tf:
tf.extractall("/srv/work/unpacked", filter="data")
Which Python version changes the default
In Python 3.12 and 3.13, extraction without a filter behaves like fully_trusted unless you set one. The docs say that in Python 3.14 the default became data. If your code runs on several versions, set the filter explicitly so behavior is the same everywhere.
The docs also suggest checking for the feature with hasattr(tarfile, 'data_filter') instead of a version number, because filters can be backported to older versions as security updates.
What filters do not do
The docs say plainly that none of the available filters blocks all dangerous archive features. They do not prevent denial of service, such as an archive that expands to a huge amount of data. The data filter is described as not suited to extracting untrusted files without prior inspection.
Practical limits to add yourself:
- Check the member count and the total uncompressed size before extracting.
- Extract into a fresh, empty directory with no sensitive neighbors.
- Run extraction in a low privilege process.
- Never extract archives from untrusted sources without inspecting them first, as the docs put it.
Custom filters
The filter argument also accepts a callable that takes a member and a path and returns the member or None to skip it. This is useful for allowing only certain file types or rejecting anything over a size.
Related reading: a recent tarfile filter bypass advisory shows why keeping Python patched matters even when you use filters.
Safeguard's dependency scanning and reachability analysis helps you see which of your own packages unpack archives. Try the free scan at gold.safeguard.sh/scan.
Quick check
Is filter='data' enough for archives from the internet?
No. The docs say it is not suited to untrusted files without prior inspection, because it does not stop denial of service or every dangerous feature.
Do I need to set a filter on Python 3.14?
The default is data there, but setting it explicitly keeps older interpreters consistent and makes your intent visible.
Sources
Last reviewed: 19 October 2026.