Information
MySQL 9.7 LTS introduces Dynamic Data Masking for MySQL Enterprise Edition and OCI MySQL HeatWave. Dynamic Data Masking allows a masking policy to be attached directly to a base-table column so that MySQL returns either the original value or a masked value at query time, based on the executing user or active role. This provides server-side protection without requiring application changes or maintaining separate masked copies of data.
A masking policy is defined as a CASE expression that uses gatekeeper functions such as CURRENT_USER_IN() or CURRENT_ROLE_IN() and a masking expression such as mask_ssn(), mask_pan(), mask_inner(), or mask_outer() . MySQL evaluates the policy when a query references the masked column and returns either the unmasked value or the masked value.
Sensitive data such as personal identifiers, payment card data, tax identifiers, phone numbers, email addresses, and other regulated or confidential values should not be exposed to users or applications unless there is a documented business need.
Historically, masking in MySQL was often implemented through views or application logic. That approach can be bypassed if users query the base table directly, and it requires ongoing maintenance as schemas change. Dynamic Data Masking reduces this risk by enforcing masking at the column level in the MySQL server, helping support least-privilege access and reducing sensitive-data exposure across applications and query paths.
NOTE: Nessus has provided the target output to assist in reviewing the benchmark to ensure target compliance.
Solution
Create a role for users who are explicitly authorized to view unmasked sensitive data:
CREATE ROLE IF NOT EXISTS 'pii_unmasked_reader'@'%';
Grant the role only to approved users or service accounts:
GRANT 'pii_unmasked_reader'@'%' TO '<user_name>'@'<host_name>';
Create an appropriate masking policy. For example, to mask SSNs for all users except sessions with the approved active role:
CREATE MASKING POLICY mask_ssn_policy(ssn_col)
CASE
WHEN CURRENT_ROLE_IN('pii_unmasked_reader')
THEN ssn_col
ELSE mask_ssn(ssn_col)
END;
Apply the masking policy to the sensitive column:
ALTER TABLE protected.user_profiles
ALTER COLUMN ssn
SET MASKING POLICY mask_ssn_policy;
For other sensitive data types, use an appropriate masking function or expression. MySQL Enterprise Data Masking provides general-purpose masking functions such as mask_inner() and mask_outer(), and specialized masking functions such as mask_ssn(), mask_pan(), mask_iban(), mask_uuid(), and others.
Verify behavior with both an unauthorized and authorized account:
- As a user without the approved role
SELECT ssn FROM protected.user_profiles LIMIT 5;
- As an approved user
SET ROLE 'pii_unmasked_reader'@'%';
SELECT ssn FROM protected.user_profiles LIMIT 5;
The unauthorized user should receive masked values. The authorized user should receive unmasked values only when the approved role is active.
Impact:
Users and applications that do not meet the masking policy condition will receive masked values instead of original sensitive values. Reports, exports, troubleshooting queries, analytics jobs, and downstream integrations may need to be reviewed to ensure they can operate correctly with masked values.
Role-based masking policies that use CURRENT_ROLE_IN() depend on the appropriate role being active in the session. If authorized users are expected to see unmasked data, their role configuration and role activation behavior must be reviewed. Dynamic Data Masking should be used with access control, auditing, encryption, and secure role management; it should not be treated as a complete replacement for those controls.
There may also be operational impact when identifying sensitive columns, designing masking policies, testing application behavior, and reviewing exceptions for users or roles that are allowed to view unmasked data.