Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Redact Sensitive Laravel Package

leocavalcante/redact-sensitive

Safely redact sensitive data like passwords, tokens, and personal details from strings and arrays. A lightweight PHP package offering a simple API to mask values before logging, debugging, or returning API responses, with easy integration into Laravel applications.

Deep Wiki
Context7

Getting Started

Install the package with Composer:

composer require leocavalcante/redact-sensitive

Then look at, in order:

  1. vendor/leocavalcante/redact-sensitive/README.md for the supported constructor/config API.
  2. The processor class under vendor/leocavalcante/redact-sensitive/src/ — this package is small, so read the whole processor once. Confirm whether it accepts a key list, uses defaults, and what replacement token it writes.
  3. composer.json for the Monolog and PHP version constraints, especially if you are on Laravel 11 / Monolog 3.

The core integration is always the same: create or obtain a Monolog logger, push the processor, and log sensitive values as context keys.

use Leocavalcante\RedactSensitive\RedactSensitiveProcessor;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

$logger = new Logger('app');
$logger->pushHandler(new StreamHandler(__DIR__.'/app.log'));
$logger->pushProcessor(new RedactSensitiveProcessor([
    'password',
    'password_confirmation',
    'token',
    'authorization',
]));

$logger->info('login attempt', [
    'email' => '[email protected]',
    'password' => 'hunter2',
]);

Inspect the resulting log line. The password value should no longer be hunter2. If your installed version uses a different constructor name or a config file, follow the README; the important first use case is validating that a known secret disappears from the output.

For Laravel, the quickest wiring is on a channel in config/logging.php:

'single' => [
    'driver' => 'single',
    'path' => storage_path('logs/laravel.log'),
    'level' => env('LOG_LEVEL', 'debug'),
    'processors' => [
        \Leocavalcante\RedactSensitive\RedactSensitiveProcessor::class,
    ],
],

If the processor needs constructor arguments, use a tap class instead of instantiating it directly in config.

Implementation Patterns

Use a central tap for the key list. Keep the sensitive-key list in one place so channels do not drift. A tap is also safe for config:cache, unlike closures or object instances in config files.

namespace App\Logging;

use Leocavalcante\RedactSensitive\RedactSensitiveProcessor;
use Monolog\Logger;

final class RedactSensitiveTap
{
    public function __invoke(Logger $logger): void
    {
        $logger->pushProcessor(new RedactSensitiveProcessor([
            'password',
            'password_confirmation',
            'current_password',
            'token',
            'access_token',
            'refresh_token',
            'api_key',
            'secret',
            'authorization',
            'cookie',
            'credit_card',
            'cvv',
        ]));
    }
}
'single' => [
    'driver' => 'single',
    'path' => storage_path('logs/laravel.log'),
    'tap' => [\App\Logging\RedactSensitiveTap::class],
],

Treat the key list as an application contract. Align it with request validation rules, API payload fields, and job payloads. Add aliases your app actually uses: passwd, pwd, auth, bearer, client_secret, private_key, session, remember_token. Review it when new integrations are added.

Keep context deliberately shaped. The processor protects keys, not arbitrary strings. Do not pass $request->all() into a log call and hope for the best. Pass validated, explicit context:

Log::info('payment failed', [
    'user_id' => $user->id,
    'gateway' => 'stripe',
    'card_last_four' => $lastFour,
    'error_code' => $exception->getCode(),
]);

Use Log::withContext() for correlation data such as request IDs and tenant IDs, not for secrets.

Test the redaction path. Use a Monolog TestHandler so processors actually run:

use Monolog\Handler\TestHandler;
use Monolog\Logger;

$logger = new Logger('test');
$handler = new TestHandler();

$logger->pushHandler($handler);
$logger->pushProcessor(new RedactSensitiveProcessor(['password']));

$logger->info('login', ['password' => 'hunter2']);

$this->assertStringNotContainsString('hunter2', json_encode($handler->getRecords()));

Also test nested arrays, extra data, and objects if your logging pipeline can produce them.

Apply it to every long-lived logger. Monolog processors are attached per logger, not globally. Queue workers, console commands, and custom loggers all need the processor if they can emit sensitive context. In Laravel, centralizing through channel config or a shared tap avoids this.

Configure downstream tools separately. If you ship logs to Sentry, Flare, Bugsnag, Papertrail, or a SIEM, those tools may capture request bodies or exception context independently of Monolog. Redacting Monolog output does not automatically scrub the SDK's own event payloads.

Gotchas and Tips

  • Redaction is key-based, not content-based. A secret stored under meta.value, embedded in a message string, or interpolated through {password} placeholders can still leak. Avoid PSR-3 placeholders for secrets and keep secrets in explicitly named context keys.
  • Exception traces are outside the processor. PHP can include function arguments in stack traces. Set zend.exception_ignore_args=On in production, and avoid putting credentials into exception messages.
  • Case and alias matching matter. Confirm whether matching is exact or case-insensitive. Password, passwd, and pwd may not match password. Add variants explicitly.
  • Nested data and objects may not be traversed. If the processor only walks arrays, convert DTOs to arrays with toArray()/jsonSerialize() before logging, or wrap sensitive values in arrays with recognized keys. Test this rather than assuming recursion.
  • Monolog 2 vs 3 compatibility. Monolog 3 processors receive a LogRecord; Monolog 2 processors receive an array. Check the package's composer.json and run composer show monolog/monolog. Laravel 11 uses Monolog 3, so verify before adopting.
  • Processor order is easy to get wrong. Monolog processors run in reverse push order in common versions (pushProcessor prepends). If another processor injects or interpolates context, verify with a test that redaction runs before the secret reaches the message or formatter.
  • Do not instantiate processors directly in config/logging.php. Use a class name or tap. Object instances in config can break php artisan config:cache or behave unexpectedly after deployment.
  • Stack channels need attention. A Laravel stack fans out to child channels; configure processors on the channels that actually hold handlers, and confirm you are not relying on a processor that never runs for a given child. Double redaction is usually harmless if the replacement is idempotent.
  • Keep the replacement token machine-friendly. If you emit JSON logs, the redaction token should keep the JSON valid and should not collide with values your alerting rules search for.
  • Do not log giant payloads. Redaction recursively walks context; large request bodies are both a security risk and a performance cost. Truncate or omit them before logging.
  • Pin and review. With a small package and a modest star count, pin the version, skim the processor once, and keep a fallback custom ProcessorInterface implementation handy. The core behavior is small enough to reproduce in-house if maintenance stalls.
  • Extension point: if you need regex-based matching, partial masking (jo***@example.com), or a configurable token, subclass the processor or wrap it in your own Monolog processor rather than forking the package. Keep the custom processor tested against nested arrays and both context and extra.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle