Security
Content-Security-Policy
Section titled “Content-Security-Policy”Ghostwire runs under a strict CSP — no inline <script>, no eval, no new Function. The compiled resources/dist/ghostwire.js bundle never uses either. The @ghostwireStyles/@ghostwireScripts Blade directives both accept an optional nonce argument for apps that thread a per-request CSP nonce through their asset pipeline.
Verified in CI: the package’s own test gallery runs under the strictest CSP each Livewire line actually supports — no 'unsafe-eval' at all on Livewire 4 with csp_safe enabled, and 'unsafe-eval' granted only on Livewire 3, whose Alpine can’t evaluate wire:* expressions without it — not just a documented claim.
Livewire 4 offers a CSP-safe Alpine build, but it’s opt-in: set 'csp_safe' => true in your config/livewire.php (it defaults to false). With it enabled, your policy needs no 'unsafe-eval'. Left at the default, a Livewire 4 app’s policy still needs 'unsafe-eval' — same as Livewire 3, where that same flag has no effect and the violation is still recorded regardless. Either way, this is a Livewire/Alpine requirement, not Ghostwire’s: Ghostwire’s own bundle needs no eval on either line.
Supply chain
Section titled “Supply chain”- Dependency auditing —
composer auditruns in CI on every PR (.github/workflows/security.yml) - Reproducible
dist/build — the committedresources/dist/ghostwire.js/.cssare verified in CI to match a freshjs/build.mjs(esbuild) run from source, so what ships is provably what’s in the repo, not something hand-edited post-build
Data-surface hardening
Section titled “Data-surface hardening”- Server→client transport — the
data-ghostpayload (compact keysm/o/x/d/h/r/p/s/l/g/n) is schema-validated on the client: an unknown key discards the whole payload rather than partially trusting it, and a malformed value falls back to the package default for that field, never to an unvalidated pass-through - Learning store — validated on every read, capped at a fixed 256 KB with least-recently-used eviction, and holds structural bone-tree shape only — never textual DOM content
ghost:export— path-traversal-hardened: component names are charset-validated, the destination is resolved canonically and refused outsideresources/views, and a symlinked or directory target is refused regardless of--force. See Learning for the full flow.
Privacy
Section titled “Privacy”No data from the user’s DOM ever leaves the browser. Learning, when enabled (GHOSTWIRE_LEARNING env var, off by default) and refused server-side in production regardless of that setting, is entirely local — nothing is ever transmitted. Zero telemetry, full stop.
Reporting a vulnerability
Section titled “Reporting a vulnerability”See SECURITY.md in the repository. Response target: under 72 hours (GOV-04).