Skip to content

Releases: mr-grj/ciphermoth

CipherMoth v3.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 23:35

A security key that takes part in the encryption itself, and a way back if you forget your master password.

Added

  • Require a security key (Settings → Security). Register a FIDO2 key such as a YubiKey and the vault is encrypted with your master password and the key together: a secret only that key can produce (its WebAuthn PRF / CTAP2 hmac-secret output) joins the master password in the key record. A copied vault file, snapshot or a stolen master password opens nothing without the key, and the file alone no longer even lets anyone test password guesses. Every unlock also checks the key's signature over a fresh, single-use challenge, its user verification (its PIN) and its signature counter (clone detection). Register a backup key too; any registered key unlocks. Works in Chrome, Edge and Firefox (HTTPS or localhost), in the desktop app (which talks to the key over USB) and in the CLI. Biometric unlock keeps working and needs the key to turn on.
  • Recovery code (Settings → Security). A one-time code (160 random bits, eight groups of four) that sets a new master password if you forget yours, and gets you in if you lose your security keys: Forgot master password? on the unlock screen, or ciphermoth recover. Using it re-keys the vault, logs every other session out and shows a new code; your keys keep working unless you say you lost them. The vault stores only a public key and the vault key sealed to it (X25519), bound to the vault key, so a master password change keeps the code working without knowing it.
  • Change the master password from the app (Settings → Security), with the strength meter. It re-encrypts everything under a new vault key and logs you out everywhere.
  • Every security change (keys, recovery code, master password, biometric unlock, backups) asks for the master password again, and for the security key once one is required, so an unattended unlocked screen cannot make it.
  • API: POST /api/master_password/unlock/challenge, POST /api/master_password/recover, GET /api/security, POST /api/security/challenge, POST /api/security/keys/options, POST /api/security/keys, POST /api/security/keys/{id}/remove, POST /api/security/recovery-code and .../remove; unlock, backup, master password change and biometric enrollment accept a security_key answer; /api/meta lists security-keys and recovery-code; /api/master_password/status says whether a key is required and whether a recovery code exists. CLI: unlock and backup ask the key (and its PIN) over USB; new ciphermoth recover.

Changed

  • Vault schema 3. The first start of this release upgrades a 3.3.0 vault in place, in one transaction, after keeping a copy of it in snapshots/before-schema-3-<time>.db. Nothing existing changes: a vault without keys or a recovery code works exactly as before. Older releases refuse a schema 3 vault (restore that snapshot to go back).
  • The settings dialog has General and Security tabs.

Download the file for your OS and CPU below. macOS: open the DMG and drag CipherMoth to Applications. Windows: run the installer. Linux: use the AppImage or install the .deb. Create a master password on first launch.

These installers have no Apple notarization or Microsoft verified-publisher certificate. Tauri updater signatures are separate and mandatory. See installation and update instructions.

AppImage supports built-in updates; Debian uses package updates. SHA256SUMS and per-target source/build provenance are attached.

CipherMoth v3.3.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 14:28

Tidy many secrets at once, and reach the everyday actions with a right-click.

Added

  • Select several entries and move them to the trash together. Tick rows (the header box selects every entry the current search or folder shows); the selection stays across pages and searches, a bar shows how many are selected and how many the current filter hides, and the confirmation lists every name. The move is all or nothing, and the toast offers Undo. Delete or Backspace moves the selection (or the focused row) to the trash, Escape clears it.

  • The Trash has the same selection, with Restore and Delete forever for many entries at once. Deleting forever lists what goes and never confirms on Enter by itself; a restore that would clash with an active name changes nothing and says which name.

  • Quick actions: double-click a row (or press Enter) to edit it, and right-click it for Copy username, Copy password (or note), Copy 2FA code, Copy website, Open website, Edit, Duplicate, favorite and Move to Trash. Right-clicking a selected row acts on the whole selection. Shift+right-click keeps the browser's own menu.

  • API: POST /api/vault/entries/trash, POST /api/vault/trash/restore and POST /api/vault/trash/purge act on up to 10,000 entries in one transaction; /api/meta lists the bulk-entry-actions feature. CLI: ciphermoth password delete takes several names and moves them together.

  • Clear the search with one click: an × appears in the search box once you type (Escape works too), and an empty result offers "Clear search".

  • A real menu bar in the macOS app: New Login (⌘N), New Secure Note (⇧⌘N), Import, Back Up Vault, Find (⌘F), Trash, Vault Health, Settings (⌘,), Lock Vault (⇧⌘L), Check for Updates, a light/dark switch, and Help links to the project, its release notes and its issue tracker. Vault items are greyed out while the vault is locked, and a menu action never replaces a dialog you are working in.

Changed

  • Copy toasts say what was copied ("Password copied.").

Fixed

  • Quitting the desktop app (⌘Q) froze the window for about three seconds: the shutdown waited on the window it was trying to reset. It now closes at once (about 0.2 s) and still shuts the vault core down cleanly.

Download the file for your OS and CPU below. macOS: open the DMG and drag CipherMoth to Applications. Windows: run the installer. Linux: use the AppImage or install the .deb. Create a master password on first launch.

These installers have no Apple notarization or Microsoft verified-publisher certificate. Tauri updater signatures are separate and mandatory. See installation and update instructions.

AppImage supports built-in updates; Debian uses package updates. SHA256SUMS and per-target source/build provenance are attached.

CipherMoth v3.2.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 17:06

Unlock with a touch, and a vault table that fits your window.

Added

  • Unlock with Touch ID or another biometric, as an option in Settings, next to the master password. The desktop app on Macs with Touch ID uses a Secure Enclave key tied to the current fingerprints; browsers use a passkey with the PRF extension (HTTPS or localhost, on a device with a fingerprint, face or PIN unlock). Turning it on needs the master password and it works only on that device. The master password is asked for again every 7, 14 or 30 days (14 by default) so it is not forgotten, and changing the master password ends every biometric unlock. The vault format and schema are unchanged. The CLI keeps using the master password.

Changed

  • The vault table scrolls on its own: the app bar, search and page controls stay in place at every window size. The page only scrolls when a window is too short to fit the table (landscape phones). Page size choices now go up to 100 (default 25) and are remembered per browser. A new search or folder filter returns to the first page, and each page starts at its first row.
  • Smaller screens: the toolbar buttons become icons, unused or unfitting columns (folder, tags, 2FA) stay hidden until needed, row actions stay visible on touch screens, and the theme toggle no longer covers the page arrows.

Security

  • Update certifi to 2026.10.23, which no longer trusts the emSign root behind compromised eMudhra intermediates (PYSEC-2026-4320). This affects the ciphermoth CLI inside the Docker backend image when it connects to a remote HTTPS API; the desktop app does not include certifi.
  • Update the frontend image's file server dependency fast-uri and the frontend's follow-redirects, Vite, Vitest and zod to versions with published fixes.

Download the file for your OS and CPU below. macOS: open the DMG and drag CipherMoth to Applications. Windows: run the installer. Linux: use the AppImage or install the .deb. Create a master password on first launch.

These installers have no Apple notarization or Microsoft verified-publisher certificate. Tauri updater signatures are separate and mandatory. See installation and update instructions.

AppImage supports built-in updates; Debian uses package updates. SHA256SUMS and per-target source/build provenance are attached.

CipherMoth v3.1.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 14:21

CipherMoth is now a standalone desktop password manager for macOS, Windows and Linux. Your secrets stay in the dark; Docker remains available.

Added

  • Native desktop installers for Apple Silicon/Intel macOS, Windows x64/ARM64 and Linux x64/ARM64, with bundled Python 3.13 and SQLite. No development tools or backend listener.
  • Optional GitHub release checks and user-confirmed Tauri updates, with mandatory signatures binding the release version and native architecture. Downloads can be canceled; verified installs lock the vault and preserve its local data.
  • DMGs, NSIS installers, AppImages, Debian packages, updater signatures, latest.json, SHA-256 checksums and source provenance in one release. AppImage supports built-in updates; Debian uses manual package updates.
  • Native clipboard clearing, automatic locking, private binary IPC and complete encrypted backups using the existing vault format. Passwords, notes, attachments, TOTP, generator, folders, history and Trash are shared with the Docker edition.

Changed

  • Production app identity is com.ciphermoth.desktop, with a separate vault from Alpha and Docker. Existing vaults are never moved automatically.
  • Updater credentials are restricted to trusted release jobs. Installer signing for Apple/Microsoft verified-publisher status is not provided; OS warnings and managed-device restrictions may apply.
  • Preserve explicitly injected empty session stores, enforcing the desktop single-session policy while retaining the server API.
  • Wait for saved settings before checking for updates, so a disabled preference is respected after unlocking.

Download the file for your OS and CPU below. macOS: open the DMG and drag CipherMoth to Applications. Windows: run the installer. Linux: use the AppImage or install the .deb. Create a master password on first launch.

These installers have no Apple notarization or Microsoft verified-publisher certificate. Tauri updater signatures are separate and mandatory. See installation and update instructions.

AppImage supports built-in updates; Debian uses package updates. SHA256SUMS and per-target source/build provenance are attached.

Validation: release CI passed on commit a792ed789ba5de71e670397febcb0d675ba5cf67: all six native production packages, installed GUI suites, and 20 real updater checks per target, plus both architectures of the cosign-verified Docker images. Updates were installed between isolated packaged versions and preserved vault contents, attachments and encrypted backups. Public downloads, all six updater signatures, every SHA-256 checksum and the live v3.1.0 no-update result were independently verified after publication. CI does not simulate internet reputation dialogs or organization-specific security policies.

Known upstream dependency advisory: the GTK3 chain includes glib 0.18.5, affected by RUSTSEC-2024-0429. No calls to the affected string-array iterator were found in the checked application/dependency sources; the repository alert remains tracked.

CipherMoth v3.0.0

Choose a tag to compare

@mr-grj mr-grj released this 16 Oct 07:45

CipherMoth 3.0 encrypts entry metadata and introduces complete, authenticated encrypted backups.

Names, usernames, descriptions and all other user-entered entry contents now live inside authenticated AES-256-GCM documents. This release uses a random 256-bit vault key wrapped under an Argon2id-derived key, with a domain-separated password commitment instead of the old bcrypt verifier. Changing the master password generates a new vault key and re-encrypts every entry and attachment. Clients continue to receive opaque session tokens; the Python core owns the vault key.

Complete encrypted backups

  • .cmbackup exports include active entries, Trash, password history, attachment names and bytes, timestamps and settings.
  • Backups use Argon2id password protection and authenticated sequential frames. Wrong passwords, tampering, truncation, reordering and substitution are rejected atomically.
  • The backup password is the master password at export time. Use that password when restoring, including after a password change or into another vault.
  • Restoring into a populated vault merges entries. “Skip” keeps an existing active name; “overwrite” moves the existing entry, history and attachments to Trash before replacing it. Existing Trash entries with matching names and deletion times are skipped. Settings restore only into an empty vault.
  • Limits: 1 GiB per complete backup, 1,000,001 frames including the envelope, 64 MiB per entry frame, and 5 MiB per attachment frame. Capacity checks reject supported writes before the vault exceeds backup capacity.
  • Exports use a consistent read snapshot, bounded resources and cleanup after errors or cancellation. Check that your browser saved the downloaded file.

Damaged records are isolated and reported in the UI and CLI. Complete backups and master-password rotation refuse damaged records rather than silently omitting them. Recovery is an explicit removal of damaged rows or restoration of an earlier snapshot.

CipherMoth remains SQLite only: two Docker containers and one persistent vault volume. One-click updates remain unavailable; updates are manual.

Breaking change: existing v2.0.0 vaults

3.0 does not open or automatically migrate a v2.0.0 SQLite vault. It refuses the old file unchanged and never silently erases it. New vaults use the new format directly.

A v2.0.0 ZIP export restores active entries only. Old ZIP exports do not include Trash, history, attachments or settings. A raw v2 SQLite snapshot is for recovery with v2; it cannot be opened or imported by v3. Likewise, rolling back to v2 cannot open a v3 vault.

Follow the complete upgrade and rollback guide:

  1. Before updating, export a backup from v2.0.0 and separately download any attachments you want to retain. Take an integrity-checked snapshot using ciphermoth-admin snapshot, and keep it for recovery with v2.

  2. Set CIPHERMOTH_VERSION=3.0.0 in .env, pull the new images and verify their signatures as documented.

  3. With the backend stopped, explicitly preserve the old vault:

    docker compose -f docker-compose.prod.yml pull
    docker compose -f docker-compose.prod.yml stop backend
    docker compose -f docker-compose.prod.yml run --rm backend ciphermoth-admin set-aside
    docker compose -f docker-compose.prod.yml up -d

    set-aside asks for confirmation and moves the old SQLite file and its WAL unchanged into /data/snapshots/set-aside-<time>/. It deletes nothing.

  4. Create a new master password in the web UI, then import the v2 ZIP with the password used to create it. Restore downloaded attachments separately and make a new complete .cmbackup.

  5. Keep the preserved old vault and snapshot until you no longer need rollback. They retain the old format's plaintext metadata; the guide explains deliberate cleanup and rollback. No automatic deletion runs.

Use the CLI shipped with v3.0.0. For PostgreSQL-era installations, follow the separate manual fresh-install procedure; the old Compose configuration is refused.

Security scope

Entry encryption does not encrypt the entire SQLite file. Counts, timestamps, sizes, Trash membership, attachment relationships, equal-name indexes and timeout settings remain visible. Rollback of a file or row and deletion are not detected. Earlier snapshots and backups retain the password and protection they were created with.

This release has automated verification and code-agent review, not a formal third-party security certification or human cryptographic audit. See the vault and backup format specification, security model, and full changelog.

CipherMoth v2.0.0

Choose a tag to compare

@mr-grj mr-grj released this 15 Oct 06:58

CipherMoth 2.0 now uses SQLite, with no PostgreSQL server required.

A fresh installation is two containers (backend and frontend) and one Docker volume holding the vault as a single SQLite file. There's no database service, no database credentials, and the .env file is optional.

curl -fsSL https://raw.githubusercontent.com/mr-grj/ciphermoth/master/install.sh | sh

Coming from 1.x (PostgreSQL)

2.0 needs a fresh installation: it starts a new, empty vault.

  • Your PostgreSQL vault is not converted. It's also never deleted: the PostgreSQL volume stays exactly as it is, and pinning CIPHERMOTH_VERSION=1.6.0 brings the old version back.
  • To bring your active entries along, export an encrypted backup ZIP in 1.6.0 and import it into the new vault. The ZIP leaves out the trash, password history, attachments and settings.
  • Safety nets:
    • A 2.0 backend started from a 1.x compose file exits with a message and creates no vault.
    • The 1.x one-click updater refuses 2.0 before it changes anything.
    • install.sh stops when it finds an old PostgreSQL install, unless you confirm, and keeps backups of your compose file and .env.

The full steps, and how to go back, are in docs/UPDATING.md.

Updating from 2.0 on

One-click updates are temporarily unavailable, because the old updater was built around PostgreSQL. Update by hand, taking a complete snapshot of the vault first:

docker compose -f docker-compose.prod.yml exec backend ciphermoth-admin snapshot
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

Snapshots and restores

ciphermoth-admin snapshot makes a consistent, integrity-checked copy of the complete vault (trash, history, attachments and settings) while CipherMoth runs. ciphermoth-admin check checks a vault or a snapshot.

ciphermoth-admin restore puts a snapshot back while CipherMoth is stopped:

  • It refuses while anything else has the vault open.
  • It keeps the vault it replaces byte for byte.
  • It survives being interrupted.

The encrypted backup ZIP remains an export of your active entries, not a copy of the vault.

Security notes

  • Encryption is unchanged. It is field-level, not whole-file: passwords, notes, URLs, 2FA secrets, tags, folders, custom fields, history and attachments are encrypted with a key derived from your master password (Argon2id, Fernet).
  • Still in plaintext: entry names, usernames and descriptions, until the planned vault format v2. Anyone with the vault file or a snapshot can read them.
  • SQLite runtime: the images run SQLite 3.53 (3.51.3 or newer is required, for the WAL-reset fix), with full sync, secure_delete, a 0600 vault file in a 0700 folder, and a non-root backend.
  • Signed images: the backend and frontend images are signed with cosign; docs/UPDATING.md shows how to verify them.

The complete list of changes is in the CHANGELOG.

v1.6.0

Choose a tag to compare

@mr-grj mr-grj released this 13 Oct 10:04

Unlocking with a session is now the only way in: the vault key never leaves the server, for any client. This retires the compatibility path for v1.4.x apps and CLIs that v1.5.0 announced. Your vault, its database and your backups stay exactly as they are.

Upgrading

  • Update as usual, by hand or with one click. One-click updates work as in v1.5.1, with the same updater: there is nothing new to install. No database migration runs, and everyone is asked to unlock once, as after any update.
  • Nothing is converted. The database, the encryption and the backup format are unchanged, and backups made by earlier releases restore as before.
  • Use a CLI from v1.5.0 or newer. The CLI bundled in the backend image (./cip) is always current. A CLI from v1.4.x stops with a message asking you to update, and changes nothing.
  • Browser tabs left open since v1.4.6 or v1.4.7 reload into the current web UI on their next request; unlock again. Tabs from older releases show the refusal instead: reload them by hand.
  • Scripts that called POST /api/master_password/check or sent x-ciphermoth-key-derivation must unlock with POST /api/master_password/unlock and send the returned token in x-ciphermoth-session (deprecated since v1.5.0).
  • CIPHERMOTH_LEGACY_KEY_AUTH no longer exists. If your .env or compose file still sets it, it is ignored; you can delete the line.

Security

  • Removed the vault key protocol of v1.4.x clients, as announced in v1.5.0. No route returns the vault key or accepts it as a credential: unlocking with the master password opens a server-side session, and the session token is the only way in. Requests that still send the key in x-ciphermoth-key-derivation are refused (403, "code": "invalid_key") on every route, even together with a valid session token, before any route runs and without touching the session. POST /api/master_password/check answers 410 ("code": "upgrade_required") without checking the password, so it can no longer be used to obtain the key. Both answers say which client to update.

Removed

  • POST /api/master_password/check, the x-ciphermoth-key-derivation header, the legacy-key-auth feature in /api/meta, the CIPHERMOTH_LEGACY_KEY_AUTH setting, and the CLI's fallback to the vault key for servers older than v1.5.0. Against such a server, the CLI now stops and asks you to update the server (or use CLI 1.5.x).

Images

Signed with cosign by release.yml@refs/tags/v1.6.0, for linux/amd64 and linux/arm64:

  • ghcr.io/mr-grj/ciphermoth-backend@sha256:a84c299c9b9db917d324b85db268c58e8f338df3077f076bdce5861575aa9b94
  • ghcr.io/mr-grj/ciphermoth-frontend@sha256:9a29b5cbd7181f9be270db9582c63a30b1af068f814f2ce9a9b272e56cf58596
  • ghcr.io/mr-grj/ciphermoth-updater@sha256:e967d9cfc32aca3e8372cb6d853a057e2ee353ec8e6826759b23c271afc798a0

v1.5.1

Choose a tag to compare

@mr-grj mr-grj released this 13 Oct 05:44

