Limitations & security
Static analysis cannot find every runtime leak, and this tool does not pretend otherwise. Out of scope for v1:
- Dynamic property and variable access —
$obj->{$name},$$var,Foo::${$prop}. - Reflection and anything that writes state through it.
- Runtime-generated code —
eval(), generated classes,create_function. - Third-party packages.
vendor/is not scanned, so state retained inside a dependency is invisible. If a dependency leaks, this tool will not tell you. - C extension memory leaks and leaks inside the runtime itself.
- Complex data flow. A value that reaches a static property through several function calls, an array, or a closure captured elsewhere may be missed.
- Inherited and trait-provided members. A static property declared in a parent class or a trait is analyzed where it is declared, not once per using class, so inherited instance state can be missed by the container rules.
- A user function that shadows a built-in. A namespaced
function putenv()called unqualified cannot be told apart from the global one, so WS003 may report it. Aliased imports (use function putenv as changeEnv) are resolved correctly. - Container bindings whose class is not in the scanned paths are skipped rather than guessed at.
- Bindings and listeners registered dynamically, from a config array or a loop, are not correlated.
- Where a memoized value comes from, and how long it lasts. WS001 can prove
that
self::$x ??= …writes only into an empty slot, but not whether the stored value is a constant or request data, and not how long it survives — an initializer that returns null re-runs every time, and a reset in unscanned code re-opens the slot. See the standard Laravel factory. - No runtime detection. Which runtime an application actually uses is never
determined;
--runtimeselects what the analysis reasons about. See these are targets, not detections. - Suppression is anchored to the reported line. An inline directive or a baseline entry for a static property keeps applying when the code that assigns it changes, because the fingerprint is built from the declaration.
Position this tool accordingly. It is a
worker-safety risk analyzer
not a
proof of safety.
A clean scan means the known cross-request patterns are absent from the analyzed paths. It does not mean the application is safe to run on a worker. Stage the rollout, watch memory, and recycle workers.
Security model
Section titled “Security model”The scanner never executes, includes, autoloads or evaluates the code it
analyzes. Source is turned into an AST and nothing more; scan does not
bootstrap the analyzed application, and YAML is parsed without object support.
See SECURITY.md for the full threat model.