3.2.2.2
What's Changed
This is a maintenance release on the 3.2.2 line. It closes an unauthenticated HTTP entry point to the background scheduler, removes a leftover installation table that stored the administrator password in clear text, repairs the Docker upgrade path that could leave a container permanently unable to log in, and fixes the command palette item search. Upgrading is recommended for every installation, and required for anyone running 3.2.0.0 or later, which is the range exposing the scheduler endpoint.
This release carries a data migration. UPGRADE_MIN_DATE is raised, so every installation goes through the upgrade wizard once. There is no ALTER TABLE: the migration drops a temporary table left behind by the installer.
🔒 Security fixes
-
The background scheduler was reachable over HTTP without authentication (GHSA-fpv9-jxph-qg96) -
public/sources/scheduler.phpsat in the web root and forwarded to the cron entry point. That entry point has no session, no authentication and no CSRF check, because it is designed to be invoked from a command line, anditems_handleris due on every run, so an unauthenticated request dispatched the privileged background jobs. The wrapper was created by thepublic/+app/split in 3.2.0.0 and was referenced nowhere: the documentation, the Docker entrypoint, the Windows scheduled-task builder and the language files all invokeapp/sources/scheduler.phpover CLI. It is removed, and the scheduler itself now refuses any non-CLI invocation so a flat layout or a misrooted vhost cannot reintroduce the exposure. Reported by Tike00. -
The installer left the administrator password in the database in clear text - the temporary
_installtable also holds theSECUREFILEname. It is created unprefixed, butrun.step6tried to drop<prefix>_install, a name that never existed, so theDROPsilently did nothing on every installation ever performed. The fallback cleanup inapp/sources/core.phponly runs whilepublic/install/still exists, which is never true in Docker, where the entrypoint deletes that directory at boot. The table is now dropped correctly by the installer and by the 3.2.2 upgrade script, so existing installations are cleaned up as well. -
Client-side sanitization helpers rewritten after CodeQL findings -
decodeStorageEntities()chained 18 replacements and decoded&before", so a stored&quot;came back as a live quote; it is now a single pass over an entity map, where a character produced by a substitution is never rescanned.sanitizeString()tried to strip<script>blocks with a regular expression that missed</script >and every other tag able to run JavaScript, while leaving<and>unescaped; the filter is replaced by escaping the angle brackets. Incsrfprotector.js,\sinside a template literal collapsed to a plains, so the cookie separator became;s*and no cookie but the first could be read.
🛠️ Improvements
-
The admin dashboard information block is now adaptive - the "Teampass information" card only ever listed pending maintenance operations, so it was empty on a fresh installation and on any healthy up-to-date instance, leaving a blank card next to system health. It is renamed Actions required, its content is collected before rendering, and the card disappears entirely when there is nothing to report, system health then takes the full width. The card colour and a counter follow the most severe notice. Five getting-started recommendations are added (scheduled backup, MFA, external authentication source, API over HTTPS, first shared folder) so a fresh installation gets a useful checklist; they are dismissible per administrator, while maintenance notices are not. Two warnings that were hard-coded in English now use language keys.
-
The file integrity manifest no longer lists development files - the 3.2.2.1 manifest still carried 54 entries of repository metadata vendored inside dependencies (
.github/workflows,.gitignore,.travis.yml,.editorconfig,.php-cs-fixer*, and more), because the path policy only matched prefixes anchored at the repository root. It now applies a structural rule (a top-level hidden directory is tooling metadata) plus known CI/editor directory names and development metadata basenames matched at any depth, so a vendored package or a newly added tool directory is covered with no list to maintain.
🐛 Bug fixes
-
Docker containers could end up unable to log in after a patch upgrade - the entrypoint decided whether the database was up to date by comparing
teampass_versionwithTP_VERSION. That value never storesTP_VERSION_MINOR, so a patch release shipping a migration inside the existingupgrade_run_3.2.2.php(3.2.2.1 addeditems.revision_changed_at) looked identical to the previous one. The container skipped the migration and then removedpublic/install/, while the application (testingupgrade_timestampagainstUPGRADE_MIN_DATE) demanded an upgrade and disabled the login button, leaving no way to recover. The entrypoint now reads the same signal as the application, replays the current version's migration when the schema floor is stale, and never removes the install directory while an upgrade would still be required. -
Command palette (Ctrl+K) returned no items (PR #5359, @guerricv) - the item-level restriction clause was built against the wrong table alias, so the search matched nothing. The regression guard around it was also relaxed to assert the alias and the join that makes it usable, instead of pinning the exact argument expressions, and the search-cache normalization of an empty
restricted_tois now covered on both representations. -
Documentation links to
DOCKER.mdandDOCKER-MIGRATION.mdpointed at the repository root instead ofdocs/.
⬆️ Upgrade notes
- Schema. No
ALTER TABLE. The upgrade runsDROP TABLE IF EXISTS \_install`, removing the temporary installation table and the clear-text administrator password it held.UPGRADE_MIN_DATEis raised to1788498749, so **every installation goes through the upgrade wizard once**, including those already running 3.2.2.1, that is deliberate: the timestamp is the only signal that separates two releases sharingTP_VERSION` 3.2.2. - Cron / scheduled tasks. If anything in your environment calls
https://<your-teampass>/sources/scheduler.phpover HTTP, it will now return404. The supported invocation has always been the CLI one (php /path/to/teampass/app/sources/scheduler.php) which is what the documentation, the Docker entrypoint and the Windows scheduled-task builder already use. Check your crontab if you built it by hand. - Docker. After upgrading, the container replays the current version's migration when the recorded schema level is behind the image, and keeps
public/install/until the upgrade has actually completed. No manual step is required. - Admin dashboard. The "Teampass information" card is now "Actions required" and is hidden when there is nothing to act on, a blank card is no longer expected. The new getting-started recommendations are dismissed per administrator and stored in the browser, so each administrator dismisses their own.
- Back up your database before upgrading, as always.
Full Changelog: 3.2.2.1...3.2.2.2
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.