github nilsteampassnet/TeamPass 3.2.2.7

one hour ago

What's Changed

This is a maintenance release on the 3.2.2 line. It closes two vulnerabilities: a database dump alone was enough to recover the users' private keys, and the per-role MFA requirement did not apply to roles inherited from Active Directory groups (GHSA-fv78-jwjv-pj25, GHSA-6mg2-rh62-rr3g). It also hardens how other secrets are kept: the LDAP bind password and the SMTP password are now encrypted at rest, the Docker image no longer writes Secure Send link credentials to its access log, and the session cookie gets the Secure attribute behind an HTTPS reverse proxy. Folders can be protected against accidental deletion, the Secure Send recipient page carries the organisation's branding, and the knowledge base gains category browsing and Markdown editing. The bug fixes cover accounts stuck after their first LDAP login on large vaults, the personal sharekeys repair, and LDAP or SMTP passwords containing special characters. Upgrading is required for every installation.

This release changes the database schema and includes a data migration. UPGRADE_MIN_DATE is raised, so every installation goes through the upgrade wizard once: it adds one column to the folders table, encrypts the LDAP bind password and the SMTP password still stored in plain text, and seals the users' private key recovery copies with the instance key. No table is added, and no existing column is altered.

🔒 Security fixes

  • A database dump alone no longer reveals the users' private keys (GHSA-fv78-jwjv-pj25, reported by @higels) - so that a user whose LDAP or OAuth2 password changed outside TeamPass can sign in without being asked for the previous one, TeamPass keeps a second copy of the users' private keys. That copy was encrypted with a key computed from two columns of the same users row, so anyone holding a database dump, without the instance key, could recover the private keys and through them every password those users could read. The copy is now also encrypted with the instance key (SECUREFILE), like the other secrets a dump must not open, and the upgrade converts the existing copies without opening them. Affected versions: 3.1.5.0 to 3.2.2.6. Database dumps taken before the upgrade keep the old format - see the upgrade notes.

  • The LDAP bind password and the SMTP password are now encrypted at rest (PR #5411, @ais-yasas) - both were stored in plain text in the settings table, so every database dump and every backup carried them, although the installer and the 3.1 upgrade flag them as encrypted. They are now encrypted with the instance key, the one that already protects the other encrypted settings, and decrypted only when the LDAP bind or the SMTP login takes place. The LDAP and Emails settings pages no longer send them to the browser either: the field stays empty with Leave empty to keep the existing value, and the page source never contains the password. Reading them still required database or administrator access, so this is hardening, not an advisory.

  • The MFA role requirement now applies to roles inherited from Active Directory groups (GHSA-6mg2-rh62-rr3g) - with MFA is requested for users in Roles set, the login only looked at the roles assigned in the user form, so a user who held the MFA role through the AD group mapping alone was never asked for an MFA code. Both role sources now count. Saving the user form also hid the issue: when every role shown in the form came from AD, they were all stored as manually assigned roles, so they no longer followed the group membership and survived the user's removal from the AD group. Roles inherited from AD are now always left out of the roles the form stores. Affected versions: 3.0.0.23 to 3.2.2.6.

  • The Docker image no longer writes Secure Send link credentials to its access log - the Nginx server inside the official image logged every request with its query string, so the code, key and stamp of every opened Secure Send link were kept in /var/log/nginx/teampass-access.log, together with the Referer header that repeats them. The image now logs the request path without its query string and without the Referer. It also no longer adds a second Referrer-Policy header on top of the no-referrer sent by the Secure Send page, the password reset page and the API: browsers apply the last one, so the confirmation request carried the complete link in its Referer. Reading that log required access to the container, so this is hardening, not an advisory.

  • The session cookie is marked Secure behind a reverse proxy that terminates HTTPS - TeamPass only looked at the connection reaching PHP, so behind such a proxy, the usual Docker deployment, the session cookie was issued without the Secure attribute, and a browser led to a plain http:// address would have sent it in clear. When IP detection mode is set to Reverse proxy / WAF, a request coming from a declared trusted proxy with X-Forwarded-Proto: https now counts as HTTPS for that cookie. The header is ignored in Direct mode and from any other address, and it can only add the attribute, never remove it.

✨ New features

  • Folders can be protected against accidental deletion (PR #5409, @guerricv) - a new Protect against accidental deletion option, set by a TeamPass administrator from the folder creation dialog or the folder edit panel of the Folders page, and shown there as a shield column. A protected folder cannot be deleted, and neither can any parent folder whose subtree contains it, so a user with write access can no longer remove a whole branch, with its items, in one operation. It is meant for the structural folders the role permissions are built on. Only an administrator can set or remove it: users who otherwise manage the folder cannot. The protection is attached to one folder, it is not inherited by new subfolders, it stays in place when the folder is moved, and it survives a deletion and restore through Utilities → Recycled bin. It covers folder deletion only: the items inside a protected folder can still be deleted one by one or in bulk, according to the usual rights. Through the API, an administrator sets it with deletion_protected (0/1) on PUT /folder/update.

  • Branded Secure Send recipient page (PR #5413, @guerricv) - the page a recipient opens from a Secure Send link has a new layout, with a dark mode. It shows the organisation name set in the new Public entity name option (General Info settings), and the custom logo when it is an image placed in public/assets/custom/: a logo given as a URL stays on the login page only, so opening a link never contacts another server. Before anything is revealed, the recipient sees the expiry date, the remaining views and a reminder to check that the page address belongs to the sender's organisation. With the new Show the sender's profile name option (Collaboration settings), the page also shows the sender's first and last name, never the login or the e-mail address, and the sender sees in the Secure Send dialog what the recipient will be shown.

  • Knowledge base articles can be browsed by category (PR #5414, @guerricv) - a new List / Categories switch above the article list of the Knowledge base page. Categories shows one card per category that holds articles, in alphabetical order with its number of articles; choosing a card shows that category's articles in the usual table, where search and paging then apply within the category, and All categories goes back to the cards. Older articles without a valid category are grouped under Uncategorized, always shown last. The list follows live changes made by other users, and now keeps the current page instead of returning to the first one, and the edition and presence badges stay visible after a page change or a search. List remains the default view.

  • Markdown in the knowledge base editor - plain text that looks like Markdown, typically an answer copied from an AI assistant, is formatted when it is pasted into an article, with a Keep plain text offer to undo it (Ctrl+Shift+V pastes it as plain text from the start). A new Edit as Markdown button, next to the code view, shows the article as Markdown and applies the edited text when you go back; left untouched, the article is restored exactly as it was, and a notice lists what Markdown would simplify (underlining, merged cells, image sizes, table header rows). Headings are mapped to the levels an article keeps, and the Ctrl/Cmd+1, +5 and +6 heading shortcuts no longer produce headings that disappeared on save. The two converters, markdown-it and Turndown (MIT licence), are bundled with TeamPass: nothing is loaded from the Internet. See Knowledge base.

🛠️ Improvements

  • A folder holding items used by LAPR can no longer be deleted or moved into a personal folder (PR #5409, @guerricv) - while LAPR is enabled, deleting a folder whose subtree contains an item that is a managed Linux account or the SSH credential of an endpoint is now refused, even for an administrator, with a message explaining that the items must first be moved out or unlinked. Deleting such an item on its own was already refused; deleting its folder went through, and left the managed account or the endpoint pointing at a deleted item. An administrator, the only one who can move a shared folder into a personal folder, can no longer do it with such a folder, as was already the case for the items themselves: LAPR reads them as the server, which only works in a shared folder. Restoring a deleted endpoint whose SSH credential item has since been deleted or moved into a personal folder now says so, instead of a generic permission error.

  • Secure Send deployment guide (PR #5412, @guerricv) - a new Secure Send page explains how to publish Secure Send links on a dedicated public hostname while the vault stays private: the exact requests the public address must accept (Apache and Nginx allowlists, reverse-proxy and Docker setups), logging without link credentials, TLS, sessions on several nodes, and a validation matrix and production checklist.

  • Docker: the dead INSTALL_MODE=auto option is removed, and the volume and backup instructions are fixed - INSTALL_MODE=auto ran a command-line installer that no longer exists since 3.2.0, so the container only logged a warning and fell back to the browser installer. The option and its ADMIN_EMAIL and ADMIN_PWD variables are removed from the entrypoint, the compose files and the .env examples; a container still started with INSTALL_MODE=auto says the option is no longer supported. The Docker Hub page listed 3.1 volume paths, without storage/config and secrets, and its backup procedure saved neither the master key nor settings.php; it now follows the Docker guide (issue #5380).

  • Polish is fully translated - the 1,294 strings translated by the community on POEditor since the previous release are included, and every string added by this release is available for translation there.

  • An upgrade that changes the database now closes open sessions - when an upgrade is pending, the login page already refused sign-in, but a user who was signed in kept browsing pages that read columns the database did not have yet, and got errors. Such a session is now closed at its next page load, and the user lands on the login page that announces the upgrade.

🐛 Bug fixes

  • An account created at its first LDAP login could stay locked on a large vault - generating the account's encryption keys re-encrypts every shared item of the vault, and on a large vault it lasted longer than Maximum time a script is allowed to run: the task was killed and marked failed, the account stayed Tasks in progress - User not active, and each new sign-in generated a new key pair and started again from scratch, into the same limit. The generation now runs in slices that stay within the limit and keeps the batches already done, and a failed generation is resumed at the next sign-in with its key pair. A batch that alone does not fit the limit three times fails the task with a message naming the two settings to adjust. A lookup that, for user 5, could pick up the failed key generation of user 50 is gone, and each batch no longer derives the owner's keys again.

  • The Tools sharekeys repair skipped the personal items damaged by #5407 (PR #5410, @ais-yasas) - a shared item moved into a personal folder and then saved kept only the server's key (issue #5407, fixed in 3.2.2.6), and the repair refused to restore the owner's key because the owner was not the item's creator. It now accepts the folder owner when they made the item's latest move, since only the owner of a personal folder can move an item into it; every other owner and creator mismatch is still left untouched. A folder changed from the item's edit form is not recorded as a move, so such an item is still skipped.

  • An LDAP bind or SMTP password containing &, ', ", < or > stopped working once saved from the settings pages (PR #5411, @ais-yasas) - the browser and the server both HTML-encoded the value on save, so a&b was stored as a&amp;b, and the LDAP bind or the SMTP login then failed. The two passwords are now stored exactly as typed.

  • "See log" failed for an account without any log - the user log table was built by hand and answered [][] for an account with no log yet, typically one just created at its first LDAP login, and DataTables reported an invalid JSON response.

  • The Docker image no longer reports three critical unknown files in the file integrity check - the image builds its library folder with Composer, which installs three maintainer scripts of the justinrainbow/json-schema package (bin/extract-release-notes.sh, bin/prepare-release.sh, bin/update-changelog.sh). They were missing from the reference list of shipped files, so Utilities → Health → File integrity reported them as critical unknown files on every container. They are now part of that list. They are maintainer scripts, never run by TeamPass, and they sit outside the web root.

  • Knowledge base: image sizes and merged table cells were lost on save - the browser-side sanitizer applied its URL filter to the width, height, colspan and rowspan values too, so every save and every display dropped them.

  • Knowledge base: an HTML sample written as text turned into real markup - the repair of articles stored escaped by earlier versions also ran on genuine rich content, so HTML code shown as text, for example in a code block, became real markup when the article was displayed or saved, and code blocks lost their <pre> tag. Content that already holds real formatting is now left unchanged.

⬆️ Upgrade notes

  • Schema. The upgrade adds nested_tree.deletion_protected (TINYINT(1) NOT NULL DEFAULT 0): every existing folder starts unprotected. It also runs one data migration, described below. UPGRADE_MIN_DATE is raised, so every installation goes through the upgrade wizard once; the Docker entrypoint runs the migration on start.
  • TeamPass is closed until the upgrade has run. The folder tree reads the new column everywhere, so from the moment the new files are in place, the login page refuses sign-in and users already signed in are signed out at their next page load. Run the upgrade wizard right after replacing the files.
  • Private key recovery copies are sealed during the upgrade. The upgrade encrypts every existing copy with the instance key, without opening it, so no user has to do anything. A copy the upgrade did not reach is still read, and sealed the next time it is written.
  • Protect or destroy the database dumps taken before this upgrade. They keep the old format: a mysqldump file, a replica, a virtual machine or volume snapshot, or a hosting backup made with an earlier version still opens the users' private keys on its own. Protect them like the instance key, or destroy those you no longer need. The backups TeamPass makes itself are encrypted, and expose nothing without their key. If such a dump may have leaked, change the passwords that were stored in TeamPass at that time: regenerating the users' keys is not enough. See Private key recovery copy.
  • Do not return to an older version after upgrading. An older version cannot read the sealed copies: when a user whose directory password changed signs in, it fails to recover the key and disables the account, which an administrator then has to enable again. This adds to the encrypted LDAP and SMTP passwords below, which an older version cannot use either.
  • Users who hold the MFA role through AD only will be asked for MFA. If MFA is requested for users in Roles is set and roles are mapped from AD groups, the users who get one of the selected roles only through an AD group are asked for an MFA code at their next sign-in, and must enroll first if they never did. Users exempted with MFA enabled off in their user form are not affected.
  • Roles copied from AD by earlier saves of the user form stay manual until the form is saved again. The upgrade does not change any role assignment. Saving the user's form again, by someone allowed to grant those roles, removes the manual copy, and the role then follows the AD group membership again. A role the user holds both manually and through AD keeps only its AD origin once the form is saved, so it now disappears when the user leaves the AD group.
  • API changes for folder clients. GET /folder/writableFolders returns two new fields, deletion_protected and contains_deletion_protected, and can_delete_folder is now 0 when the folder or one of its subfolders is protected. DELETE /folder/delete answers 409 when the subtree contains a protected folder or, while LAPR is enabled, an item linked to LAPR. PUT /folder/update answers 403 when a non-administrator sends deletion_protected.
  • The stored LDAP bind and SMTP passwords are encrypted during the upgrade. Each value is decrypted back and compared before it replaces the plain text. A value that cannot be encrypted is left as it is and keeps working, and the PHP error log gets a line starting with TEAMPASS Upgrade 3.2.2 - credential settings: that reports how many were encrypted and how many were left in plain text. A value still in plain text keeps working, and saving it from its settings page encrypts it.
  • The two password fields now look empty. That is expected: the password is still stored. Leave the field empty to keep it, or type a new one to replace it. A blank field never erases the stored password, so it cannot be cleared from the page. This only matters if you move to an anonymous LDAP bind or to SMTP without authentication, and in both cases the password is no longer used anyway.
  • Re-type a password that contains &, ', ", < or > once. The migration encrypts the stored value as it is, including the HTML encoding added by earlier saves. If LDAP sign-in or e-mail was failing because of one of these characters, enter the password again on the LDAP or Emails page after upgrading.
  • Downgrading. An older version would use the encrypted LDAP and SMTP values as the passwords themselves: after a downgrade, re-type both passwords once. Downgrading is not supported anyway, see the private key recovery copies above.
  • Keep the instance key with your backups. Both passwords are now encrypted with the instance key (SECUREFILE in the TEAMPASS_SECRETS directory, or the secrets volume on Docker), like the other data that key protects. A database restored without that key file cannot decrypt them: you would have to type them again.
  • Docker access log format. The Nginx access logs of the container no longer use the combined format: each line holds the client address, the time, the method, the path without its query string, the status, the size, the user agent and X-Forwarded-For, and no longer the Referer. Adapt any tool that parses them. If you replaced /etc/nginx/http.d/default.conf to remove the query strings, as the Secure Send guide advised for 3.2.2.6, compare it with the new file: the override is no longer needed.
  • Docker environment. INSTALL_MODE, ADMIN_EMAIL and ADMIN_PWD are no longer read: remove them from your .env file. They only mattered for a first installation, which is always completed in the browser.
  • HTTPS reverse proxy. To get a Secure session cookie behind a proxy that terminates HTTPS, set Settings → Options → Networks → IP detection mode to Reverse proxy / WAF and declare the proxy address, as TeamPass sees it, in Trusted proxies. With Docker, that is the address of the proxy seen from the container. Nothing changes in Direct mode, the default.
  • Secure Send sender name is off after an upgrade. On an upgraded installation, Show the sender's profile name is disabled: recipients see no sender name until an administrator enables it. New installations enable it. Before enabling it, keep in mind that anyone holding a link sees the name before entering the passphrase, and that the name is the one in the user's profile, which users can change themselves unless Users can no longer edit their profile is enabled.
  • Back up your database before upgrading, as always.

Full Changelog: 3.2.2.6...3.2.2.7

Important

  • Requires at least PHP 8.2

Languages

Please join Teampass v3 translation project on Poeditor and translate it for your language.

Installation

Follow instructions from Documentation.

Upgrade

Follow instructions from Documentation.

Ideas and comments

Are welcome ... please use Discussions.

Download TeamPass

Don't miss a new TeamPass release

NewReleases is sending notifications on new releases.