Skip to content

V5 folder creation fails when Log plugin validates folder history #617

Open

Description

@GitKa3sar
  • API: Community Edition 5.14.3 (passbolt/passbolt:5.14.3-1-ce)
  • Environment
    • Operating system: official Docker image, Debian GNU/Linux 13
    • PHP: 8.4.24
    • Web server: nginx 1.26.3
    • Database server: MariaDB 10.11.18

What you did?

With the standard Metadata, Folders, and Log plugins enabled, I authenticated normally and attempted to create a personal metadata-v5 folder through:

POST /folders.json?api-version=v2

The request used the same v5 shape exercised by MetadataFoldersCreateControllerTest:

{
  "metadata": "<valid encrypted PASSBOLT_FOLDER_METADATA message>",
  "metadata_key_id": "<valid metadata key UUID>",
  "metadata_key_type": "user_key",
  "folder_parent_id": null
}

No plaintext name was supplied. MetadataFolderDto treats this as a v5 payload and rejects mixing a non-null v4 name with v5 metadata.

Reproduction outline:

  1. Enable v5 metadata settings and leave the standard Folders and Log plugins enabled.
  2. Authenticate a valid user through the normal Passbolt authentication flow.
  3. Produce valid encrypted and signed PASSBOLT_FOLDER_METADATA for the user's metadata key.
  4. POST the request above to /folders.json?api-version=v2.
  5. Inspect the API response and aggregate database state.

No private URL, account identity, credential, OpenPGP fingerprint, remote object identifier, or ciphertext is included in this report.

What happened?

The endpoint returned HTTP 400 with:

Could not validate folder history data.

The transaction rolled back completely. Aggregate checks immediately after the failure showed:

  • folders: 0 rows;
  • folders_history: 0 rows;
  • orphan folder-history rows: 0;
  • folders without history rows: 0;
  • CHECK TABLE folders, folders_history: both OK.

The causal path appears to be:

  1. MetadataFolderDto::toArray() includes name => null for v5 and validates that v4 and v5 metadata fields are not mixed.
  2. FolderSaveV5AwareTrait selects FoldersTable::validationV5(), which removes the v4 name validation and validates encrypted metadata instead.
  3. FoldersCreateService saves the folder inside a transaction.
  4. The standard Log plugin handles Model.afterSave.
  5. EntitiesHistoryCreateService detects the detailed FoldersHistory association and calls FoldersHistoryTable::create($entity->toArray()).
  6. FoldersHistoryTable::validationDefault() still requires a non-empty plaintext name, while its accessible history fields are only id, folder_id, and name.
  7. FoldersHistoryTable::create() throws the validation exception, rolling back the folder transaction and returning HTTP 400.

This does not appear to be caused by residual or corrupt laboratory data: both tables were empty and healthy after rollback, the application endpoint was healthy, the database container was healthy, and the Passbolt container had zero restarts.

I also reviewed the official v5.14.3...v5.15.0 comparison. v5.15.0 does not change:

  • plugins/PassboltCe/Folders/src/Model/Table/FoldersHistoryTable.php;
  • plugins/PassboltCe/Log/src/Events/ActionLogsModelListener.php;
  • plugins/PassboltCe/Log/src/Service/EntitiesHistory/EntitiesHistoryCreateService.php.

The v5.15.0 release notes do not identify a corresponding folder-history fix.

What you expected to happen?

  • HTTP 2xx for a valid metadata-v5 folder request.
  • Atomic persistence of the v5 folder, owner permission, and optional folder relation.
  • Successful audit/history recording without requiring a plaintext folder name that is intentionally absent from v5 metadata.
  • A response containing the new folder identifier and v5 metadata fields.

Because the server cannot generally decrypt personal v5 folder metadata to reconstruct a plaintext name, a fix should preserve audit semantics without disabling the Log plugin or requiring clients to send both v4 and v5 metadata.

A regression test could enable Metadata, Folders, and Log together, establish the real FoldersCreate.create UserAction context, create personal root and child v5 folders without plaintext name, and assert both the HTTP success and internal consistency of the action log/history representation.

Relevant public sources:

Activity

  1. pbottero commented on Oct 13, 2026

    @pbottero

    Confirming this is still present in passbolt CE 5.16.0 (docker 5.16.0-1-ce-non-root).

    It is not limited to personal folders: with zero-knowledge metadata key sharing and only v5 types allowed, a v5 folder encrypted with the shared metadata key (metadata_key_type: shared_key) fails the same way, with {"name":{"_required":"A name is required."}}.

    We are carrying a local patch until this is merged. The approach in #618 (nullable folders_history.name, a v5 validator, v4 still requiring a name) would let us drop it. Tested on our side with the patch in and out on the same database: v5 folders, shared and personal, are created and the history row is written; v4 is still rejected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions