Skip to content

Teampass

Secrets & Credentials

A collaborative, on‑premise password manager for teams

PHP Latest 3.1.7.6 · 1mo ago Security brief →

Features

  • Self‑hosted collaborative password storage
  • Supports MySQL/MariaDB and PHP 8.2+ backends
  • Multi‑language UI (20+ languages)
  • Optional Docker container deployment

Recent releases

View all 25 releases →
3.1.7.6 Breaking risk
Breaking changes
  • Minimum PHP version raised to 8.1
Notable features
  • Health dashboard now shows a dedicated info‑box for corrupted items count
  • Anti‑bruteforce options page gains lock duration field and improved UI attributes (min=0, step=1)
Full changelog

What's Changed

Security Fixes

  • Access control bypass (folders): Read-only users were able to perform write operations (edit, delete, move) on folders they only had read access to. The per-folder user-read_only_folders restriction was not enforced in the folder query handler; only the global read-only flag was checked. All three operations are now guarded individually. Folder deletions now also record the responsible user in the audit log.
  • Privilege escalation (Manager role): A Manager-level user could grant the can_create_root_folder permission to other users, which is reserved for administrators. The UI toggle and the server-side handler now both restrict this option to admins.
  • Circular folder reference: Moving a folder into one of its own descendants caused an infinite loop. A cycle-detection guard is now applied before any folder move is committed.

Bug Fixes

Authentication & LDAP

  • Infinite account-disable loop on LDAP password change: When an LDAP user changed their password and had no transparent recovery data (accounts predating that feature), handleExternalPasswordChange() unconditionally disabled the account. Re-enabling via the admin panel would trigger the same failure on the next login, creating an infinite disable loop. The function now distinguishes between "no recovery data" (updates the password hash and sets special='recrypt-private-key' without disabling) and genuine decryption failures (which still disable the account).
  • Transparent recovery false-positive: AES-CBC decryption with the wrong key can produce valid-UTF-8 garbage approximately 0.4% of the time. A -----BEGIN PEM guard is now applied after decryption so SHA-256 false-positives are caught and retried with SHA-1 before failing.
  • integrity_check_failed treated as fatal: An integrity check failure (e.g. after a server key file was restored from backup) incorrectly disabled user accounts. This condition is now treated like "no recovery data"; the user is prompted to re-enter their password via the re-encryption modal rather than being locked out.
  • Wrong private_key_backup encoding: changeUserLDAPAuthenticationPassword() was storing AES(base64(PEM)) in the backup field instead of AES(PEM). On the next LDAP password change, attemptTransparentRecovery() would fail the PEM validation guard and disable the account. The missing base64_decode() call has been added, consistent with every other backup-creation site in the codebase.
  • Anti-bruteforce configuration not applied correctly (PR #5184 by @guerricv): addFailedAuthentication() was not receiving the $SETTINGS array in all call sites, causing bruteforce limits to not be evaluated. The lock duration validation logic has been simplified, default seed values for nb_bad_authentication_by_ip and bruteforce_lock_duration are now seeded via INSERT IGNORE during upgrade, and the admin panel now includes an IP blacklist management handler.

Installation & Upgrades

  • bck_script_passkey encryption during fresh install: The backup script passkey was generated in install step 5, before the encryption key was available. Generation has been moved to step 6 where $encryptionKey is defined; an empty placeholder is inserted in step 5. cryptionForInstall() is also now guarded against undefined SECUREPATH/SECUREFILE constants to prevent a fatal crash.
  • Missing show_subfolders column: The column was absent from fresh installs and was not added by 3.1.x upgrade scripts, causing database errors. It is now created during step 5 of the installer and added by the 3.1.7 upgrade script when missing.
  • Install folder not deleted after upgrade (#5183 by @guerricv): recursiveChmod() was called with file and directory permission arguments in the wrong order, causing the recursive permission change to fail silently. The clear_install_folder flag is now consumed only when deletion actually succeeds.

Items & Folders

  • Corrupted items integrity scan (PR #5182 by @guerricv): Integrated the community-contributed corrupted items scan with fixes: replaced SQL string concatenation with MeekroDB %l placeholders, fixed severity inconsistency in notice builder, added set_time_limit(0) to prevent fatal timeouts during RSA decryption on large databases, removed a redundant ALTER TABLE, and fixed a double folder-tree load on the items page. When a password is updated, the item's corrupted state is now automatically cleared.
  • Duplicate folder name check on rename: Renaming a folder to its current name was incorrectly flagged as a duplicate. Collapse/expand UI state was also not preserved correctly after a rename.
  • Items tree refresh and profile display (#5178 by @guerricv): The folder tree load strategy (lazy vs. full) was not preserved after a profile display change triggered a page refresh. Using $(this).delay().queue() to defer the refresh was also unreliable; replaced with setTimeout(). A missing break in users.queries.php was preventing a correct JSON response for empty user_profile_update payloads.

User Management

  • Manager user list filtering: When a Manager (non-admin, non-HR-manager) had no assignable roles, the SQL WHERE clause was left with a trailing AND that broke the query and could expose all users. The filter now emits AND FALSE in that case so the result is correctly empty. The roles array is also built once with array_values(array_filter(...)) and shared between the SQL filter and the PHP-side in_array check, eliminating mismatches caused by empty string entries in the session value.
  • Role and administration-role dropdowns in user edit: Admins and users with the global user-management permission now see all available roles in the role and administration-role selectors when editing a user, instead of only their own roles. Role-managers without that permission continue to see only the roles they personally hold.
  • Pagination state reset on user list: If the DataTable pagination state saved by the browser pointed beyond the total number of visible users (e.g. after a user was deleted), the list appeared empty. The offset is now reset to page 0 in that case.

Logs

  • Failed authentication log table (#5184 by @guerricv): Columns were reordered (IP address now shown before user agent), horizontal scrolling is enabled, and responsive/auto-width modes are disabled to prevent column layout issues on smaller screens.

Improvements

  • Health dashboard: The corrupted items count is now displayed as a dedicated info-box on the Health overview page.
  • Anti-bruteforce options page (#5184 by @guerricv): The bruteforce settings fields now have min=0 and step=1 attributes and improved keyword tagging for the settings search. A lock duration field has been added alongside the existing attempt count.
  • Orphan objects maintenance task.

Full Changelog

https://github.com/nilsteampassnet/TeamPass/compare/3.1.7.5...3.1.7.6

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.

3.1.7.5 Breaking risk
Breaking changes
  • Minimum PHP version raised to 8.1
Notable features
  • Online Users Panel with avatar rendering and visibility toggle
  • Health Logs Settings administration section with hardened path validation
  • Browser Extension FQDN auto-persist when API is enabled
Full changelog

What's Changed

New Features

  • Online Users Panel - Added a sidebar drawer showing currently connected users, with avatar rendering and configurable visibility toggle in settings (#5155)
  • Health Logs Settings - New administration section to configure and manage runtime/health log file paths,
    with hardened path validation (blocks path traversal via realpath()) (#5168)
  • Browser Extension FQDN Auto-persist - When enabling the API, the browser extension FQDN is now automatically saved (#5169)

Bug Fixes

  • Custom field encryption state mismatch -Fixed read path in show_details_item: raw ciphertext was returned to the client when encrypted_data=0 but encryption_type='teampass_aes'; the branch now returns a decryption_failed error instead (#5161)
  • LDAP authentication with special characters in password — Fixed authentication failure for passwords containing certain special characters (#5160)
  • Folder filter UX - Fixed broken folder filter UI behavior; action buttons are now properly disabled when appropriate (#5174)
  • Backup passkey handling - Refactored and fixed backup script passkey resolution, encryption, and storage logic; passkey is now properly encrypted during installation
  • Create folder when no folder exists - Fixed crash when creating the first folder in an empty tree
  • File permissions hardening - Improved install/upgrade requirement checks for file permissions
  • Import feature access - Admin users can now access the Import feature even when it is disabled for regular users
  • Password dialogs - Fixed several issues in password display and copy dialogs (#5157)

Improvements

  • Backup passkey management - Fully refactored passkey resolution logic with clearer logging and better key candidate handling
  • Split view / full screen item view - Refactored view switching logic for better reliability
  • Admin page - Grouped and reorganized CSS classes; removed stale admin.js.php
  • Users page - Various UX improvements
  • XSS protection - Added tpEscapeHtml() utility function for consistent HTML escaping in JS

Full Changelog

https://github.com/nilsteampassnet/TeamPass/compare/3.1.7.4...3.1.7.5

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.

3.1.7.4 Security relevant
⚠ Upgrade required
  • Minimum PHP version raised to 8.1
  • FontAwesome upgraded to version 7.2 (including symbolic link path fix)
Security fixes
  • Custom field encryption performed before database INSERT, removing plaintext persistence window; added decryptUserObjectKeyWithMigration() migration handling and cleanup of orphaned encrypted rows during personal→public folder moves
Notable features
  • BIP-39 passphrase generator with multi‑language support (8 languages) and client‑side generation
  • Reveal toggle eye icon for masked custom field values in item detail view
  • Server‑side PasswordGeneratorService meeting folder complexity requirements
Full changelog

What's Changed

New Features

BIP-39 Passphrase Generator

A passphrase generator is now available alongside the existing password generator in the item creation and edit forms. It uses BIP-39 word lists and supports 8 languages (English, French, Spanish, Italian, Czech, Portuguese, Japanese, Chinese) with automatic fallback to English. Options include word count (3–8), separator character, and capitalization. Word count minimum is driven by the folder's complexity requirement. Separator preference is persisted in localStorage across sessions. All generation is client-side using crypto.getRandomValues(); no server round-trip or external call at runtime.

Reveal Toggle for Masked Custom Fields

An eye icon button now appears next to the copy button on masked custom fields in the item detail view. Clicking it toggles between the asterisk placeholder and the actual field value, using the same fa-eye / fa-eye-slash pattern as the password reveal button.

Server-Side Smart Password Generation

A new PasswordGeneratorService class generates passwords server-side that meet a folder's minimum complexity requirement in a single call, replacing the previous client-side iterative AJAX loop.


Bug fixes

Custom Fields — Encryption Atomicity Gap (Security)

Custom field values are now encrypted before INSERT instead of after, eliminating the window where plaintext could be persisted if the subsequent UPDATE failed. All read paths (show_details, copy_item) now use decryptUserObjectKeyWithMigration(), enabling transparent phpseclib v1→v3 migration on read. During a personal→public folder move, non-encrypted fields are skipped and orphaned encrypted field rows (whose sharekey is missing) are deleted and logged rather than left permanently undecryptable.

"New Item" Button — "Please select a folder" Error After Login

itemsListFolderId was not updated when navigating the folder tree directly. On a fresh page load, if the user clicked "New" before the jstree state plugin fired select_node.jstree, both fallback values were false and the folder selection error appeared despite the tree showing a selected folder. Fixed by syncing itemsListFolderId with selectedFolder on every tree selection, and falling back to selectedFolder in the loaded.jstree handler.

Subfolders Not Shown on Page Load When Session Folder Is Restored

Subfolders were not displayed when a previously selected folder was restored from the session on page load.

Personal Folder — Sharekey Ownership Integrity

Fixed a bug in EnsurePersonalItemHasOnlyKeysForOwner() that could leave stale sharekeys for other users on personal items.


Maintenance

FontAwesome Upgraded to 7.2

The FontAwesome library has been upgraded to version 7.2, including a fix for the symbolic link path.

Full Changelog

https://github.com/nilsteampassnet/TeamPass/compare/3.1.7.3...3.1.7.4

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.

3.1.7.3 Bug fix
⚠ Upgrade required
  • Requires at least PHP 8.1
Notable features
  • Loading spinner added to password field during fetch/decrypt
  • Parallel privilege check improves edit‑form latency
  • Version badge now uses in‑memory ConfigManager cache and DNS pre‑flight check
Full changelog

What's Changed

Bug Fixes

Item editing

  • Fixed custom fields from previously visited folders accumulating in the new/edit form when switching folders without a page reload. All category fields are now properly hidden before revealing only those belonging to the current folder (#5147).
  • Fixed subfolders not being displayed after saving an item. groupe_id is now normalized with parseInt() before being passed to displaySubfolders().
  • Fixed password field in edit form not loading the actual password when opening the edit view via the pencil icon from the item list (#5144 by @guerricv).
  • Restore password modal display for local user password generation flows (#5143 by @guerricv).
  • Improve user attribution in the task manager for several background task types that were displayed as anonymous (#5143 by @guerricv).
  • Fix unusable Select2 dropdowns in the folder edit right sidebar (#5140 by @guerricv).
  • Persist the selected folder depth filter on the folders page for the current browser session (#5140 by @guerricv).
  • Fix item password complexity refresh/generation consistency and list duplicate refresh after deletion (PR #5141 by @guerricv) (Fix #5138, #5139.

Docker / restricted PHP environments

  • Fixed a fatal error during upgrade prerequisites check when exec() is disabled via disable_functions in php.ini (e.g. Docker). The call is now guarded with function_exists('exec') and gracefully reports missing optional extensions instead of crashing. (#5137)
  • Fixed CSRF cookie Secure flag being forced to true during installation on HTTP deployments (Docker without a reverse proxy). The flag is now derived from the configured URL protocol, preventing silent login failures. (#5137)
  • Fixed a fatal error in background task handler (triggerBackgroundHandler) when exec() is disabled, and corrected an early-return issue in step99 that could prevent task completion. (#5127)

Access rights & sharekeys

  • Fix users admin panels visibility/authorization and notify admins on account lock (PR #5135 by @guerricv)
  • Fixed access rights check during copy_item and move_item operations. getItemFolderIdFromDb() was silently overriding the caller's $treeId, causing incorrect permission evaluation on the target folder.
  • Fixed deleteUserObjetsKeys() incorrectly cleaning up file sharekeys: object_id in sharekeys_files references files.id, not items.id. The query now uses the correct files JOIN items join.

Performance

  • Eliminated a duplicate get_complixity_level backend request when opening item edition. The edit form now reads complexity/visibility data from the store already populated by getPrivilegesOnItem().
  • Cached SHOW COLUMNS results in EnsurePersonalItemHasOnlyKeysForOwner() with a static variable; schema discovery queries now execute once per PHP process instead of on every call.

Improvements

Password field UX in edit form (#5141 by @guerricv)

  • Added a loading spinner in the password field while the encrypted password is being fetched and decrypted.
  • Password fetch and privilege check now run in parallel, reducing total latency when opening the edit form.

Version badge (admin panel) (#5146 by @guerricv)

  • Version badge now reads the release cache from ConfigManager (already in memory) instead of issuing separate DB queries.
  • Added a DNS pre-flight check (checkdnsrr()) before any GitHub API call; the check is skipped entirely on air-gapped servers.
  • Added a browser-side sessionStorage cache (4h TTL) to avoid redundant AJAX calls on subsequent page loads within the same session.

Enhancement: enforce Network ACL on API entry point (#5142 by @guerricv)

  • The web UI ACL is already enforced early in the application bootstrap. This change applies the same ACL evaluation logic to the API so that blocked IPs cannot: request an authorization token, call authenticated API endpoints, and bypass the web ACL by using the API directly.

Security badge on passwords

  • Item detail panel now displays a green Secure or red Not secure badge next to the password label, based on an OWASP ASVS-aligned policy (minimum length ≥ 12 and complexity score ≥ 70).

Database integrity

  • Added a UNIQUE KEY on teampass_misc(type, intitule) to prevent duplicate settings rows.
  • All INSERT statements targeting teampass_misc are now idempotent (INSERT IGNORE / ON DUPLICATE KEY UPDATE).

Documentation

  • Improved server migration guide.
  • Updated GitHub issue report template with a more structured format.

Full Changelog

https://github.com/nilsteampassnet/TeamPass/compare/3.1.7.2...3.1.7.3

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.

3.1.7.2 Breaking risk
⚠ Upgrade required
  • Requires at least PHP 8.1
Notable features
  • REST API now enforces configured network ACL rules (403 Forbidden for blocked IPs)
  • Folder depth filter state persisted via store.js across reloads
  • Logs datatable functions reordered to eliminate forward references
Full changelog

What's Changed

Bug Fixes

Active Directory - objectGUID byte order

Fixed a long-standing bug where AD group lookup failed silently for users authenticating via Azure AD / Active Directory. The manual byte-sequential unpacking of objectGUID produced a byte-swapped UUID that never matched the value shown in the AD portal.
Replaced with LdapRecord\Models\Attributes\Guid which handles the Windows mixed-endian byte order correctly.

Password generator - search retry loop (PR #5141)

Fixed a regression where the password generator could skip already-tried sizes when retrying in both directions. The retry loop now checks both lowerTriedSizes and upperTriedSizes on every iteration, preventing redundant AJAX calls. A missing warning message is now shown via toastr when the generator cannot find a password matching the required complexity.

Admin - change user password dialog reset (PR #5143)

Removed a duplicate .prop('checked', false) call that fired before resetAdminChangeUserPasswordDialogContext(), causing a visual glitch where the password checkbox flickered on dialog open.

Background tasks - user display in logs (PR #5143)

Fixed log entries where background task rows showed no user name. getBackgroundTaskUserDisplayFromUserId() now correctly falls back to login when name/lastname are empty, and HTML entities are decoded then re-encoded safely before output.

Email recipient name in new-user notification (PR #5143)

Fixed emails sent to new users having a blank recipient name. The task handler now builds the display name from name + lastname, falling back to login when both are empty.

Improvements

API - network ACL enforcement (PR #5142)

The REST API (/api/index.php) now enforces the network access control rules configured in TeamPass settings. Requests from blocked IP ranges receive a 403 Forbidden response with a localized error message. Language detection from Accept-Language header is supported (English and French).

Folder depth filter - persistent state (PR #5140)

The folder depth filter selection is now persisted across page reloads via store.js instead of sessionStorage, consistent with the rest of the TeamPass client-side state management.

Items page - code simplification

Eight single-use helper functions in items.js.php have been inlined at their call sites, reducing indirection and making the file easier to follow. A redundant websocketClientAvailable check in reloadItemDetailsAfterSave was removed (the condition reduces to websocketExpected only).

Logs datatable - function ordering

Moved normalizeBackgroundTaskDisplayValue(), getBackgroundTaskUserDisplayFromUserId(), and resolveBackgroundTaskUserDisplay() above their first call site in logs.datatables.php to eliminate forward-reference issues.

Full Changelog

https://github.com/nilsteampassnet/TeamPass/compare/3.1.7.1...3.1.7.2

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.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

About

Stars
1,790
Forks
570
Languages
PHP JavaScript CSS

Install & Platforms

Install via
docker

Community & Support

Beta — feedback welcome: [email protected]