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

Anti Xss Laravel Package

voku/anti-xss

AntiXSS is a lightweight PHP library for filtering malicious input and preventing cross-site scripting attacks. It cleans user-supplied strings and arrays, with support for custom sanitizing, making it a simple drop-in defense for web forms and input handling.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • voku/anti-xss is a framework-agnostic, single-class sanitizer (voku\helper\AntiXSS) with one primary entry point, xss_clean(). It has no Laravel service provider, facade, config file, or published assets — it is a plain Composer library that Laravel must wrap.
  • The package's design is input/string mutation, not context-aware output encoding. That is orthogonal to Laravel's primary XSS control (Blade's {{ }} escaping and e()), so it cannot replace existing defenses and should not be positioned as the control of record.
  • The only genuinely valuable architectural seams are:
    • xss_clean() for allowlisted rich-text/HTML paths where Blade escaping is intentionally bypassed ({!! !!}, WYSIWYG content, markdown rendering, email templates).
    • isXssFound() as a detection/telemetry signal — useful for security logging, anomaly alerting, and measuring attack traffic, independent of whether sanitization is applied.
    • The add* / remove* dictionary mutators for building a curated, product-specific policy profile.
  • It is a poor fit as a global middleware or model mutator: sanitizing on input causes irreversible lossy writes to the database and conflates storage with presentation.

Integration feasibility

  • Trivially installable (composer require voku/anti-xss), MIT licensed, PHP 8.x-oriented, no Laravel version coupling. Estimated integration effort for a wrapper service + Blade directive is roughly 1–2 engineering days, plus test corpus work.
  • No first-party Laravel package means we own: the service provider binding, configuration surface, facades/helpers, and test coverage.
  • A real blocker-class side effect: the transitive dependency voku/portable-utf8 calls ini_set('default_charset', 'UTF-8') during autoload. In a Laravel app this can shift json_encode escaping, mb_* behavior, and DB driver charset assumptions. Mitigation requires defining PORTABLE_UTF8__DISABLE_AUTO_ENCODING before the Composer autoloader loads — awkward to guarantee under Octane, queue workers, and PHPUnit bootstraps. This must be validated in staging before rollout.

Technical risk

  • High — false sense of security. Regex/dictionary sanitization is inherently bypassable; the README itself defers to HTML Purifier or tgalopin/html-sanitizer for configurable needs and to OWASP guidance for the actual prevention model. Treating this as "XSS solved" is the dominant failure mode.
  • Medium-high — data corruption. setStripe4byteChars() can silently destroy emoji and CJK content; setKeepPreAndCodeTagContent() and attribute stripping can mangle legitimate developer/user HTML. Because sanitization is lossy and one-way, a misconfiguration becomes an unrecoverable data incident.
  • Medium — mutable global state. Dictionary changes are instance-level mutators with no immutable config object. Bound as a singleton in the container, per-request or per-tenant policy differences become a cross-request contamination risk; bound as a non-singleton, large regex dictionaries are rebuilt per resolution.
  • Medium — supply chain / bus factor. Effectively a single-maintainer project with modest adoption signals (711 stars, reported 0 dependents — likely a data artifact, but not a strong ecosystem-confidence signal). No vendor SLA or formal CVE process we can point auditors at. Positives: active CI, Codecov, PHPStan + Infection mutation testing gate on PRs (100% MSI on the diff), and a recent release — indicating real regression discipline.
  • Low-medium — performance. Dictionary-driven regex passes over large strings are CPU-linear at best; pathological inputs can approach PCRE backtrack limits. Relevant for API payloads, imports, and bulk backfills.

Key questions for the team

  1. Which concrete sinks are we protecting — rich-text output, legacy unescaped fields, email templates? If the answer is "everything," this is the wrong tool.
  2. Do we sanitize at write time (lossy, unauditable) or read time (repeatable cost, reversible)? Read-time is strongly preferred.
  3. What is our CSP posture? If CSP is not yet enforced, adding a sanitizer may create the illusion of coverage.
  4. Do we accept the portable-utf8 charset side effect, and have we proven it under Octane and queue workers?
  5. Is an allowlist sanitizer (Symfony HtmlSanitizer / HTML Purifier via mews/purifier) a better primary with anti-xss demoted to a detection layer?
  6. Who owns the dictionary policy, and how do we review changes to it — it is a security boundary expressed as application config.

Integration Approach

Stack fit

  • Recommended topology: three layers, clearly ranked.
    1. Blade escaping / context-aware output encoding (primary, unchanged).
    2. Allowlist HTML sanitization for rich-text sinks (Symfony HtmlSanitizer or HTML Purifier).
    3. anti-xss as a secondary hardening + detection layer, wrapped behind a first-party interface (e.g. App\Support\Security\HtmlSanitizer) so the implementation is swappable.
  • Never expose AntiXSS directly to controllers or views. Wrap it; the wrapper owns configuration, logging, and the isXssFound() telemetry hook.

Migration path

  • Greenfield: no migration, but establish the wrapper and a golden-corpus test suite before first use.
  • Replacing an existing sanitizer (e.g. HTML Purifier via mews/purifier): do not swap in place. Build a differential harness — replay a corpus of production HTML (top N content records by traffic) through old and new, diff outputs, and classify regressions before cutover.
  • Existing dirty data: run a read-only audit pass first (sanitize → compare → report), quantify how many rows would change, and only then decide between read-time sanitization and a backfill job.

Compatibility

  • Verify PHP version matrix against the Laravel version in use and against Octane/Swoole longevity assumptions (instance reuse and mutable dictionaries).
  • Validate the default_charset side effect across web, queue, scheduler, and test environments.
  • Confirm interaction with existing middleware ordering: sanitization must not run before validation (it corrupts input and defeats validation messages) and must not double-run on already-encoded data.

Sequencing

  1. Discovery: inventory every unescaped output sink ({!! !!}, v-html, mail templates, API consumers rendering HTML). This is the highest-value TPM deliverable — it defines scope and is reusable regardless of tool choice.
  2. Policy: decide allowlists (tags, attributes, URL schemes) with Product/Security sign-off; encode them in the wrapper, not in scattered calls.
  3. CSP in report-only in parallel, so we get independent detection coverage.
  4. Wrapper + tests: unit tests, a regression corpus, and a isXssFound() → structured log/metric pipeline.
  5. Pilot on one low-risk surface (e.g. comments) for two sprints; measure false positives and user-reported content breakage.
  6. Broaden to remaining rich-text sinks; keep CSP moving to enforce.
  7. Backfill only after pilot data confirms the corruption rate is acceptable.

Operational Impact

Maintenance

  • Low code footprint, but ownership is ours: the wrapper, the dictionary policy, and the test corpus are all application artifacts that need an owner and a review process. Dictionary changes are security changes — treat them like auth code, not config.
  • Pin the dependency (exact or ~ constraint), commit composer.lock, and run composer audit in CI. Add release-watch for voku/anti-xss and voku/portable-utf8; a transitive charset change is a plausible silent breakage.
  • Keep the abstraction seam so a future swap to Symfony HtmlSanitizer is a one-file change.

Support

  • MIT, no vendor SLA, no commercial backing — acceptable for a defense-in-depth layer, unacceptable as the sole XSS control. Document this explicitly in the threat model so auditors and future engineers understand the layering.
  • No official Laravel channel; internal documentation and a runbook are required deliverables, not optional.

Scaling

  • Cost is per-sanitized-string CPU. At high write or render volume, sanitize at read time with a request-scoped cache keyed by content hash, and cap input size before sanitization.
  • For bulk operations (imports, backfills, re-renders), batch and throttle; watch for PCRE backtrack-limit warnings in logs, which indicate pathological payloads.
  • Under Octane, resolve the sanitizer per-request rather than as a long-lived singleton unless policy is provably global.

Failure modes to instrument

  • Over-sanitization: legitimate content mangled — track edit-after-post rates, support tickets, and content-diff counts.
  • Under-sanitization / bypass: track isXssFound() hit rates and CSP violation reports; a spike in one without the other indicates a gap.
  • Charset drift: JSON or DB encoding anomalies post-deploy, especially after a portable-utf8 bump.
  • Emoji/4-byte loss: only if setStripe4byteChars(true) is enabled — assert against it in tests.
  • PCRE/backtrack failures on large or adversarial strings — return the original string and log rather than throwing into the request path.
  • Regex/PCRE errors after a PHP upgrade — regex-based security code is version-sensitive; include it in PHP upgrade checklists.

Ramp-up

  • Engineer ramp-up is a few hours; the conceptual ramp-up is the real cost. The team must internalize that this package is hardening, not prevention, and that Blade escaping and CSP remain the load-bearing controls.
  • Provide a short internal one-pager (sink inventory, layering diagram, when to use the wrapper vs. {{ }}) and a test corpus so new engineers can validate changes without rediscovering XSS semantics.
  • The highest-risk onboarding failure is a well-intentioned engineer adding xss_clean() in a middleware as a "safety net" — pre-empt it with a lint rule or code-review checklist.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core