JSON & SARIF
--format=json writes a stable schema to stdout and nothing else — no colour, no
progress, no banner:
{ "version": "1", "tool": { "name": "Worker Safety", "package": "goktugcy/worker-safety", "version": "1.1.0" }, "project": { "root": "/app", "paths": ["app"], "framework": { "name": "laravel", "version": "12" }, "runtimes": ["frankenphp", "octane"], "analysis_targets": ["frankenphp", "octane"], "runtime_detected": false, "php": "8.4.2", "config": "worker-safety.yaml", "baseline": null }, "summary": { "files": 284, "duration_seconds": 1.42, "total": 5, "critical": 0, "high": 2, "medium": 3, "low": 0, "info": 0, "suppressed": 0, "baseline_filtered": 0, "parse_errors": 0, "fail_on": "high", "failed": true, "failed_on_severity": true, "failed_on_incomplete_analysis": false, "by_rule": { "WS001": 1, "WS005": 1, "WS006": 1, "WS008": 1, "WS009": 1 } }, "findings": [ { "rule": "WS005", "title": "Laravel container singleton with mutable state", "severity": "high", "category": "container-binding", "file": "app/Providers/AppServiceProvider.php", "line": 18, "column": 9, "end_line": 18, "message": "Laravel singleton UserContext contains potentially request-specific mutable state ($user).", "details": "…", "remediation": ["…"], "snippet": "$this->app->singleton(UserContext::class);", "symbol": { "class": "App\\Support\\UserContext", "method": "register", "property": "user" }, "runtimes": ["frankenphp", "octane"], "framework": "Laravel", "fingerprint": "a907350778c516d031547604abb544df" } ], "parse_errors": []}version is the schema version and only changes on a breaking change to the
shape, independently of the tool version.
Reading the report fields
Section titled “Reading the report fields”project.analysis_targetsis what--runtimeselected.project.runtimescarries the same values under the original name and is kept for compatibility; new consumers should readanalysis_targets.project.runtime_detectedis alwaysfalse. No runtime detection exists — the field is there so a consumer never has to infer it from the presence of the list.summary.failedis the exit-code decision. The two reasons behind it are reported separately:failed_on_severitymeans findings crossedfail_on, andfailed_on_incomplete_analysismeans files could not be parsed. They are independent and either can be true on its own.
Fields are only ever added within a schema version, never renamed or removed,
so reading by key is safe.
Use --format=sarif to produce SARIF 2.1.0 for code scanning. See CI & GitHub code scanning. Both the CLI and Artisan use the same reporters.
vendor/bin/worker-safety scan --format=sarif > worker-safety.sarif