github nilsteampassnet/TeamPass 3.1.7.0

2 hours ago

What's Changed

Highlights

TeamPass 3.1.7.0 is a major feature release introducing real-time WebSocket synchronization, a complete overhaul of the permissions engine, significant performance improvements, and a wide range of security hardening and bug fixes accumulated across five release candidates.

New Features

Real-Time WebSocket Synchronization

A new WebSocket server (Ratchet 0.4.4 + ReactPHP) provides live updates across all connected clients without page refresh.

  • Item events — create, update, delete, and move operations are broadcast instantly to all users viewing the same folder.
  • Edition locking — when a user opens an item for editing, all other users see a live lock indicator. The lock is released automatically on disconnect, save, or cancel.
  • Folder events — folder create, rename, delete, and permission changes are pushed in real time.
  • User & task events — encryption key readiness (user_keys_ready), background task progress, session expiry, and system maintenance notifications.
  • Role permission refresh — when an administrator changes role permissions, all affected users receive a folder-tree refresh immediately without re-login.
  • Auto-reconnect — the JS client reconnects with exponential backoff (max 30 s, 10 attempts) and a secure reconnect token (never passed in URLs).
  • Systemd unit (teampass-websocket.service) included for production deployments.
  • WebSocket can be enabled/disabled from the admin panel; host/port are configurable via teampass_misc.

Permissions Engine Overhaul

  • Direct folder grants restored — folders assigned directly to a user (via users_groups) always grant full write access, regardless of any role-level restriction on the same folder.
  • Least-permissive multi-role resolution — when a user holds multiple roles that disagree on a folder's access level, the most restrictive permission wins (write > no-delete > no-export > read).
  • Effective permission helper (evaluateFolderAccesLevel()) introduced in main.functions.php and used consistently across items and users.
  • Deprecated list_folders_limited and list_restricted_folders_for_items session variables removed; all checks now use the unified user-accessible_folders.
  • Per-user direct grants now passed as the base allowed set to identUserGetPFList(), restoring correct folder visibility after a role change.

Folder Rights Panel Redesign (Users page)

  • Folder rights now displayed in a scrollable modal instead of an inline card.
  • Animated progress bar while folder data loads.
  • Client-side filter buttons for permission types (W / ND / NE / R / no access).
  • "Roles" column showing one badge per contributing role and its individual permission type.

Roles & Folders Page Improvements

  • Folder list loads faster with continuous (non-blocking) rendering.
  • Forms replaced by modals for a cleaner UX.

Options Management

API Enhancements

  • New endpoint GET /api/item/allTags — returns all tags across items accessible to the authenticated user.
  • Browser extension: accessible folders now resolved from cache_tree instead of the JWT payload, preventing stale folder lists after permission changes.

Browser Extension — Dashboard Status

  • Admin dashboard now displays the browser extension licence status.

Performance Improvements

APCu Configuration Cache

ConfigManager caches the full teampass_misc settings table in APCu shared memory (60 s TTL, key teampass_settings_v1). Cache is invalidated automatically after any write via ConfigManager::invalidateCache(), eliminating redundant DB reads on every request.

Optional Redis Session Storage

SessionManager supports Redis-backed sessions via RedisSessionHandler wrapped by EncryptedSessionProxy. Falls back to filesystem on connection failure. Configurable via redis_host, redis_port, redis_prefix, and redis_session_enabled in teampass_misc. gc_maxlifetime is now set dynamically to prevent premature PHP garbage collection.

Batch Sharekey Upserts

storeUsersShareKey() now executes a single batched INSERT … ON DUPLICATE KEY UPDATE (chunked at 100 rows) instead of N individual queries, reducing DB round-trips from O(users) to O(1) per item save.

cache_tree Optimizations

  • N+1 SQL queries in tree.php replaced with in-memory lookups (pre-loaded $completTree), reducing ~400–600 queries to 1 for a 200-folder tree.
  • Per-user cache invalidation via a new invalidated_at column — only users with access to the affected folder have their cache marked stale. Global invalidation (last_folder_change) removed.
  • Visible folders are now built synchronously in the same rebuild pass; a separate async background task is no longer needed.
  • Missing idx_user_id index added to cache_tree.user_id.

WebSocket Poll Interval

EventBroadcaster poll interval reduced from 200 ms to 500 ms to lower contention on teampass_websocket_events under high load.

Items Page

  • Unnecessary AJAX calls removed during item edition.
  • Item list refresh triggered immediately on add/delete.
  • Faster item save (background encryption task launched immediately).
  • Improved multi-item edition with immediate lock release.

Security

SQL Injection Fixes (API)

  • In ItemController (getAction, inFoldersAction, findByUrlAction): JWT folder/item IDs now sanitised with array_map(intval, ...).
  • User-supplied label/description passed through DB::escape() instead of raw string interpolation.
  • Internal exceptions logged server-side; only a generic message returned to the client.
  • N+1 sharekey queries in findByUrlAction() replaced with a single IN() query.

WebSocket Security Hardening

  • Single-use tokens: validateFromToken() now enforces used = 0 and marks the token used atomically on success; token validity reduced from 3600 s to 60 s.
  • Reconnect token: a long-lived reconnect token is generated after successful initial auth and transmitted only over the WS channel (never in a URL); the JS client uses it for all subsequent reconnection attempts.
  • Object injection prevention: @unserialize replaced with allowed_classes restriction.
  • Per-user API permissions: WS token holders now receive permissions from teampass_users.api_allowed_to_* columns instead of unconditional full CRUD access.
  • IP-based rate limiting for failed auth attempts (max 10 failures / 60 s per IP), applied before any credential validation.
  • Double-delivery prevention: EventBroadcaster poll+mark cycle wrapped in a DB transaction with SELECT FOR UPDATE.
  • Expired websocket_tokens purged in the existing hourly cleanup timer.

XSS Prevention

  • Sanitisation added on two newly exposed fields to prevent XSS.
  • Guard added in main.functions.php when the master encryption key is empty.

HTTP Security Headers (API)

X-Content-Type-Options, X-Frame-Options, and Referrer-Policy headers added to all API responses.

AES Private Key Migration

xss_clean() removed from AES private key derivation path (it was corrupting binary-safe key material); transparent migration added for existing keys.

Bug Fixes

Issue Description
#5104 OAuth2 / Azure Entra — three bugs fixed: FK violation on new user creation, missing name/email in DB and missing confirmation email, "login credentials do not correspond" error on second login
#5108 Items list showed wrong access rights after a role was deleted because restriction_to_roles was not cleaned up; restriction_to_roles is now purged on role deletion and an INNER JOIN is used in the rights query
#5111 mfa_auth_requested_roles was not re-computed after LDAP checks, causing MFA to be skipped in some configurations
#3956 AD group-to-role mapping broken: binary objectGUID is now normalised to a formatted string so it matches getADGroups() output; ldap_groups_roles deduplicated and UNIQUE KEY added on ldap_group_id
#5114 Miscellaneous fixes (see commit 8e8df67)
#5124 Missing SQL instruction in fresh install process
#5103 Fallback crash when preg_split() returns false
#5106 Admin page fix
#5102 Several bugs identified and fixed in the items view
#5065 Items page improvements and fixes
#5131 Implemented and improved (see commit cf05e9ec)
#5132 Applied provided fix
2FA method selector was shown to all users regardless of whether their role required MFA; now only displayed when relevant
Notification bug when notifications are enabled for an item
When another user updates an item currently being browsed, the UI now refreshes automatically
Session-error modals now displayed when server returns ERROR NOT ALLOWED, ERROR SESSION EXPIRED, or the forced-disconnection message
Fix WebSocket start/stop control in admin panel when the daemon is managed by systemd
Docker installer: DB connection over TCP fixed; Docker documentation updated
MySQL ONLY_FULL_GROUP_BY compatibility fixed across all SQL queries
Manager access correctly restricted to System Health and specific user views
Files Integrity Check: warning block added for folders that cannot be parsed due to permission errors
Admin Dashboard: direct shortlink added to System Health card
Item moved events now broadcast via WebSocket; edition lock correctly shown in item detail panel
Edition lock enforced on item delete and move operations
Permissions: create right, role restrictions, and item form fixes applied

Upgrade Notes

Database Schema Changes (upgrade_run_3.1.7.php)

  • New tables: teampass_websocket_events, teampass_websocket_tokens, teampass_websocket_connections.
  • New table: teampass_cache_tree improvements (invalidated_at column, idx_user_id index).
  • New table: teampass_favorites.
  • roles_values table: orphans and duplicates purged, UNIQUE KEY added.
  • ldap_groups_roles: deduplicated, corrupted INT(12) entries purged, UNIQUE KEY on ldap_group_id.
  • New teampass_misc settings: redis_session_enabled, redis_host, redis_port, redis_prefix, websocket_enabled, websocket_host, websocket_port.
  • AGSES column renamed.

PHP Extensions

The installer and upgrade wizard now check for (optional) extensions: OPcache, APCu, ext-redis, PHP-FPM. None are mandatory, but APCu and Redis are recommended for production performance.

Composer

  • firebase/php-jwt upgraded from v6.9 to v7.0.
  • All other Composer dependencies updated.

WebSocket Daemon (optional)

If you want real-time synchronisation, start the WebSocket daemon:

php /path/to/teampass/websocket/bin/server.php
# or use the provided systemd unit:
systemctl enable --now teampass-websocket

The daemon requires ext-pcntl and ext-posix (CLI only). Configure websocket_enabled = 1 in Admin > Settings.

Code Quality

  • PHPStan analysis raised to level 4 (previously level 1); errors fixed across sources/, api/, and custom classes.
  • PHPUnit setup added with initial test suite covering authentication flows and the Encryption class.
  • Encryption::decrypt() null guard added.
  • scan_corrupted_items.php diagnostic script added under scripts/.

Removed / Deprecated

  • list_folders_limited and list_restricted_folders_for_items session variables removed.
  • Deprecated direct folder restriction mechanisms removed from the permission engine.

Full Changelog

3.1.6.13...3.1.7.0

Important

  • Requires at least PHP 8.1

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.