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

Blade Sandbox Laravel Package

sytxlabs/blade-sandbox

Blade Sandbox provides a safe, isolated environment for rendering untrusted Blade templates in Laravel. It helps preview user-supplied views while limiting access to app data and risky directives, ideal for CMS previews, template builders, and multi-tenant apps.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. sytxlabs/blade-sandbox is an additive render path, not a replacement for Blade. It ships its own compiler, AST validator, runtime mediator, and policy engine, so existing resources/views and the framework's view finder are untouched. That is an unusually low blast radius for a security-critical dependency and makes it viable for a single bounded surface first (e.g. customer-editable notification templates) rather than a platform-wide mandate.

The package addresses a problem most Laravel teams solve badly today: any user-supplied Blade string routed through Blade::render() or eval is remote code execution. A default-deny, explicit-allow model with deny-wins semantics is the correct shape for a multi-tenant or user-authored template feature. Two design choices carry the security claim and should be verified in a spike, not taken on faith:

  1. Structural validation on the PHP AST at compile time + runtime mediation of every operation (method/property access, iteration, string conversion, ArrayAccess). This is the right architecture — allowlisting at the AST is far stronger than regex filtering or strip_tags.
  2. The Livewire server-side request guard. Compile-time wire:* checks are cosmetic against a browser that can POST arbitrary public methods. The release correctly identifies the request guard as "the real boundary." If we adopt Livewire exposure, this component deserves independent review.

Integration feasibility. High. Composer-only install, no framework hard dependency (illuminate/support|view|contracts|filesystem only), and a config publish step. The learn() / blade-sandbox:policy authoring tools are a genuine migration accelerator: we can derive an initial policy from templates that already work, then tighten, rather than hand-authoring a policy from scratch. validate() and non-throwing preview() give us a build-mode UX and a CI gate — the single most important operational control for a sandbox, since it moves policy violations from runtime incidents to pull-request failures.

Technical risk.

Risk Severity Notes
Vendor maturity High 1.0.0 is the first stable release. Strong test posture (900+ tests, 97% lines, 3k–5k fuzzed templates per seed per push) is a good signal but not a substitute for time-in-production. No LTS history, no published CVE response track record.
Cooperative limits Medium Iteration, timeout, memory, output-size, and depth limits are explicitly cooperative. The hard boundary is the separate render process. Teams that enable "isolated rendering = off" for latency silently lose the real containment.
Blast radius of DTO exposure Medium Exposing DTOs via "own public API exposure" plus value-object defaults (Carbon, enums, Collections) is where data leakage usually appears — now(), tenant-scoped query objects, enum cases. Needs a deliberate data contract per surface.
Integrity manifest key management Medium SHA-256 + HMAC-signed manifests are only as good as key custody and rotation. This becomes our operational secret, not the vendor's.
Dependency conflict Low–Medium nikic/php-parser ^5 collides with tooling pinned to ^4; illuminate/* 10–13 may fight our lockfile. Resolve in the spike.
Security scope drift Medium SECURITY.md defines out-of-scope items we have not read. Threat model must be reconciled with ours before adoption, not after.

Key questions.

  • Who are the "untrusted authors" in our product, and is per-tenant and per-user policy resolution sufficient, or do we need per-surface isolation too?
  • What does SECURITY.md list as out of scope, and does anything there fall inside our compliance perimeter?
  • Is a separate OS process enough isolation, or does our threat model require container/cgroup-per-render for hostile tenants?
  • What is our p95 render budget, and does process-per-render fit it without an output cache hit rate we cannot achieve?
  • If the vendor disappears, who owns the fork? (MIT permits it; nobody is assigned to it.)
  • Are our Livewire components already guarded, or does adoption require a Livewire inventory we have not done?

Integration Approach

Stack fit. Compatible with Laravel 10–13, PHP 8.2–8.5, with or without Livewire. We should target Laravel 12 or 13 — the release itself flags 10 and 11 as end-of-life, and shipping a security boundary on an EOL framework undermines the whole exercise. Required extensions (ctype, dom, libxml, tokenizer) are present in any standard PHP build and should be asserted in CI and in the container image healthcheck, not assumed.

Compatibility sequencing. Two hard gates:

  • PHP floor 8.2. Any service still on 8.1 is out of scope until upgraded.
  • Livewire floors for Laravel 13 — Livewire ≥3.7.11 (v3) or ≥4.2.0 (v4). If we are on an earlier Livewire 3 patch, the Livewire upgrade is a prerequisite, not a parallel track. Confirm our exact Livewire minor before committing to a 13.x target.

Migration path. Depends on what we have today:

  • Existing user-editable templates in another engine (Twig/Mustache/Handlebars): run learn() against a representative sample, diff the generated policy against intent, then hand-tighten. Budget for the tightening, not the learning.
  • Existing raw Blade::render() on user input: this is an active vulnerability. Treat as a hotfix candidate — swap to the sandbox on the affected surface before the broader rollout.
  • Greenfield template feature: start in the sandbox. Retrofitting is the expensive path; do not build the "fast" version first.

Sequencing (suggested).

  1. Spike (1–2 weeks): lockfile resolution, extension assertions, render a hostile template corpus, measure p50/p95 latency with and without process isolation, read SECURITY.md against our threat model.
  2. Policy design: pick one non-critical surface, define the allowlist as reviewed code in config/blade-sandbox.php, wire validate() / blade-sandbox:check into CI as a required check.
  3. Containment: enable isolated rendering and queued rendering with explicit worker pools; instrument fallback events before enabling fallback rendering.
  4. Livewire (if applicable): inventory guarded components, enable the request guard, add a regression test per guarded component.
  5. Tenant rollout: canary one tenant, then percentage roll-out keyed on fallback/denial rates.
  6. Author enablement: preview() in the authoring UI, blade-sandbox:policy in the template editor's save path.

Operational Impact

Maintenance. MIT license means no procurement friction and a fork option, but also no support contract, no SLA, and no guaranteed security disclosure timeline. Operationally we must assign an internal owner (name, not a team alias) for: policy files, HMAC key rotation, Livewire guard coverage, and vendor release monitoring. Policy is code — it belongs in review, version control, and the same change-management gate as migrations. The compiled-template cache is keyed by compiler version, Livewire major, and policy fingerprint; every policy change is a cache-invalidation event. Plan deploys accordingly.

Support. Assume community-only. That means: subscribe to the repo's releases and security advisories, pin exact versions (1.0.0, not ^1.0), and rehearse the fork. A single-maintainer security dependency in the render path is a real concentration risk; the mitigation is our ability to patch it ourselves, which requires at least one engineer who has read the compiler.

Scaling. The cost model shifts from HTTP-bound to queue-bound. Queued + isolated rendering means throughput is a function of worker concurrency and process-spawn overhead, not web workers. Autoscaling must key on queue depth, not request rate. Three levers to plan: the output cache (repeat renders are near-free), the compiled-template cache (warm it on deploy, don't let the first tenant request pay for compilation), and per-render memory ceilings (process isolation multiplies peak RSS by concurrency). Budget a load test with realistic template complexity before committing to a capacity number.

Failure modes and required instrumentation.

Failure Observable Mitigation
Fallback rendering on error Fallback rate Alert on it. Fallback is silent degradation by design and will hide policy regressions indefinitely.
Runtime denial of an allowed operation Denial events Structured logs → dashboard; spike = policy gap, steady trickle = fine.
Cooperative limit breach / runaway render Timeout, memory, output-size events Hard containment via isolated process; per-tenant rate limit.
Policy fingerprint change → mass recompile Latency spike at deploy Warm caches pre-traffic; deploy policies outside peak.
HMAC manifest mismatch Template rejection Key rotation runbook; mismatch is either tampering or an ops error — distinguish them.
Livewire guard regression after Livewire upgrade Guarded-component request succeeding Pin Livewire, add a per-component regression test, run the Livewire upgrade in isolation.

Ramp-up. Two audiences, two curves. Engineers need roughly 1–2 sprints to internal comfort: AST-level mental model, policy inheritance and override semantics (configure() / definePolicy() / extendPolicy()), and the Livewire guard. Add an independent security review before the first hostile-tenant exposure — the vendor's fuzzing is evidence, not a substitute for our own review of the boundary. Template authors need a shorter curve: preview() plus validate() plus clear denial messages in the editor UI, and author lockout must be tuned carefully — it is a usability control that, mis-set, reads as "the editor is broken."

Net recommendation. Adopt, scoped, on Laravel 12/13, with a named internal owner, pinned versions, CI-gated validation, isolated rendering on, fallback alerting, and a written fork contingency. Do not adopt as a blanket replacement for the view layer; adopt it where untrusted input currently reaches a template engine.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console