Skip to content

Guard tar/zip extraction against path-traversal (CVE-2007-4559)#2458

Open
dsblank wants to merge 2 commits into
gramps-project:maintenance/gramps61from
dsblank:fix/gpkg-tarfile-path-traversal
Open

Guard tar/zip extraction against path-traversal (CVE-2007-4559)#2458
dsblank wants to merge 2 commits into
gramps-project:maintenance/gramps61from
dsblank:fix/gpkg-tarfile-path-traversal

Conversation

@dsblank

@dsblank dsblank commented Jul 4, 2026

Copy link
Copy Markdown
Member

Summary

  • The .gpkg importer (gramps/plugins/importer/importgpkg.py) extracted archive members with tarfile.TarFile.extract() without validating their paths, vulnerable to CVE-2007-4559 / "Zip Slip" (see also python/cpython#73974).
  • The addon/plugin installer (load_addon_file() in gramps/gen/plug/utils.py) has the same class of bug in two places: the custom Zipfile.extractall() wrapper (used for .zip addon packages) and a bare tarfile.TarFile.extractall() call (used for .tar.gz/.tgz addon packages). This is arguably higher risk than the .gpkg case since addon packages are fetched from a URL (the Gramps addon server or a configured mirror) rather than a file the user deliberately imports.
  • In each case a crafted archive could use an absolute path, a ../ path-traversal member name, or a symlink/hardlink to create or overwrite files outside the intended target directory (media directory for .gpkg, plugin directory for addons).
  • Added a shared gramps/gen/utils/safearchive.py module (is_safe_archive_member(), is_safe_tar_member()) and applied it at all three extraction sites before any member is written to disk. This is a self-contained workaround that does not rely on Python 3.12+'s filter= extraction parameter (PEP 706), so it works across all Python versions Gramps supports (3.10+).

Fixes #12911.

Test plan

  • gramps/gen/utils/test/safearchive_test.py — unit tests for the shared helpers (absolute paths, ../ traversal, symlink/hardlink escapes).
  • gramps/plugins/importer/test/importgpkg_test.py — integration-style test against a crafted malicious tar archive.
  • Manual checks: crafted malicious zip/tar member is rejected via Zipfile.extractall() (raises ValueError) and via the addon-installer's tar-member pre-check; a benign zip with a real directory entry still extracts correctly (no regression).
  • python3 -m unittest gramps.gen.utils.test.safearchive_test gramps.plugins.importer.test.importgpkg_test -v — all pass.
  • black --check on all changed files.
  • mypy (full project) — no issues.

🤖 Generated with Claude Code

Gramps package (.gpkg) import extracted archive members with
TarFile.extract() without checking their paths. A crafted .gpkg file
could use an absolute path, a "../" path-traversal name, or a
symlink/hardlink to create or overwrite files outside the intended
media directory. Each archive member's resolved path is now validated
before extraction, and extraction is aborted if any member would
escape the target directory.

Fixes #12911.
@emyoulation

Copy link
Copy Markdown
Contributor

@DavidMStraub
Is this kind of protection needed for the GEDCOM7 zip importer? Does it use relative paths for media that might susceptible to this kind of attack?

@DavidMStraub

Copy link
Copy Markdown
Member

.gpkg is disallowed in Gramps Web API precisely because it's not safe.

There was a path traversal vulnerability in the media importer though, see GHSA-m5gr-86j6-99jp and gramps-project/gramps-web-api@3ed4342.

The addon/plugin installer (load_addon_file() in
gramps/gen/plug/utils.py) downloads or opens a .zip or .tar.gz addon
package and extracts it into the user's plugin directory. Neither the
custom Zipfile.extractall() wrapper nor the tarfile.TarFile.extractall()
call validated member paths, so a crafted or MITM'd addon package could
use an absolute path, a "../" path-traversal name, or a symlink/hardlink
to create or overwrite files outside the intended plugin directory
(the same class of bug as CVE-2007-4559, aka "Zip Slip").

The path-traversal checks added for the .gpkg importer in the previous
commit have been factored out into a shared
gramps.gen.utils.safearchive module and are now also applied here
before any zip or tar member is extracted.

Fixes #12911.
@dsblank dsblank changed the title Guard .gpkg import against tarfile path-traversal (CVE-2007-4559) Guard tar/zip extraction against path-traversal (CVE-2007-4559) Jul 6, 2026
@dsblank

dsblank commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

Thank you @emyoulation for mentioning zip importer (in general). I have updated the PR to fix all known security issues in gramps zip/tar importing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants