NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Testing for Laravel

Secret-safe about capture

Captures one artisan about section and pins that it renders what it must while leaking none of the secrets it must not:

expect($section)->toLeakNoSecrets(array $secrets, array $mustRender);
expect('passkeys')->toLeakNoSecrets(
    secrets: ['auth.acme-internal.example', '/srv/acme/secrets', 'ea9b8d66'],
    mustRender: ['Sign-count policy', 'AAGUID allow-list'],
);
ParameterTypeMeaning
$sectionstringThe section passed to artisan about --only=<section>.
$secretslist<string>Values that must not render — keys, paths, hosts, fingerprints. Every entry must be a non-blank string; an empty list is a deliberate render-only check.
$mustRenderlist<string>Strings that must render — positive proof the capture worked. Required, non-empty, and every entry a non-blank string.

Order of operations

  • First, the output must be non-empty.
  • Then every $mustRender string must be present.
  • Only then is each $secrets entry asserted absent.

Capture goes through Artisan::call('about', ['--only' => $section]) and Artisan::output(). It never reads app(Kernel::class)->output(), which returns an empty string — that is how a whole section’s “does not leak” checks once passed vacuously, and the leak was caught only because one positive assertion happened to exist. An empty $mustRender throws InvalidArgumentException at call time, because a negative-only check can pass against empty output.

Every entry must be set

Every entry of both lists must be a non-blank string, or the call throws InvalidArgumentException. A null secret — config('a.key.that.is.not.set') — or an empty one from an unset env var can never be found, so the leak check would pass while checking nothing; an empty $mustRender needle is found in every output. Set the secret to a real value in the test first.

In an application

it('does not leak credentials through artisan about', function (): void {
    // Only a secret that is set can be looked for — a null or empty entry throws.
    config(['services.stripe.secret' => 'sk_test_do_not_render_me']);

    expect('environment')->toLeakNoSecrets(
        secrets: [config('app.key'), config('services.stripe.secret')],
        mustRender: ['Application Name'],
    );
});

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.