A reliability release for one-click updates. Nothing changes in your vault or its database.

Upgrading

  • Update as usual. One click, or docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d. Nothing changes in the database, and everyone is asked to unlock once, as after any update.

  • If you use one-click updates, update the updater once. It doesn't replace itself. After the update, the update dialog shows this command; run it once in your CipherMoth folder:

    docker compose -f docker-compose.prod.yml --profile autoupdate pull updater
    docker compose -f docker-compose.prod.yml --profile autoupdate up -d --no-deps updater

    Until you do, CipherMoth refuses one-click updates instead of risking your vault, and shows you the command again. Future releases that change the database will only install through the new updater.

  • If a newer release than 1.5.1 is already out when you read this, the old updater will offer that one instead. Set CIPHERMOTH_VERSION=1.5.1 in .env, run docker compose -f docker-compose.prod.yml --profile autoupdate pull and ... --profile autoupdate up -d, then update with one click. See docs/UPDATING.md.

Changed

  • One-click updates can now undo a failed database change. Before applying an update, the updater pauses writes (the API answers 503 for a moment), takes a database snapshot and checks that it restores exactly. If the new version, its database migration or its web UI doesn't come up healthy, it puts that snapshot back and restarts the previous version. Before, it kept going when its backup failed and could only switch the images back.
  • Interrupted updates finish safely. A crash, docker stop, reboot or power cut in the middle of an update is completed or rolled back when the updater starts again. If it ever cannot recover on its own, it keeps the API paused, says so in the app, and docs/UPDATING.md explains what to do (updater.sh retry or a manual restore).
  • Stricter checks. The updater also verifies the signature of the version it would roll back to, insists that the web UI (not just the backend) runs the new version, keeps its three newest snapshots, and ignores expired, repeated or malformed requests.

Added

  • GET /api/health reports the version, whether the database matches the release, and whether an update is in progress. The web UI serves /version.json.
  • A release that changes the database refuses to migrate while an older updater is installing it, so the first such release cannot be installed by an updater that could not restore your vault. Updating by hand is not blocked, but it has no automatic rollback, so back up first.
  • Release images carry an io.ciphermoth.min-updater-protocol label, and the updater refuses releases that need a newer updater.

Images

Signed with cosign by release.yml@refs/tags/v1.5.1, for linux/amd64 and linux/arm64:

  • ghcr.io/mr-grj/ciphermoth-backend@sha256:b6d67d0486ed5093c530f43fc2a22d010d5957091f4672f1eeacb7318903c811
  • ghcr.io/mr-grj/ciphermoth-frontend@sha256:8577c2cf80e9d87e5ee205fff2eaee6fefb20d349225ee364793a1914b4c59d0
  • ghcr.io/mr-grj/ciphermoth-updater@sha256:f42ce4defacf1687bb1031719921f6b5976168e7b31bda5b87ead320a382c49d

v1.5.0

Choose a tag to compare

@mr-grj mr-grj released this 12 Oct 15:42

