Field Encryption prevents UniqueField from working as intended

Created on 7 July 2025, 7 days ago

Problem/Motivation

(This issue was originally reported by arousseau to the security issue queue. The security team and module maintainers have decided to make this report public.)

Using the Field Encryption module, I came across an unexpected side effect, upon enabling encryption of a configurable user field.

This particular field had a "UniqueField" constraint added to it through custom code.
After enabling encryption, I noticed the unique field constraint stopped working, and entity validation did not flag duplicated values for this field anymore.

I read through the code of core's \Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator class and realized it relied on an entity query, to determine if the value
being validated was unique for the given field.

Field Encryption replaces the value stored in a field's table with a placeholder value, and moves the encrypted value to a encrypted_field_storage__value column (in the users_field_data table in the case of a user field). The module then makes use of hook_entity_storage_load() to decrypt the value when needed.

This means a regular entity query cannot be used to determine the existence of a value for the field.

I don't think I've read this mentioned as a caveat in the documentation, only mentions of encrypted field not working with Views filters or JSON:API filtering.

I am not sure of the security implications.
I could imagine a case where someone would set up encryption for the "mail" base field, and it making core's UserMailUnique constraint stop working.
I know some modules like Shared Email provide this as a feature, but they only allow users with the right permission to do so, and a proper warning is displayed if an account is created, using an existing account's email.

Steps to reproduce :

- Using the field UI, add a custom string field named field_foo to the user entity
- Add the UniqueField constraint to field_foo, through a hook_entity_bundle_field_info_alter() implementation
- Setup a key and encryption profile, to use in the Field Encrypt module settings
- Edit the field configuration for field_foo, to check the "Encrypt field" and "Text value" boxes
- Run the "field_encrypt_update_entity_encryption queue, to encrypt data for this field (this can be done through the UI, using the "Process queues" tab provided in field_encrypt admin pages)
- Try setting the same value for field_foo on two different users, and see it passes validation with no error

🐛 Bug report
Status

Active

Version

4.0

Component

Code

Created by

🇯🇵Japan ptmkenny

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @ptmkenny
  • 🇯🇵Japan ptmkenny

    Comment from the security issue by ptmkenny:

    I was able to reproduce the behavior locally and confirm the bug.

    Regarding the example of the mail field, if you use the Field Encrypt module to encrypt the "mail" or "name" base field, it will break logging in to the site, but it will not (to my knowledge) expose any information; you will just have a broken site (which is not good, but it is not a security issue; I will open a follow-up issue later to fix this by not showing the mail and name fields as options). For people who need to encrypt email addresses, the Dbee module is available and works well (this should be noted on the Field Encrypt project page under Known Limitations).

    This issue is a result of the entity query in the UniqueField constraint not having access to unencrypted data, which will result in failed validation (values will always be considered unique). This is a bug, but I do not think it is a security issue because the encryption is maintained (also, this is not a case of breakage in which a feature stopped working; the module has never worked with the UniqueField constraint), so I think it is safe to work on publicly.

  • 🇯🇵Japan ptmkenny

    Comment from the security issue by alexpott:

    I think this is the same as the caveats for Views filters or JSON:API filtering but should ideally come with a solution of sorts. Maybe an error if you try to encrypt a field or some form other way of doing uniqueness without knowing the value.

  • 🇯🇵Japan ptmkenny

    For now, I have updated the module page to note this incompatiblity.

Production build 0.71.5 2024