VYPR
Medium severityNVD Advisory· Published Jun 11, 2026· Updated Jun 11, 2026

CVE-2026-53912

CVE-2026-53912

Description

Cerebrate before version 1.37 exposed credential material from self-registration requests. The self-registration workflow stored the registrant’s hashed password in the inbox message data payload. This payload was returned unredacted through inbox index and view responses, including HTML, JSON, and CSV outputs, and could also be written unredacted into audit log entries for the inbox message.

An authenticated user with sufficient privileges to access inbox entries or related audit logs could retrieve password hashes associated with pending self-registration requests. Although the exposed value is a password hash rather than a plaintext password, disclosure of password hashes may enable offline password-cracking attempts and could increase risk where users reuse passwords across systems.

Cerebrate 1.37 fixes the issue by redacting sensitive password and authkey fields from inbox display/API output and recursively redacting those fields from JSON values written to audit logs, while leaving the stored registration payload intact for account creation processing.

Affected component: Inbox self-registration request handling and audit logging

Fixed version: Cerebrate 1.37

Affected products

2

Patches

1
02da6d708d61

fix: [security] redact registration password hash from inbox views and audit logs

https://github.com/cerebrate-project/cerebrateiglocskaJun 10, 2026via nvd-ref
5 files changed · +102 2
  • src/Controller/InboxController.php+9 2 modified
    @@ -136,7 +136,10 @@ public function index()
                         ],
                     ],
                 ],
    -            'contain' => $this->containFields
    +            'contain' => $this->containFields,
    +            'afterFind' => function ($entity) {
    +                return $this->Inbox->redactSensitiveData($entity);
    +            }
             ]);
             $responsePayload = $this->CRUD->getResponsePayload();
             if (!empty($responsePayload)) {
    @@ -151,7 +154,11 @@ public function filtering()
     
         public function view($id)
         {
    -        $this->CRUD->view($id);
    +        $this->CRUD->view($id, [
    +            'afterFind' => function ($entity) {
    +                return $this->Inbox->redactSensitiveData($entity);
    +            }
    +        ]);
             $responsePayload = $this->CRUD->getResponsePayload();
             if (!empty($responsePayload)) {
                 return $responsePayload;
    
  • src/Model/Behavior/AuditLogBehavior.php+24 0 modified
    @@ -184,6 +184,15 @@ private function changedFields(EntityInterface $entity, $fieldsToSave = null)
                     if ($old !== null) {
                         $old = $value;
                     }
    +            } else {
    +                // JSON columns (e.g. Inbox.data for user registration requests)
    +                // can carry credentials nested inside the payload
    +                if (is_array($value)) {
    +                    $value = $this->redactNestedSensitiveFields($value);
    +                }
    +                if (is_array($old)) {
    +                    $old = $this->redactNestedSensitiveFields($old);
    +                }
                 }
     
                 if ($old === null) {
    @@ -195,6 +204,21 @@ private function changedFields(EntityInterface $entity, $fieldsToSave = null)
             return $changedFields;
         }
     
    +    /**
    +     * Recursively mask sensitive keys inside array (JSON column) values.
    +     */
    +    private function redactNestedSensitiveFields(array $data): array
    +    {
    +        foreach ($data as $key => $value) {
    +            if ($key === 'password' || $key === 'authkey') {
    +                $data[$key] = '*****';
    +            } else if (is_array($value)) {
    +                $data[$key] = $this->redactNestedSensitiveFields($value);
    +            }
    +        }
    +        return $data;
    +    }
    +
         /**
          * @return AuditLogs
          */
    
  • src/Model/Table/InboxTable.php+22 0 modified
    @@ -46,6 +46,28 @@ protected function _initializeSchema(TableSchemaInterface $schema): TableSchemaI
             return $schema;
         }
     
    +    public const REDACTED_DATA_FIELDS = ['password', 'authkey'];
    +
    +    /**
    +     * Mask credential material stored in the message payload (e.g. the hashed
    +     * password from a self-registration request) so it never reaches any view
    +     * or API response. The stored value is left untouched, as processors
    +     * (e.g. user registration) still need it.
    +     */
    +    public function redactSensitiveData($entity)
    +    {
    +        if (!empty($entity->data) && is_array($entity->data)) {
    +            $data = $entity->data;
    +            foreach (self::REDACTED_DATA_FIELDS as $field) {
    +                if (isset($data[$field])) {
    +                    $data[$field] = '*****';
    +                }
    +            }
    +            $entity->data = $data;
    +        }
    +        return $entity;
    +    }
    +
         public function validationDefault(Validator $validator): Validator
         {
             $validator
    
  • tests/TestCase/Api/Inbox/IndexInboxApiTest.php+10 0 modified
    @@ -33,4 +33,14 @@ public function testIndexInbox(): void
             $this->assertResponseContains(sprintf('"uuid": "%s"', InboxFixture::INBOX_USER_REGISTRATION_UUID));
             $this->assertResponseContains(sprintf('"uuid": "%s"', InboxFixture::INBOX_INCOMING_CONNECTION_REQUEST_UUID));
         }
    +
    +    public function testIndexInboxRedactsRegistrationPassword(): void
    +    {
    +        $this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
    +        $this->get(self::ENDPOINT);
    +
    +        $this->assertResponseOk();
    +        $this->assertResponseContains('"password": "*****"');
    +        $this->assertResponseNotContains('$2y$10$');
    +    }
     }
    
  • tests/TestCase/Api/Inbox/ViewInboxApiTest.php+37 0 added
    @@ -0,0 +1,37 @@
    +<?php
    +
    +declare(strict_types=1);
    +
    +namespace App\Test\TestCase\Api\Inbox;
    +
    +use Cake\TestSuite\TestCase;
    +use App\Test\Fixture\AuthKeysFixture;
    +use App\Test\Helper\ApiTestTrait;
    +
    +class ViewInboxApiTest extends TestCase
    +{
    +    use ApiTestTrait;
    +
    +    protected const ENDPOINT = '/inbox/view';
    +
    +    protected $fixtures = [
    +        'app.Inbox',
    +        'app.Organisations',
    +        'app.Individuals',
    +        'app.Roles',
    +        'app.Users',
    +        'app.AuthKeys'
    +    ];
    +
    +    public function testViewInboxRedactsRegistrationPassword(): void
    +    {
    +        $this->skipOpenApiValidations();
    +        $this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
    +        // id 1 is the user registration entry from InboxFixture
    +        $this->get(self::ENDPOINT . '/1');
    +
    +        $this->assertResponseOk();
    +        $this->assertResponseContains('"password": "*****"');
    +        $this->assertResponseNotContains('$2y$10$');
    +    }
    +}
    

Vulnerability mechanics

Root cause

"The Inbox index/view responses and audit log entries returned the full hashed password from self-registration request payloads without redaction."

Attack vector

An attacker who is an authenticated user with sufficient privileges to access inbox entries or audit logs can retrieve password hashes associated with pending self-registration requests [patch_id=5593505]. The self-registration workflow stored the registrant's hashed password in the inbox message data payload, and this payload was returned unredacted through inbox index and view responses (HTML, JSON, and CSV outputs) as well as written unredacted into audit log entries. Although the exposed value is a password hash rather than plaintext, disclosure enables offline password-cracking attempts and increases risk where users reuse passwords across systems.

Affected code

The vulnerability exists in `src/Model/Table/InboxTable.php` (the `data` payload returned without redaction), `src/Controller/InboxController.php` (index/view responses), and `src/Model/Behavior/AuditLogBehavior.php` (audit log entries). The patch modifies all three files plus adds test coverage in `tests/TestCase/Api/Inbox/ViewInboxApiTest.php` and `tests/TestCase/Api/Inbox/IndexInboxApiTest.php` [patch_id=5593505].

What the fix does

The patch adds a `redactSensitiveData()` method to `InboxTable.php` that masks `password` and `authkey` fields in the data payload at display time, while leaving the stored value untouched so the registration processor can still create the account [patch_id=5593505]. The `InboxController` index() and view() methods apply this redaction via CRUD `afterFind` callbacks, covering HTML, JSON, and CSV output. Additionally, `AuditLogBehavior.php` now recursively redacts `password` and `authkey` keys nested inside JSON column values before writing audit log entries.

Preconditions

  • authAttacker must be authenticated with sufficient privileges to access inbox entries or related audit logs
  • inputA self-registration request with a hashed password must exist in the inbox

Generated on Jun 11, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

1

News mentions

0

No linked articles in our index yet.