Skip to content

3.2.4.3

Latest

Choose a tag to compare

@nilsteampassnet nilsteampassnet released this 13 Nov 07:36
9cdbaf2

What's Changed

This release on the 3.2.4 line closes three single sign-on weaknesses and a folder permission gap, and modernizes email delivery. An identity provider user named Admin, tp or api could be signed in to the built-in administrator or an internal account. An SSO user could take over the local or LDAP account holding the same login, private key included. The Allowed groups for self-registration list was never enforced. A user with a read-only role on a folder could rename it and change its settings. TeamPass can now send email through Microsoft Graph, Microsoft 365 SMTP with OAuth2 or the Gmail API, as well as through an SMTP relay, and queued emails are encrypted. Secure Send links can be emailed to their recipient, and created by API clients such as the browser extension (both off by default). Installation, upgrade and disaster recovery now end with a file permission review, and the installer folder is removed by the operator. Most email work comes from @guerricv. Upgrading is recommended for all installations, and strongly recommended for every installation using OAuth2 single sign-on.

This release changes the database schema. UPGRADE_MIN_DATE is raised, so every installation goes through the upgrade wizard once, including installations already running 3.2.4.2.

🔒 Security fixes

  • SSO never signs in to the administrator or an internal account (GHSA-9f44-82r9-8878) — the OAuth2 sign-in excluded the built-in administrator by comparing the submitted login with admin. The users table compares logins without regard to case, accents or trailing spaces, so an identity provider user Admin@contoso.com located the account admin. tp@, otv@, api@ or ssh@ located the internal accounts, which nothing excluded. The sign-in converted the account to OAuth2, replaced its password and opened an administrator session. For the TP account, this also broke the server-side key operations: key generation of new users, key repairs and LAPR rotation. The decision now uses the account the login located. Such a sign-in is refused and written to the failed authentications of the Logs page. Every release since 3.1.2 is affected.
  • OAuth2 accounts are bound to their identity at the provider (GHSA-rwmr-96mp-w36x) — an OAuth2 sign-in found the TeamPass account by the provider's user name alone: the part before @ of the Entra UPN, or preferred_username for a generic OpenID Connect provider. A local or LDAP account with the same login was converted to OAuth2, and transparent key recovery re-encrypted its private key for the newcomer, who could then read every item the account could read. Each account now stores the identity the provider asserts: the Entra object id, or the iss + sub pair of an OpenID Connect provider. The sign-in checks it before changing anything, and binds an unbound account only once the whole sign-in, MFA included, has succeeded. Converting an existing local or LDAP account is now a setting, Link existing accounts at their first SSO sign-in (OAuth page). A renamed UPN is refused with an explicit message, instead of creating a second account. Refusals and bindings are written to the Logs page. On the Users page, the new Release the SSO identity link action of an OAuth2 account undoes a binding, as does any change of its authentication type. A generic provider whose UserInfo sub differs from the ID token is refused. Every release since 3.1.2 is affected. The risk is highest with a generic OpenID Connect provider (usable since 3.2.4.2) whose users can choose their own user name; with Entra ID, UPNs are set by the directory administrators.
  • The Allowed groups for self-registration list is enforced (GHSA-grv6-m9pj-4cf2) — any non-empty value let every user authenticated by the provider create a TeamPass account: the list itself was never checked. A user outside the listed groups is now refused with a message saying so, and the failed authentications of the Logs page list the groups TeamPass received. A group is matched by name, ignoring case, or by its Entra object id, which unlike a name is unique. * lets every user in, and an empty field disables self-registration as before. Groups are read from the provider answer kept by the server, never from the login form. Existing accounts are not affected. Every release since 3.1.4.20 is affected.
  • A read-only folder role prevents editing the folder (GHSA-32hp-p55x-wr8v, @p-w) — a user whose only access to a shared folder was a read-only role could rename it, move it, raise its password complexity and change its icons, renewal period and restrictions. The check of the folder edit form compared numbers with the text values held by the session, so it never refused anything. A second folder rename request had no check at all. Both now refuse such a folder. The forced release of an item edit lock is now reserved to the users of the Database page: any user who could see an item could release another user's lock on it. Every release since 3.0.0 is affected. No password or item content was exposed.
  • Email diagnostics and task logs no longer keep credentials or message contents (PR #5453, @guerricv) — with a debug level set, the test-email dialog showed the raw SMTP transcript, authentication exchange included. It now keeps only the connection stages, command names, numeric reply codes and local socket or TLS errors. When a background email task completes or fails, its stored arguments shrink to the outcome plus the recipient's email and login, so the subject, body and temporary passwords are gone. Its error message is one of a few fixed texts. Bug reports mask the new email provider settings and every registered secret.
  • Symfony components updated — symfony/http-foundation and symfony/routing 6.4.50 and symfony/serializer 7.4.23 fix CVE-2026-118514, CVE-2026-118515 and CVE-2026-118516, reported by dependency scanning. The other dependencies received their patch and minor updates.

✨ New features

  • Email through Microsoft Graph, Microsoft 365 SMTP OAuth2 or the Gmail API (PR #5454, PR #5458, @guerricv) — Configuration → Emails now offers one transport at a time: an SMTP relay (no authentication, username and password, or Microsoft 365 OAuth2 as an application), Microsoft Graph, or the Gmail API with delegated Google consent. The page saves a complete profile at once. Each secret is kept, replaced or cleared explicitly and is never sent back to the browser. A save that fails names the invalid field. Provider credentials and tokens are encrypted with the instance key. Token renewal needs no signed-in user. OAuth token requests and API calls go through the global proxy when one is set. Graph and Gmail accept up to 2 MiB of prepared message and refuse Bcc. There is no fallback from one transport to another, and none to Basic SMTP authentication. Password recovery, passkey and upgrade notifications, and the Users page warning recognize every transport, not only an SMTP host. Provider setup, Exchange mailbox scoping and the acceptance checks to run are in the email transports documentation.
  • Email a Secure Send link (PR #5457, @guerricv) — the Secure Send form gains Email the link to and Create and email. TeamPass creates a new link and emails one recipient an invitation with the link and its expiration, without the item, the note or the passphrase. The default subject names the sender only when Show the sender's profile name allows it, and says Someone otherwise. The name is resolved at each submission, so a policy change also applies to pending invitations. The worker checks the setting, the sender's access to the item, the remaining views and the expiry again before each attempt, and a link that became unusable is not sent. My secure sends shows each invitation as awaiting submission, accepted by the mail service, unconfirmed or not sent. Each sender may email ten links per rolling hour. The feature is off by default: enable Allow Secure Send email invitations under Options → Collaboration → Secure sharing. It requires an HTTPS sharing address and a configured email transport. The invitation can be customized under Email templates.
  • Secure Send from API clients — the browser extension, paired mobile devices and API scripts can create Secure Send links for the items the user can read. Two new endpoints serve them: GET secureSend/policy returns the limits set by the administrator, and POST secureSend/create creates the link, optionally emailing it. A link created this way is the same as one created from the web interface. The same policy, item permissions, audit journal and email delivery apply, and the sender can revoke it from My secure sends. The answer, which holds the link, is never cached, and the read-only flag of the account is re-read at every API request. This version covers item sends only, not notes. The feature is off by default: enable Allow Secure Send from API clients under Settings → API, in addition to User can propose One-Time-View links. See the Secure Send API documentation.
  • The Secure Send journal in the Logs — Monitoring → Logs gains a Secure Send source, for administrators only. It lists link creations, views, failed attempts, revocations, invalidations and expirations, with the reason of each, filterable by event, date and sender. The journal is not purged from this page: its retention is set under Options → Collaborative & advanced features → Secure sharing. In the item logs, a view made through a Secure Send link is now labelled Viewed through Secure Send and filterable, instead of appearing as a view by the internal One-Time View account.
  • Test an SSO user before they sign in (Microsoft Entra ID) — the OAuth page ends with two read-only tools. Test a user takes a login or a UPN and lists every directory user who would sign in with that TeamPass login. For each one it shows what the next SSO sign-in would do: account linked, converted, created, or refused with the reason. It also lists the groups the sign-in reads and the roles a new account would receive. Check the allowed groups looks up each entry of Allowed groups for self-registration in the directory, to catch a typo or a name several groups share. Both read the directory as the application, like the OAuth2 synchronization: User.Read.All and Group.Read.All of type Application.
  • Add and remove favourites from the search results (PR #5455, @guerricv, discussion #4843) — when favourites are enabled, each search result row carries a star. Read-only users can use it too. With the favourites filter on, removing a star refreshes the results. Adding a favourite now checks the item's folder and its user or role restrictions, from the item list as well as from the search results.

🛠️ Improvements

  • Installation, upgrade and recovery end with a file permission review (PR #5452, @guerricv) — installation and upgrade need temporary write access that could stay in place afterwards. The last page of the installer and of the web upgrade wizard, and the disaster recovery finalization, now run a fresh permission audit on the server and display the correction commands. A previous pass or a browser answer cannot skip that audit. Where automatic verification is impossible (Windows ACLs, container ownership, custom layouts), the operator must explicitly acknowledge a manual review, which is recorded as manual. TeamPass no longer deletes or changes the permissions of public/install itself: the operator removes it with the command displayed, or restarts the official Docker container, whose entrypoint removes it. The web upgrade still restores the previous maintenance mode at the end of the database upgrade. The command-line upgrade is unchanged.
  • Queued emails are encrypted and retried within limits (PR #5454, @guerricv) — new background emails are encrypted with the instance key before they are stored. A confirmed temporary failure (network, timeout, throttling) is retried up to three attempts, 30 then 60 seconds apart, or after the provider's Retry-After up to one hour. An ambiguous outcome is never replayed automatically, since the provider may already hold the message: an interrupted send, a timeout or a partial acceptance. The Emails page counts the background queue separately from the historical backlog.
  • Email failures are reported instead of being silent (PR #5453, PR #5458, @guerricv) — a background notification rejected by the relay was marked completed. It is now marked failed. The local password recovery and the Google Authenticator setup email now tell the user when their email could not be queued. A failure while queuing an email no longer interrupts the sign-in that triggered it. Failed tasks without subtasks, every email among them, were never purged: they now follow the task history retention period.
  • Emails are left-aligned (PR #5457, @guerricv) — the common email layout pushed the content to the right inside its card. The content is now left-aligned in the centered card, in every email TeamPass sends.
  • Entra groups include nested groups — the sign-in reads the user's groups with transitiveMemberOf and follows paging, falling back to memberOf. A member of a group placed inside another group gets both, for the self-registration check and for the roles matched at account creation. Directory roles such as Global Administrator are no longer returned as groups.
  • Translations — 141 new strings, translated into French, are on POEditor, and 20 new German translations ship with the release. Stale English text stored as a translation of the self-registration tip in six languages was cleared, so they show the current English wording until a translator updates it.

🐛 Bug fixes

  • An active account was refused when a deleted account had the same login — a deleted account is kept as <login>_deleted_<time>. The sign-in refused every login with such a homonym with User has been deleted, including the account an administrator had re-created under the same login. The check now only applies when no active account holds the login, where it still stops LDAP or OAuth2 from creating an account in place of the deleted one.
  • A role named after an SSO group with an accent, & or ' was never granted — role titles are stored HTML-encoded, so Équipe R&D never matched the group name sent by the provider. The account created at the first SSO sign-in missed the role, and the OAuth2 synchronization panel showed it as missing. Both now compare the decoded title.
  • The legacy email backlog sent each message to the previous recipients too (PR #5453, @guerricv) — when one batch sent several emails of the historical emails table (the waiting emails button of the Emails page, or the sending triggered at sign-in), each message kept the recipients of the messages before it. Every delivery now starts with an empty recipient list, and the SMTP connection is closed after a failure too.
  • Password expiry notifications all showed the same countdown (PR #5456, @guerricv) — the inbox recomputed each warning's "expires in N days" from the current date, so the 14-day and 7-day warnings of one password read the same a week later. Each notification now keeps the countdown of the day it was delivered, next to its date. Notifications already stored benefit without migration.
  • A password change could save an empty private key (PR #5459, @MarMarAba) — when the session held no private key, which is the case right after a key generation or while a temporary code or an LDAP re-encryption is pending, the account dialog encrypted an empty key with the new password and stored it, along with its recovery backup. The dialog also accepted a wrong current password in that state. The user could no longer open any item, and every sign-in logged auto_reencryption_failed. The profile password change and the temporary code dialog had the same weakness, the latter when AES v2 writes are enabled. All three now refuse the change. The encryption of a private key now fails instead of returning an empty value or its error message, which the callers stored as the key.
  • Line breaks of plain-text descriptions were lost — a description stored as plain text, as API clients and the browser extension write it, was shown on a single line on the Secure Send page and on the item card. Saving the item from the web interface then removed its line breaks for good. Such text is now escaped and its line breaks kept, in the display and in both description editors.
  • Administrators could not release an item edit lock from the Database page — since 3.2.0.0, the forced release required access to the item's folder, which administrators do not have. The request was refused while the page reported a success. Administrators can now release any lock; managers and HR managers still need access to the item, and the page reports a refusal.
  • Saving TeamPass location (URL) failed — the save also rewrote the CSRF protection script URL in a file it looked for at a path that no longer exists since the public/ web root. That rewrite was not needed: the URL is computed on every page load. It was removed.

⬆️ Upgrade notes

  • Schema. The upgrade adds the email transport settings, a configuration revision, the email_oauth_state table, the email_attempts and next_attempt_at columns of background_tasks with an index, the secure_send_email table, and the users.oauth2_identity column with a unique index. Existing SMTP settings are kept and SMTP stays the transport. As with every schema change, TeamPass and its background tasks wait until the upgrade has run.
  • Installer folder. At the end of the installation or of the web upgrade, correct the permission findings, check again and finalize, then remove public/install with the command displayed. Keep the final page open until then. On the official Docker image, restart the container instead. See File system permissions.
  • Allowed groups for self-registration. The field is left as it is, but it is now enforced. If you relied on any value letting everybody self-register, enter *. Prefer Entra object ids to group names. With Entra, the group names are only returned when the sign-in token can read groups (delegated Group.Read.All or similar): with User.Read alone, list object ids. The listed groups are no longer matched against role titles.
  • Link existing accounts at their first SSO sign-in. The upgrade enables it on installations whose OAuth2 endpoint is Microsoft Entra ID, which converted matching local and LDAP accounts until now, and disables it elsewhere. Fresh installations start with it disabled. Disable it if users can choose or change their user name at the provider.
  • Existing OAuth2 accounts are bound at their next successful sign-in. An account whose user was re-created at the provider, or moved to another tenant, is refused afterwards: use Release the SSO identity link on the Users page. A user whose UPN changed is refused with a message naming the problem: rename the TeamPass login on the Users page.
  • Check the administrator and internal accounts. Run SELECT id, login, auth_type FROM teampass_users WHERE id IN (1, 9999991, 9999997, 9999998, 9999999) (adapt the prefix). An oauth2 value means an SSO sign-in reached the account: see GHSA-9f44-82r9-8878 for the remediation.
  • Accounts holding an empty private key. The upgrade does not repair an account a password change already damaged (see the bug fix above). Find them with SELECT u.id, u.login FROM teampass_users AS u JOIN teampass_user_private_keys AS pk ON pk.user_id = u.id AND pk.is_current = 1 WHERE CHAR_LENGTH(pk.private_key) IN (24, 88) (adapt the prefix): a real private key is several thousand characters long. Generate new keys for these users on the Users page.
  • Secure Send email invitations and Secure Send from API clients are disabled on fresh and upgraded installations until an administrator enables them (secure_send_allow_email, secure_send_api_enabled).
  • Emails. Queued emails are now encrypted: a rollback needs the code and the database backup of the same version, and the pending email tasks drained first. The email profile refuses SMTP host lists and tls:// / ssl:// prefixes on save: enter one host and set the port and encryption in their own fields. The test-email debug output is filtered. Send a test after the upgrade.
  • Back up your database before upgrading, as always.

Full Changelog: 3.2.4.2...3.2.4.3

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.

Help others find TeamPass

If TeamPass serves your team well, a ⭐ on this repository, a like on AlternativeTo or a short review on SourceForge helps other administrators find it.

Download TeamPass