Skip to main content
Drupal is a registered trademark of Dries Buytaert
Release: OpenID Connect / OAuth client 3.0.0-alpha9 New alpha version released for module openid_connect (3.0.0-alpha9). Release: Timelinr 1.0.1 Minor update available for module timelinr (1.0.1). Usage Milestone: Simplify Module simplify crossed 10,000 active installs. Usage Milestone: Views Reference Filter Module entityreference_filter crossed 10,000 active installs. Usage Milestone: Dropdown Language Module dropdown_language crossed 10,000 active installs. Usage Milestone: Paragraphs Browser Module paragraphs_browser crossed 10,000 active installs. Usage Milestone: OpenAPI Module openapi crossed 10,000 active installs. Usage Milestone: Decoupled Router Module decoupled_router crossed 10,000 active installs. Usage Milestone: Time Field for Drupal 8+ Module time_field crossed 10,000 active installs. Module Revived: Entityqueue Buttons 1.1.2 Module entityqueue_buttons updated after 8 months of inactivity (1.1.2).

Masked Output

4 sites Security covered Drupal 10–11
View on drupal.org

This module masks sensitive field data, such as payment card numbers or phone numbers, across your Drupal site. It offers various masking formats, role-based bypass for specific users, on-demand reveals with audit trails, and integrates with JSON:API and Views.

Masked Output

Masked Output provides configurable field formatters, a JSON:API normalizer,
and a Views field handler that mask sensitive field values across every Drupal
output surface — entity displays, REST/JSON:API responses, and Views pages —
with role-based bypass, permissioned on-demand reveal, and a full audit trail.

Ideal for displaying:

  • Payment card numbers & account IDs
  • Phone numbers and SSNs
  • Email addresses in public listings
  • API keys, tokens, and reference codes
  • Any sensitive string or telephone field

Formatters

Mask Output (string fields)

  • Show last / first N characters, mask the rest
  • Mask first / last N characters, show the rest
  • Custom mask symbol (default *)
  • Multibyte-safe

Mask Email Output (email fields)

  • Masks the local-part of an email address, preserves the domain
  • Example: [email protected]********@example.com

Mask Pattern Output (string & telephone fields)

  • Positional pattern: # = show original character,
    * = mask, any other character = literal separator
  • (***) ***-####(***) ***-5309
  • ####-****-****-####4111-****-****-1234
  • ***-**-####***-**-6789

Role-Based Bypass

Each formatter exposes a Roles that see unmasked values setting.
Users with any selected role see the original value. Bypass is enforced
identically on entity pages, Views, and JSON:API responses. The
user.roles render cache context is applied automatically to
prevent cross-user cache poisoning.

Reveal On Demand

Enable the Reveal on demand formatter option to show a
Reveal button next to each masked value. Users with the
Reveal masked output values permission can click it to see the
original value in-place. An optional Auto re-mask timeout
automatically hides the value after N seconds. Every reveal is written to
the audit log.

JSON:API Integration

When a field's default view display uses any masked formatter, the same
masking is applied automatically to JSON:API responses — no extra
configuration needed. Role bypass is honoured for authenticated consumers.
The normalizer is registered only when the jsonapi module is
enabled.

Views Integration

Every string, email, and telephone
configurable field gains a (Masked) variant in the Views
field picker. Masking strategy, character count, pattern, mask symbol, and
bypass roles are all configurable per Views field instance, independently
of the entity display formatter.

Audit Logging & Events

  • All masking operations and every reveal action are logged to the
    masked_output watchdog channel (visible at
    Reports > Recent log messages).
  • Dispatches masked_output.post_mask
    (MaskedOutputEvent) after each masking operation — event
    subscribers can override the masked value.
  • hook_masked_output_alter(&$masked, $original, $context)
    for procedural extensibility.

Developer API

  • Plugin-based strategy system — register custom mask
    strategies by annotating a class with #[MaskStrategy(...)]
    in Plugin/MaskStrategy/.
  • MaskingServiceInterface — inject and call
    maskString(), maskEmail(),
    maskPattern() programmatically.
  • See masked_output.api.php for the full hook and event reference.

Technical Highlights

  • Service-based architecture with full dependency injection
  • 69 tests / 246 assertions (Unit + Kernel)
  • PHPStan level 6 — 0 errors
  • PHPCS Drupal + DrupalPractice — 0 errors
  • Drupal 10 and 11 tested; Drupal 13 forward-compatible

Installation

composer require drupal/masked_output:^2.1

Depends on

Dependencies of the latest stable release

  • user Drupal core

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
5
Tracked since
Feb 2025
Latest release
3 months ago
Releases (12 mo)
2 ▼ from 3
Maintenance
Active

Release Timeline

Releases

Version Type Core Release date
2.1.0 Stable 10–11 May 29, 2026
2.0.3 Stable 10–11 Feb 14, 2026
2.0.2 Stable 10–11 Feb 22, 2025
2.0.1 Stable 10–11 Feb 22, 2025
2.0.0 Stable 10–11 Feb 20, 2025