Mask sensitive data in strings, arrays, and objects for safe logging

Maintainers

Package info

github.com/philiprehberger/php-mask

pkg:composer/philiprehberger/php-mask

Fund package maintenance!

philiprehberger

Statistics

Installs: 38

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.2.0 2026-04-01 13:40 UTC

This package is auto-updated.

Last update: 2026-04-22 16:00:42 UTC


README

Tests Latest Version on Packagist Last updated

Mask sensitive data in strings, arrays, and objects for safe logging.

Requirements

  • PHP 8.2+

Installation

composer require philiprehberger/php-mask

Usage

Email masking

use PhilipRehberger\Mask\Mask;

Mask::email('john@example.com');
// "j***@e******.com"

Phone masking

Mask::phone('+1-555-123-4567');
// "+1-555-***-4567"

Credit card masking

Mask::creditCard('4111 1234 5678 1111');
// "4111 **** **** 1111"

IP address masking

Mask::ip('192.168.1.100');
// "192.168.*.*"

IBAN masking

Mask::iban('DE89370400440532013000');
// "DE****************3000"

Mask::iban('GB29NWBK60161331926789', '#');
// "GB################6789"

Custom masking

Mask::custom('SensitiveData', visibleStart: 3, visibleEnd: 3);
// "Sen*******ata"

Mask::custom('SensitiveData', visibleStart: 0, visibleEnd: 0);
// "*************"

URL masking

Mask::url('https://user:pass@example.com/path?token=abc123&key=secret');
// "https://u***:p***@example.com/path?token=a*****&key=s*****"

Mask::url('https://example.com/search?q=test');
// "https://example.com/search?q=t***"

JWT masking

Mask::jwt('eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpM');
// "eyJhbGciOiJIUzI1NiJ9.[MASKED].[MASKED]"

Generic string masking

Mask::string('SensitiveData');
// "Se*********ta"

Mask::string('SensitiveData', visibleStart: 3, visibleEnd: 3);
// "Sen*******ata"

Recursive array masking with dot notation

$data = [
    'user' => [
        'name' => 'John',
        'address' => [
            'street' => '123 Main St',
        ],
    ],
    'password' => 'secret123',
];

Mask::arrayRecursive($data, ['password', 'user.address.street']);
// ['user' => ['name' => 'John', 'address' => ['street' => '12*******St']], 'password' => 'se*****23']

Array masking (deep)

$data = [
    'name' => 'John',
    'email' => 'john@example.com',
    'nested' => [
        'ssn' => '123-45-6789',
    ],
];

Mask::array($data, ['email', 'ssn']);
// ['name' => 'John', 'email' => 'jo************om', 'nested' => ['ssn' => '12*******89']]

JSON masking

$json = '{"name":"John","ssn":"123-45-6789"}';

Mask::json($json, ['ssn']);
// '{"name":"John","ssn":"12*******89"}'

Redaction policies

use PhilipRehberger\Mask\RedactionPolicy;

$policy = RedactionPolicy::create()
    ->maskField('user.email', 'email')
    ->maskField('*.secret', 'full')
    ->maskPattern('/password|token/i', 'full');

$data = [
    'user' => ['name' => 'John', 'email' => 'john@example.com'],
    'service' => ['secret' => 'sk-12345'],
    'password' => 'hunter2',
];

$result = $policy->apply($data);
// ['user' => ['name' => 'John', 'email' => 'j***@e******.com'],
//  'service' => ['secret' => '********'],
//  'password' => '*******']

Custom configuration

use PhilipRehberger\Mask\MaskConfig;

Mask::configure(new MaskConfig(
    maskChar: '#',
    preserveLength: false,
    visibleStart: 3,
    visibleEnd: 3,
));

Mask::string('SensitiveData');
// "Sen###ata"

API

Method Description
Mask::email(string $email): string Mask an email address, preserving first char of local/domain and TLD
Mask::phone(string $phone): string Mask a phone number, preserving country code and last 4 digits
Mask::creditCard(string $number): string Mask a credit card, showing first 4 and last 4 digits
Mask::ip(string $ip): string Mask an IP address, showing first two octets (v4) or groups (v6)
Mask::iban(string $value, string $char = '*'): string Mask an IBAN, showing country code and last 4 characters
Mask::custom(string $value, int $visibleStart, int $visibleEnd, string $char = '*'): string Mask a string with configurable visible start/end lengths
Mask::url(string $url): string Mask URL query parameter values and embedded credentials
Mask::jwt(string $token): string Mask JWT payload and signature, preserving header
Mask::string(string $value, int $visibleStart = 2, int $visibleEnd = 2): string Mask a generic string with configurable visible characters
Mask::arrayRecursive(array $data, array $keys, string $char = '*'): array Recursively mask values at specified keys, supporting dot notation paths
Mask::array(array $data, array $keys): array Deep-mask specified keys in an associative array
Mask::json(string $json, array $keys): string Parse JSON, mask specified keys, re-encode
Mask::configure(MaskConfig $config): void Set global masking configuration
Mask::resetConfig(): void Reset configuration to defaults
RedactionPolicy::create(): self Create a new redaction policy
RedactionPolicy::maskField(string $path, string $method): self Register a masking rule for a field path (dot notation, wildcards)
RedactionPolicy::maskPattern(string $regex, string $method): self Register a pattern-based rule matched against field names
RedactionPolicy::apply(array $data): array Apply all rules to an array, returning masked copy
RedactionPolicy::merge(self $other): self Merge another policy into this one

Development

composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyse

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT