The Laravel factory
Every new Laravel application ships this, and WS001 reports it as HIGH:
protected static ?string $password;
// …'password' => static::$password ??= Hash::make('password'),This is a real report, not a bug — and in this specific case it is almost certainly not a problem in your code. The honest reason it is not silenced automatically is that the analyzer cannot tell this apart from the shapes that are bugs. All three of these are the same syntax to a parser:
static::$password ??= Hash::make('password'); // fixed literal — harmlessstatic::$user ??= auth()->user(); // request #1's user, foreverstatic::$tenant ??= request('tenant'); // request #1's tenant, foreverThe last two are genuine cross-request leaks: because ??= writes only into an
empty slot, whichever request stores a value there hands it to the requests that
follow, until something resets or replaces it. Any rule broad enough to silence
the first line — “the class name ends in Factory”,
“the file is under database/factories”, “the assignment uses ??=” — silences
those two as well. Deciding properly would mean knowing what Hash::make,
auth() and request() return, which is a question about the framework’s
behaviour, not about the syntax.
So the tool reports what it can prove — the assignment writes only into an empty slot, so a stored value gets reused — states which question decides whether that matters (where the value comes from), and leaves the answer to you. It does not claim how long the value lasts: that depends on whether the initializer ever returns null and on resets it cannot see. For the stock factory the answer is that the input is a fixed string, so record that decision next to the code:
// worker-safety-ignore WS001 memoized hash of a constant test passwordprotected static ?string $password;Or, if you would rather not touch the file, accept it once with a baseline.
Know what you are buying in either case. Both the directive and the baseline entry are anchored to the property declaration, not to the initializer, so they keep applying if the initializer is later changed:
// worker-safety-ignore WS001 memoized hash of a constant test passwordprotected static ?string $password; // declaration: unchanged
'password' => static::$password ??= request('tenant'), // now a real leak, still silentThat is the normal trade-off of any suppression — it is a decision recorded about a line — but it is worth knowing here, because the thing that decides the risk lives somewhere else in the file. If that matters to you, suppress WS001 per file rather than project-wide, and re-read the initializer when the factory changes.
database is one of the default scan paths for Laravel,
so this finding appears on a stock application the first time you run a scan.
Handling it once, either way, is part of adopting the tool.