Security

  • The web UI and the CLI no longer receive the vault key. Unlocking now opens a session on the server: the key stays in the server's memory and the client keeps only a random session token, sent in an x-ciphermoth-session header (Authorization stays free for a reverse proxy's own login). A token that leaks (for example through a browser extension) stops working when the session ends and never reveals the key; previously a leaked key stayed valid until the master password changed. Until v1.6.0 the server still hands the key to clients that ask for it the old way, so v1.4.x clients keep working (see Deprecated).
  • Sessions end on the server. The server enforces the inactivity timeout from Settings itself, with 5 seconds of tolerance for request latency, and a 12-hour maximum, so a forgotten tab or a copied token can't keep the vault open. Only real use counts as activity: the web UI reports keyboard, mouse and touch input at most every tenth of the timeout (between 1 and 15 seconds), and checking a session's remaining time, background requests and hidden tabs never extend it. The UI's countdown is taken only from the server's answers (a heartbeat that fails doesn't extend it) and is re-read every 15 seconds while the tab is visible, so it never outlasts the server's, also after another device shortens the timeout. It locks after a suspended laptop wakes up past the deadline, and after a tab was hidden longer than the hidden-tab setting even if the browser froze its timers. An expired session is deleted and cannot be revived, even by raising the timeout. Logging out, auto-lock and closing the session from the CLI end it on the server too. Changing the master password ends every session, including those of other devices, and so does any change of the vault key made outside this server process.
  • The web UI may only connect to its own API. The frontend image's Content-Security-Policy allowed connections to any host (connect-src *). At start-up the image now allows only its own origin, the origin of CIPHERMOTH_API_URL, and the GitHub address of the optional update check, which makes it much harder for injected code to send the session token or vault contents elsewhere. It is not a complete barrier: a policy cannot stop navigation to another site or WebRTC, it ignores query strings on the allowed GitHub address, and with an IPv6 API address it can only restrict the scheme. The API URL is checked first: every value that worked before is still accepted (absolute http(s) URLs, //host URLs and relative paths, with a logged warning for a user name, query or fragment), and an unsafe value (another scheme, or characters that could rewrite the policy or the app) gets a page explaining what to fix instead of the app. Lint rules now reject the HTML and eval sinks such code would need.
  • Unlocking no longer stalls the server. The deliberately slow Argon2id and bcrypt steps run off the request loop, so other requests keep being answered while someone unlocks. Argon2id derivations still run one at a time, which keeps memory at one 64 MiB derivation however many unlocks arrive together.

Added

  • POST /api/master_password/unlock returns a session token, POST /api/master_password/lock ends one, GET /api/master_password/session reports how long it has left without extending it, and POST /api/master_password/session records activity. POST /api/master_password/create returns a session token instead of the vault key: a v1.4.x browser tab that creates a new vault during the update gets a working vault and asks for the master password once more; scripts that create vaults must read session_token (or call the deprecated /check). /api/meta lists the vault-sessions feature, and legacy-key-auth while that is accepted.
  • CIPHERMOTH_LEGACY_KEY_AUTH=false refuses clients that still use the vault key (see below) before v1.6.0 does. Existing installs keep their own docker-compose.prod.yml, which does not pass this variable on: add CIPHERMOTH_LEGACY_KEY_AUTH: ${CIPHERMOTH_LEGACY_KEY_AUTH:-} to the backend's environment, then check that /api/meta no longer lists legacy-key-auth.

Changed

  • Everyone is asked to unlock once after updating. Sessions live only in the server's memory, so restarting or updating the server also locks every open tab and the next request returns to the unlock screen. The backend must keep running a single worker process (the shipped images do).
  • The CLI opens a session for each command and locks it when the command ends, even on errors. If a session expires while you are still answering prompts, it unlocks again once with the password you already typed. Against servers older than v1.5.0, which have no unlock route, it still uses the vault key, as those releases expect; it never falls back to that because of another error.
  • CIPHERMOTH_API_URL is checked when the UI starts. Any value that worked in v1.4.7 keeps working. A value the check refuses shows a "CipherMoth cannot start" page that names the problem; the backend and your vault are unaffected, and a one-click update still reports success because the updater checks only the backend, so open the UI once after updating. An IPv6 address works, but the policy can then only restrict the scheme, so prefer a host name.
  • Settings: the inactivity warning must now be shorter than the inactivity timeout on the server too (the UI already required it).

Deprecated

  • POST /api/master_password/check and the x-ciphermoth-key-derivation header, which hand the vault key to clients and accept it back, are kept so that v1.4.x CLIs and browser tabs that were open during the update keep working. They behave exactly as in v1.4.7 (the key must match the vault, under the same locks) and /check answers with a Deprecation header. They will be removed in v1.6.0. Update scripts that call the API directly to use /unlock and send the token in x-ciphermoth-session.

v1.4.7

Choose a tag to compare

@mr-grj mr-grj released this 11 Oct 17:34

Fixed

  • Changes are saved before the API answers. The database transaction was committed only after the response had been sent, so a request made immediately after a change could miss it, and a change whose commit failed was still reported as successful. The commit now happens first, and a failed commit returns an error.
  • Some entry names made an action hit a different entry (GHSA-cv6q-x5p4-j9cx). The API routes on the entry name, so deleting an entry named x/purge permanently deleted a trashed entry named x, and ciphermoth password delete "x/attachments/1" deleted an attachment of x while reporting success. Names containing / now reach exactly that entry. The web UI and CLI also name the entry in a header, so if a reverse proxy rewrites the address on the way (nginx decodes %2F when proxy_pass includes a path), the request is refused instead of acting on another entry; see "Pass request paths through unchanged" in CONTRIBUTING.md. Browsers rewrite . and .. in a web address (purging a trashed . trashed an entry named purge), and trash collides with the trash list, so new entries can't use those three names; existing ones still open and can be renamed by editing them, and the web UI refuses to act on . or .. until you do. The CLI sends names with / only to servers that route them correctly.
  • Imports can no longer break the vault. CSV and backup imports skipped the checks the rest of the app applies, so an over-long description, name or URL, an invalid 2FA secret, or a malformed backup entry was stored as is, after which the whole vault list failed to load. A vault already affected by this opens again, and the entry can be fixed by editing it. Every imported row is now checked before anything is written; if any row is invalid nothing is imported and the error names the row and column. CSV rows get the same checks as a new entry. A CipherMoth backup restores exactly what the vault held, including values older imports stored over the usual limits, and refuses only what the vault can't store at all.
  • CSV cells larger than 128 KB (long notes or passwords) made the import fail with a server error. They now import, and a CSV that can't be parsed gets a clear error with the line number.
  • Concurrent edits no longer lose passwords from the history. Two edits of the same entry at the same moment each started from the same old value, so one replaced password vanished from the history. Concurrent attachment uploads could also push an entry past the 25 MB and 20-file limits. Edits and uploads to one entry are now applied one at a time.
  • Text the database can't store is refused with a clear message instead of a server error: a NUL character in an entry name, username or description, or a broken Unicode escape anywhere in a request, including the master password.
  • Proton Pass CSV imports keep the login email when the username column is empty. Any CSV column now falls back to the next matching column when its cell is blank.
  • CSV imports no longer drop records silently. Secure notes from Bitwarden and Proton Pass exports were skipped while the import reported success; they now import as secure notes. Rows sharing a name (Chrome exports two accounts for one site that way) collapsed into one entry and were reported as "already exist"; each now imports, the later ones as name (2), name (3). Anything that still can't be imported (cards, identities, aliases, rows without a name or password) is listed with its row and the reason, in the web UI and the CLI.
  • Editing an entry whose name starts or ends with a space changed a different entry with the trimmed name (such names can come from older imports). Edits now match the entry's name exactly.
  • Restoring or renaming onto a name that was just taken returns a clear error instead of a server error.

Security

  • Validation errors no longer echo what you sent. A rejected master password (for example, too weak) or entry value was returned verbatim in the error response. Errors now name only the field and the problem.
  • Dependencies: cryptography 50.0.0, anyio 4.14.2, Mako 1.4.2, axios 1.20.0 and react-router 7.18.4 clear every open advisory; none of the affected code paths were used by CipherMoth. The frontend image's file server is now pinned with a lockfile, which also updates compression to 1.8.2 (a denial-of-service fix that did apply to the UI port).

Changed

  • Descriptions can be up to 10,000 characters (was 1,024), so notes from Bitwarden or KeePass exports import instead of failing.
  • Backups and imports are checked against frozen test data from every release. Vaults and backups created by v1.0.0 to v1.4.6, and vault databases from Dinopass v0.3.0, are proven to open, upgrade, decrypt and restore. Backups from v0.3.0 (dinopass_backup.json) are not importable. See testdata/golden.
  • The backend now declares Python >=3.13,<3.15.