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

Phpstan Sensitive Parameter Values Laravel Package

lychee-org/phpstan-sensitive-parameter-values

A PHPStan rule that flags sensitive values like passwords, tokens, and API keys passed directly as literal arguments to functions and methods, helping you catch hardcoded secrets before they reach your codebase.

View on GitHub
Deep Wiki
Context7

Getting Started

Install it as a dev dependency alongside PHPStan:

composer require --dev lychee-org/phpstan-sensitive-parameter-values:^1.2

If phpstan/extension-installer is present, the extension registers automatically through its extra.phpstan.includes entry. Otherwise, add the registration file (typically extension.neon inside the package) to your phpstan.neon:

includes:
    - vendor/lychee-org/phpstan-sensitive-parameter-values/extension.neon

The package targets PHP 8.2+ (#[\SensitiveParameter]) and 8.3+ (SensitiveParameterValue), so confirm your CI matrix and phpstan platform version before wiring it in.

Where to look first: the README for the supported PHPStan range, then the registration file to see exactly which services are declared, then the extension class in src/ — that class is the whole point of the package and reading it takes two minutes. Check the changelog too: 1.2.0 ("Remove false positives", #3) tightens what the extension reports, so if you tried an earlier 1.0.x build and got noisy diagnostics, that is the version worth retrying.

First use case: somewhere in your codebase you already have something like

final class Password
{
    private SensitiveParameterValue $value;

    public function __construct(#[\SensitiveParameter] string $value)
    {
        $this->value = new SensitiveParameterValue($value);
    }

    public function reveal(): string
    {
        return $this->value->getValue();
    }
}

Run PHPStan before and after installing. Before, reveal() returns mixed (or whatever SensitiveParameterValue::getValue() is stubbed as) and every caller needs a cast or an @var. After, reveal(): string is satisfied natively and downstream code type-checks against string instead of mixed. That diff is the fastest way to confirm the extension is loaded and doing something.

Implementation Patterns

Wrap at the trust boundary, unwrap at the sink. The useful shape is: controller/command receives the raw value → immediately wraps it → wrapper travels through service layers → getValue() is called exactly once, at the point where the value is hashed, compared, or sent over the wire. With the extension installed, PHPStan tracks the wrapped type across that whole journey, so intermediate layers don't need docblocks or assertions.

Pair the attribute with the wrapper. #[\SensitiveParameter] redacts the raw argument in stack traces; SensitiveParameterValue redacts it in var_dump/print_r output. Put the attribute on the constructor parameter that accepts the raw string, then store only the wrapper. Doing one without the other leaves one leak channel open and PHPStan won't tell you.

Lean on constructor-call-site inference. The extension infers the wrapped type from the new SensitiveParameterValue(...) expression. That means a factory with a precise signature gives you precise types everywhere:

/** @param non-empty-string $raw */
public static function fromString(#[\SensitiveParameter] string $raw): self
{
    return new self(new SensitiveParameterValue($raw));
}

Add a narrow accessor and treat it as the review surface. A single reveal(): string (or ->getValue() calls) per sensitive type gives you a greppable list of every place a secret becomes plaintext. In code review, rg 'reveal\(|getValue\(\)' is a fast audit. The static analyser can't enforce that discipline, but the type inference makes the accessor cheap to write.

Keep it in the same PHPStan invocation. There's no separate command — the extension just enriches the existing analysis. In CI, run it in your normal phpstan analyse step; no extra pipeline leg needed.

Use it to clean up existing casts. If you already have SensitiveParameterValue in production code, installing this package usually lets you delete @var inline annotations, assert() calls, and mixed workarounds around getValue(). Do that in a dedicated PR so you can see the type-inference improvement in isolation.

Reuse the pattern for your own wrappers. If you have similar newtype/redaction objects (e.g. an API token wrapper), the dynamic return type extension in this package is a good template — mirror its registration for your own classes rather than casting at every call site.

Gotchas and Tips

  • Runtime redaction is PHP's job, not the analyser's. SensitiveParameterValue hides values from var_dump, print_r, and debug_backtrace, but not from error_log, Monolog, or json_encode. The extension gives you types; it does not give you log redaction. Don't let installing it create a false sense of safety.
  • SensitiveParameterValue is not serializable. Queued jobs, session payloads, and cache entries containing the wrapper will fail or produce unexpected output. Unwrap before serialization, or write a normalizer that stores an opaque token.
  • Inference is only as good as the call site. Values arriving from mixed, from a container get(), or built in a file PHPStan can't fully resolve will degrade back to mixed. If reveal() suddenly widens, look at the constructor call that created the wrapper.
  • 1.2.0 removes false positives — expect baseline pruning. If you installed an earlier build, the extension used to emit diagnostics in cases it now stays quiet about. After upgrading, previously-ignored errors may no longer fire, and PHPStan's reportUnmatchedIgnoredErrors (on by default) will flag them. Run phpstan analyse on a clean cache, delete the now-dead baseline entries, and review the remainder rather than blanket-regenerating.
  • Registration order matters. With Larastan, Symfony, or other meta-packages, includes are processed in order. If the extension appears to have no effect, run phpstan analyse --debug and check the extension list, then reorder the includes.
  • Clear the result cache. vendor/bin/phpstan clear-result-cache after installing, upgrading (including 1.0.1 → 1.2.0), or reordering extensions. Stale cache is the single most common reason "it doesn't work."
  • Expect baseline churn. New inference can turn existing mixed-driven errors into different, more specific errors. Regenerate the baseline in the same commit that adds or upgrades the extension so the diff is readable — especially on the 1.x → 1.2.0 hop, where removed false positives shrink the baseline.
  • Pin the extension and PHPStan majors. Extensions that touch the type system are tightly coupled to PHPStan internals. Constrain lychee-org/phpstan-sensitive-organization-values-style deps with ^1.2 and pin phpstan/phpstan in composer.json so a minor bump doesn't silently disable inference in CI.
  • Check the platform version in phpstan.neon. If phpVersion is below 8.3, the SensitiveParameterValue class may not resolve and you'll get "class not found" noise instead of useful analysis.
  • The attribute still needs to be on the parameter. PHPStan will not flag a raw string $password that is later logged; only the attribute plus the wrapper together give you both static tracking and runtime redaction.
  • Verify inference in your own test suite. If you rely on this in a library, add an assertType()-style PHPStan test (or a tiny fixture project) so a dependency bump that breaks inference shows up as a failing test rather than a silent mixed — and so a future false-positive cleanup doesn't quietly drop coverage you were depending on.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings