Skip to content

refactor: remove legacy importer and exporter#5153

Open
chrislongros wants to merge 3 commits into
ankitects:mainfrom
chrislongros:fix-apkg-path-traversal
Open

refactor: remove legacy importer and exporter#5153
chrislongros wants to merge 3 commits into
ankitects:mainfrom
chrislongros:fix-apkg-path-traversal

Conversation

@chrislongros

@chrislongros chrislongros commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Linked issue (required)

Closes #5167

Motivation

The .apkg media uses os.path.commonprefix, which compares characters, not path components. A media filename resolving to a sibling directory that shares the media folder's name prefix passes the check, so a malicious .apkg can write outside collection.media (path traversal / arbitrary file write).

A second commit removes the legacy importer entirely. The legacy import option was removed in #3536, leaving pylib/anki/importing, qt/aqt/importing.py and their dialog forms unreachable.

The third commit removes the legacy exporter and adds a realpath check instead of the commonprefix.

Steps to reproduce

  1. Make an .apkg whose media maps a file into a sibling directory whose name begins with the media folder's name.
  2. Import it.
  3. Before: written outside collection.media. After: "Invalid file".

Testing performed

Tested by importing .apkg and .csv decks via File > Import on the main branch and on the PR branch.
Cards import completes without problems.
Also tested a deck and collection export with support to older Anki versions enabled. It works fine.

os.path.commonprefix matches
characters rather than path components. Use startswith(dir + os.sep)
instead to prevent path traversal.
The legacy import option was removed in ankitects#3536. Remove the dead code
associated with the legacy importer.
@chrislongros
chrislongros force-pushed the fix-apkg-path-traversal branch from 74052c5 to e41f234 Compare July 17, 2026 16:23
@dae

dae commented Jul 18, 2026

Copy link
Copy Markdown
Member

We might want to clean up legacy_import_export() as well? It's still referenced by the browser.

Dead code since ankitects#3536 made legacy_import_export() always return False.
Also fix the export dialog's string-based commonprefix path check.
@chrislongros chrislongros changed the title fix: prevent path traversal in apkg media import refactor: remove legacy importer and exporter Jul 18, 2026
Comment on lines -129 to 132
NOTE: Updates to the import/export code are expected in the coming
months, and this hook may be replaced with another solution at that
time. Tracked on https://github.com/ankitects/anki/issues/1018
</Warning>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is issue #1018 still relevant or can it be closed by this PR?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still relevant for future work on built-in collaboration features.

@github-actions github-actions Bot closed this Jul 19, 2026
@abdnh abdnh reopened this Jul 19, 2026
@ankitects ankitects deleted a comment from github-actions Bot Jul 19, 2026
@chrislongros

Copy link
Copy Markdown
Contributor Author

We might want to clean up legacy_import_export() as well? It's still referenced by the browser.

I submitted a new follow up commit.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Path traversal in .apkg media import (os.path.commonprefix)

4 participants