Skip to content

Repository files navigation

gnu-pass-to-csv

CI PyPI Python Documentation License: MIT

Diagram showing an encrypted pass folder converted to a Proton Pass CSV without passphrase handling

Export a pass password store to a Proton Pass-compatible generic CSV. It is for people migrating login entries from the standard Unix password manager to Proton Pass. Unlike the previous implementation, it delegates decryption to pass and gpg-agent: the tool never asks for, stores, or forwards a GPG passphrase.

  • Preserves nested entry names and extracts common URL, email, username, note, and TOTP fields.
  • Produces deterministic UTF-8 CSV files with private 0600 permissions.
  • Fails atomically on a decryption error unless a partial export is explicitly requested.

Caution

The generated CSV contains every exported password in plaintext. Import it promptly, verify the result, then remove the file according to your system's secure-data handling policy. Do not commit, sync, email, or open it in an online spreadsheet.

Quick start

Requirements: Linux or macOS, Python 3.11+, a working pass installation, and an initialized password store that pass show <entry> can decrypt.

$ pipx install gnu-pass-to-csv
$ gnu-pass-to-csv --output ~/Downloads/proton-pass-import.csv
WARNING: the output CSV contains plaintext passwords; handle it as a secret.
Exported 42 entries to /home/alice/Downloads/proton-pass-import.csv

In Proton Pass, choose Settings → Import → Generic CSV, import the file, verify a representative sample including TOTP entries, and remove the CSV.

Follow the complete getting-started guide for safe destination selection, verification, and cleanup guidance.

pipx is recommended because it keeps command-line applications isolated. A regular installation also works:

python -m pip install gnu-pass-to-csv

How entries are mapped

Given a pass entry named Work/example.com/alice:

example-password
username: alice
email: alice@example.com
url: https://example.com/login
totp: JBSWY3DPEHPK3PXP
recovery codes are stored offline

the exporter writes one row with this schema:

name,url,email,username,password,note,totp,vault

The first decrypted line is always the password. Metadata labels are case-insensitive; url, uri, website, email, username, user, login, totp, otp, and otp-secret are recognized. Unknown lines remain in note. When no URL label exists, the exporter looks for a URL in the entry and then for a domain-shaped component in the entry name.

The output is intended for Proton Pass Generic CSV login imports. It does not represent cards, identities, aliases, attachments, or arbitrary custom fields.

Usage

gnu-pass-to-csv --help

Common options:

Option Purpose
-o, --output PATH Required destination; must be outside the password store
-s, --password-store-dir PATH Store location; defaults to PASSWORD_STORE_DIR or ~/.password-store
--vault NAME Value written to the CSV vault column; default Personal
--force Replace an existing output file
--skip-errors Create an explicitly partial export when entries fail
--max-workers N Run several pass processes after unlocking gpg-agent; default 1
--pass-executable PATH Select a compatible pass executable
--timeout SECONDS Per-entry timeout; default 60

Use a custom store either way:

PASSWORD_STORE_DIR=~/.password-store-work \
  gnu-pass-to-csv --output ~/Downloads/work-import.csv --vault Work

gnu-pass-to-csv \
  --password-store-dir ~/.password-store-work \
  --output ~/Downloads/work-import.csv \
  --vault Work

The output is never written inside the encrypted store. Existing files are not overwritten without --force. By default, any failed or empty entry aborts the whole export before the destination file is created.

Security model

The exporter discovers .gpg files but reads their plaintext only through the fixed command pass show -- <entry>. It does not invoke a shell and does not accept a passphrase option or environment variable. Authentication and prompts remain the responsibility of the user's existing gpg-agent configuration.

Plaintext necessarily exists in process memory and in the final CSV. Temporary output is created in the destination directory with mode 0600, flushed, and atomically installed. Filenames can still reveal account or service names in errors and process arguments; the tool never logs decrypted content.

See the detailed security model, the architecture, and the security policy. The complete documentation is available on GitHub Pages.

Version 2 migration

Version 2 is intentionally incompatible with 1.x:

  • --passphrase and GPG_PASSPHRASE were removed because command arguments can expose secrets to other local processes and diagnostics.
  • pass is now required and handles all GPG interaction through gpg-agent.
  • --output is required and refuses accidental overwrite or placement inside the encrypted store.
  • Runtime dependencies were removed; Python 3.11 through 3.14 are tested.

Development and support

Read CONTRIBUTING.md for the reproducible local quality gate, SUPPORT.md for usage help, and CHANGELOG.md for release history. Security reports belong in GitHub's private vulnerability reporting flow, not in public issues.

This independent project is not affiliated with, sponsored by, or endorsed by Proton AG or the password-store project. “Proton Pass” is used only to describe the supported import format.

License

MIT

About

Export a pass password store to a Proton Pass-compatible CSV without handling GPG passphrases.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages