Drupal is a registered trademark of Dries Buytaert
Protected Pages 3.0.0 Major update available for module protected_pages (3.0.0). Commerce Core 3.3.8 Minor update available for module commerce (3.3.8). Search API HTML Element Filter 1.0.7 Minor update available for module search_api_html_element_filter (1.0.7). Layout Builder Reorder 2.0.1 Minor update available for module layout_builder_reorder (2.0.1). Ban 1.1.0 Minor update available for module ban (1.1.0). Field Formatter Range 2.0.0 Major update available for module field_formatter_range (2.0.0). Field Formatter Range 8.x-1.8 Minor update available for module field_formatter_range (8.x-1.8). Varbase Media Header 9.2.1 Minor update available for module varbase_media_header (9.2.1). Search API Solr 4.3.11 Module search_api_solr updated after 14 months of inactivity (4.3.11). Provus Mega Menu Module provus_mega_menu crossed 1,000 active installs.

Masked Output

4 sites Security covered
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

Activity

Total releases
5
First release
Feb 2025
Latest release
1 month ago
Releases (12 mo)
2 ▼ from 3
Maintenance
Active

Release Timeline

Releases

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