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

Xss Sanitizer Laravel Package

phlib/xss-sanitizer

PHP library for sanitizing untrusted HTML and preventing XSS. It parses user-supplied markup, strips dangerous tags, attributes and URLs, and returns safe HTML for rendering in web applications. Configurable rules suit comments, rich text and other user-generated content.

Deep Wiki
Context7

Technical Evaluation

Architecture fit. phlib/xss-sanitizer is a standalone PHP library, not a framework package. It ships no Laravel service provider, facade, config file, or Blade directive, so it occupies no opinionated slot in a Laravel architecture. Its natural home is a thin anti-corruption layer at the trust boundary: a HtmlSanitizerInterface bound in a service provider and injected wherever untrusted HTML is ingested or rendered. That is a reasonable architectural position, but the package does not earn it — the same seam can be filled by any sanitizer, which means the package is a replaceable implementation detail rather than a structural dependency. Functionally it appears to be a convenience wrapper plus configuration-caching layer over HTML Purifier; the security-critical logic lives in the upstream library, and the package's distinct value is ergonomics and performance, not detection capability.

Integration feasibility. Mechanically trivial: composer require, one wrapper class, one binding, done. The friction is entirely non-technical — licensing and provenance. Two gates must clear before any code is written:

  • License. LGPL-3.0 is copyleft-adjacent. PHP has no meaningful dynamic-linking boundary since dependencies ship as source in vendor/, so the "linking exception" argument is weaker than it is for compiled languages. Most organizations tolerate LGPL in server-side dependencies, but this requires an explicit legal ruling, not an engineering judgment call. Treat this as a hard gate, not a checklist item.
  • Provenance. The repository is listed as unknown. For a security-sensitive dependency that will be trusted to neutralize XSS, unverifiable source is disqualifying on its own until resolved. A 0.27 score and 16 stars compound this: no meaningful downstream audit surface, no crowd-sourced bug discovery, no obvious fork ecosystem.

Technical risk. Ranked by severity:

  1. Abandonment / single-maintainer risk. Low-velocity project with negligible adoption. If the maintainer steps away, there is no community to fork or patch. A sanitizer with no security patch path is a liability that grows over time.
  2. Misplaced trust. Because it wraps HTML Purifier, teams may assume the wrapper's defaults are safe and skip reviewing the allowlist configuration. The most common real-world XSS incident is not a broken sanitizer —it is a permissive configuration.
  3. Supply chain. Unknown repository combined with a name that resembles the well-known HTML Purifier family is a typosquat-adjacent pattern worth ruling out explicitly. Verify the Composer vendor, the packagist entry, and the publish history against the upstream project.
  4. Performance misjudgment. HTML Purifier is CPU-intensive; the wrapper's caching is the primary reason to prefer it over raw upstream. If caching is misconfigured or cache keys are per-request, latency regressions will surface under load rather than in tests.

Key questions for the maintainer/vendor evaluation.

  • Who maintains this, and is there a documented security disclosure process with a response SLA?
  • What is the supported PHP version matrix, and does it cover the PHP version pinned by our Laravel release?
  • Precisely what does this add over ezyang/htmlpurifier — caching only, or behavioral differences in filtering?
  • Is the serialized configuration cache safe to share across processes and nodes, and how is invalidation handled?
  • Has legal signed off on LGPL-3.0 in a distributed or SaaS context?
  • Why this over mews/purifier (Laravel-native, widely adopted) or symfony/html-sanitizer (institutional backing, no wrapper layer)?

The honest answer to the last question is likely "no strong reason," which should frame the whole evaluation.

Integration Approach

Stack fit. Poor-to-adequate. Laravel's default posture — escape on output via {{ }} and e() — already covers the majority of XSS exposure and costs nothing. A sanitizer is only warranted where rich HTML must be preserved: WYSIWYG content, imported email bodies, CMS fragments, markdown-rendered user prose. Scope the integration to those surfaces only; do not adopt a sanitizer as a blanket policy replacement for output escaping, because sanitizing everything destroys fidelity and creates a false sense of coverage.

Comparison set before committing.

Option Laravel fit Adoption License Verdict
phlib/xss-sanitizer None (DIY) Very low LGPL-3.0 Only if caching is the deciding factor
mews/purifier Native (provider, config, facade) High MIT Default candidate
symfony/html-sanitizer None, but stable API High MIT Strong if Wrapping is acceptable
HTML Purifier direct None Very high LGPL-2.1+ Baseline; same license concern

Note that three of four options carry permissive licenses — the LGPL question is largely avoidable without conceding capability.

Migration path. Because the package is a wrapper, migration risk is asymmetric and low. Integrate behind an interface from day one:

  • Define HtmlSanitizerInterface::sanitize(string $html, string $profile): string.
  • Bind PhlibSanitizerAdapter in a service provider; resolve via constructor injection only, never app() calls in views or models.
  • Keep allowlists and profiles in version-controlled config, not in code or database rows.
  • If the dependency is later abandoned or fails legal review, swap the adapter binding for HTML Purifier or Symfony's sanitizer. Call sites do not change.

This makes the adoption decision reversible, which is the correct risk posture for a low-signal package.

Compatibility. Verify explicitly during the spike: the package's composer.json PHP constraint against the Laravel version in use (Laravel 10 → PHP 8.1+, Laravel 11 → PHP 8.2+), required extensions (ext-dom, ext-libxml, likely ext-mbstring), and behavior on the newest PHP minor, since low-adoption packages often lag on deprecation fixes. Also confirm the HTML Purifier version it pins — an outdated pin can mean unpatched advisories inherited transitively.

Sequencing.

  1. Legal + security gate. LGPL ruling and repository provenance verification. No engineering time spent until both clear.
  2. Spike (1–2 days). Benchmark against mews/purifier on representative payloads — large documents, pathological nesting, malformed markup. Measure cold-start cost versus cached cost; that ratio determines whether the wrapper justifies itself.
  3. Pilot one surface. The lowest-risk rich-text input, in shadow mode if feasible: sanitize and log the diff against current behavior before enforcing.
  4. Interface + binding. Land the adapter and config; wire the pilot surface.
  5. Observe. Track content-fidelity complaints, sanitizer latency p50/p99, and any stripped-markup anomalies for a release cycle.
  6. Decide. Keep, or swap the binding to an alternative with no call-site changes.

Step 2 is the decision point. If the caching benefit is not measurable against mews/purifier, the package offers nothing that justifies its licensing and maintenance overhead, and the evaluation should terminate there.

Operational Impact

Maintenance. This is the dominant cost and it is structural, not incidental. You inherit a two-layer dependency: the wrapper's release cadence and HTML Purifier's. The wrapper adds no independent security research, so you are effectively betting on a single low-velocity maintainer to relay upstream patches promptly. Budget for the possibility that your team becomes the de facto maintainer — either by forking or by pinning and patching locally. That is a real ongoing headcount fraction, not a theoretical risk.

Support. With 16 stars, community support is effectively absent. There will be no Stack Overflow answers, no blog posts, no third-party tutorials. Every question escalates to the internal team, and every internal answer must be derived by reading source. Factor this into onboarding estimates for anyone who touches the sanitization path.

Scaling. The library is stateless and horizontally scalable; there is no shared state or session coupling. The constraint is CPU and memory. Two operating rules:

  • Sanitize at write, not read. Sanitizing on every render multiplies cost by page views. Sanitize on ingest, store the cleaned artifact, and retain the original in a quarantine column for recovery. This also bounds the blast radius of a configuration bug to new content rather than retroactively corrupting rendering.
  • Cache the purifier definition, not the output. HTML Purifier's cost is dominated by building the filter graph from config. The wrapper's serialized-config caching addresses exactly this. Make sure the cache is warm on every node or lives in a shared store — a per-request cache rebuild silently reintroduces full cost under horizontal scaling.

Enforce hard input-size limits at the boundary. Sanitizers are a classic vector for memory exhaustion and catastrophic backtracking on adversarially large documents.

Failure modes.

  • Over-sanitization. Silent stripping of legitimate markup — tables, embedded media, inline styles — produces content-fidelity defects that surface as user complaints weeks later, not as test failures. This is the most likely failure in practice, and the most expensive to diagnose because the damage is already persisted.
  • Under-sanitization. A permissive allowlist (unrestricted style, class, data-*, or permissive URI schemes) yields a bypass despite the library being "correct." Configuration is the attack surface, not the code.
  • Cache integrity. A poisoned or stale serialized configuration cache can serve a permissive filter graph. Treat the cache as security-sensitive configuration, not a performance hint.
  • Abandonment. No patches for a future HTML Purifier CVE means the sanitizer degrades from defense to liability on a timeline you do not control.
  • Upgrade coupling. A PHP or Laravel minor bump that breaks the wrapper blocks the platform upgrade — a low-adoption dependency becomes a scheduling constraint for unrelated work.

Ramp-up. Developer ramp-up is low: the API surface is small and the concepts (allowlist, profile, sanitize) are standard. Operational ramp-up is moderate: cache warming, size limits, write-path placement, and the shadow-mode rollout all require deliberate setup. Legal and security review is the long pole — plan for it to consume more calendar time than the engineering work itself, and do not let a successful spike create pressure to skip it.

Recommendation posture. Treat this as a conditional, reversible pilot rather than an adoption. The default should be mews/purifier or symfony/html-sanitizer; adopt phlib/xss-sanitizer only if the performance spike shows a material advantage that cannot be replicated by caching around a permissively licensed alternative, and only after LGPL clearance and repository provenance are resolved. The interface-first integration pattern keeps that decision cheap to reverse either way.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle