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

Htmlawed Laravel Package

vanilla/htmlawed

Laravel integration for HTMLawed, a PHP HTML sanitizer and validator. It cleans user-submitted markup, balances tags, filters unsafe attributes and elements, and helps preserve safe formatting in rich text. Useful for sanitizing comments, CMS content, and other untrusted HTML.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Unchanged by this release. htmLawed remains a single-file, dependency-free PHP HTML filter, and vanilla/htmlawed remains Vanilla Forums' Composer-packaged fork of it. It is a leaf dependency: no framework coupling, no service container assumptions, no global state beyond a class you instantiate yourself. That makes it trivially embeddable in a Laravel app — but it also means Laravel gives you nothing for free. There is no service provider, no facade, no config publishing, no Blade directive. The integration surface is one call: Htmlawed::filter($html, $config, $spec). For a TPM the blast radius is still one method, and it sits cleanly behind a port/interface in your domain layer. The relevant question remains not "does it fit Laravel" but "does a thin single-maintainer fork deserve to be the trust boundary for user-generated HTML." v2.2.15 is the first evidence in this assessment that the answer might be "yes, with conditions" rather than "no."

Integration feasibility. Still low effort, high stakes. Installation is a one-line Composer require; wiring is a 30-line service provider binding a HtmlSanitizer interface to an adapter. The real work is policy definition, not code: deciding the allowed-tag/allowed-attribute matrix per content type, encoding htmLawed's spec-string config, and building a regression corpus. Budget one engineer-day for the mechanical integration and one to two weeks of part-time effort for security validation and policy work. What v2.2.15 adds to the estimate: this is not a drop-in version bump. The package jumped from v2.2.5 to v2.2.15 — ten upstream htmLawed releases — in a single PR. Whatever accumulated behavior changes, tightened allowlists, or edge-case fixes landed in 1.2.6 through 1.2.14 arrive as one undifferentiated blob, undocumented in the release note. Add one to two engineer-days to diff the vendored Htmlawed.php, read upstream's changelog, and re-run the payload corpus before you accept this version.

Technical risk. Revised, in descending order of severity:

  1. License is still unresolved. The release note says nothing about licensing; metadata still reports NOASSERTION. Upstream htmLawed is dual-licensed GPL/LGPL, and the fork's packaging does not declare cleanly. GPL-family obligations on a component that touches every stored comment is a distribution question, not a legal footnote. This remains a genuine go/no-go gate. A routine upstream-sync release is not a licensing event, and should not be read as one.
  2. Maintenance concentration — downgraded, not cleared. The premise behind this risk ("the fork will lag upstream by an unknown interval") is now demonstrably wrong in at least one instance: the fork shipped an upstream bump. Three qualifications keep this at high severity rather than retiring it. First, the version-number jump implies the previous gap spanned ten upstream releases, so the historical lag was substantial, not incidental. Second, the release cadence is bursty and unpredictable — you cannot plan a CVE response around "they'll probably sync." Third, the fork's sync schedule is driven by Vanilla's product needs (ticket VNLA-5166), not by disclosures affecting your threat model. You are still a passenger.
  3. Correctness risk — now with a concrete new surface. htmLawed's spec-string configuration is terse and easy to misconfigure in a way that silently widens the allowlist. This release adds a second, subtler variant: behavior changes inherited from upstream that alter output on inputs your policy was validated against. Because sanitizer bugs are invisible until exploited, and because this bundle is opaque, the absence of a test corpus is itself a risk.
  4. Integration quirks. Unchanged. Verify the fork namespaces or guards the historical global htmLawed() function to avoid collision in a Composer-autoloaded app, and confirm no PHP 8.3 deprecation noise in the newly vendored file — upstream 1.2.15 may have modernized some of it, which would be a positive but unverified.

Key questions for the vendor/owner. Why this over symfony/html-sanitizer or ezyang/htmlpurifier, which have more eyes and clearer licensing? What is the exact license of the fork as packaged — and has it changed? New: what is the delta between upstream 1.2.5 and 1.2.15, and which of those ten releases contained security-relevant fixes? New: is the fork now on a stated sync cadence, or was this a one-off driven by an internal Vanilla ticket? Who is the internal owner when a bypass is disclosed? Is there a documented path to consume upstream htmLawed security fixes?

Integration Approach

Stack fit. Unchanged. Well-suited to high-volume, low-complexity sanitization: forum comments, support tickets, activity feeds, notification bodies. htmLawed's pitch is speed and zero dependencies, and it is materially cheaper per call than HTMLPurifier for typical input sizes. Poorer fit for rich, schema-heavy editorial content where you want structural DOM manipulation; keep that on a heavier library or a dedicated service.

Migration path. Do not rip out an existing sanitizer. Stand up the adapter behind a HtmlSanitizer contract and register it as an alternate implementation. Run shadow mode for two to four weeks: sanitize every write with both the incumbent and htmLawed, log divergences, and diff outputs on a sample of real stored content. For legacy stored rows, prefer sanitize-on-render over rewriting the database — in-place backfill of historical HTML is irreversible and the failure mode is silent content loss.

Compatibility. Framework-agnostic, so Laravel version support reduces to PHP version support; verify explicitly against your pinned PHP runtime with E_ALL and deprecations promoted to errors. Check ext-mbstring/iconv availability. Test in the queue worker context too. New for v2.2.15: if you are already running v2.2.x in production, treat this as a behavior-change release rather than a patch. Re-run the corpus in shadow mode against the new version for at least one release cycle before promoting it, and diff sanitizer output on a stored-content sample — the ten-release upstream delta is precisely where silent over-stripping hides.

Sequencing. (1) License review — hard gate, still open. (2) Spike: adapter + interface + allowlist policy for one content type. (3) Build the payload corpus (OWASP XSS filter evasion, payloadsallthethings) and assert both no bypass and no over-stripping. (4) Shadow mode with divergence logging. (5) Cut over one content type behind a feature flag. (6) Expand per content type, retiring the incumbent path only after a full release cycle of clean divergence data. Insert between 1 and 2: upstream-delta review of 1.2.5→1.2.15 and a manual diff of the vendored file. This is a prerequisite for greenfield adoption of this version and for any existing deployment considering the bump.

Pinning. Pin the exact version — 2.2.15, not ^2.2. The jump from .5 to .15 is an object lesson in why a caret range on a sanitizer is indefensible: a routine composer update would have silently pulled ten upstream releases with no review signal.

Operational Impact

Maintenance. The picture improves but the obligation does not disappear. You now have evidence the fork is alive and its packaged version mirrors upstream's (package 2.2.15 bundles htmLawed 1.2.15) — that mirroring is a useful operational property, since it lets you map a package version to an upstream version at a glance and reason about lag. Keep the quarterly upstream review, keep the emergency-vendoring process, and add one rule: any version-number jump of more than a patch increment triggers corpus re-validation, because the size of the delta is your only proxy for risk. Treat the allowlist config as versioned code under review, not environment configuration.

Support. No commercial support, no SLA. Nuance from this release: the change came from @acharron-hl, a first-time contributor who by naming convention appears to be a Vanilla/Higher Logic employee, working an internal ticket. That is mildly reassuring — the fork is maintained by the vendor that owns the downstream product, so it is unlikely to be abandoned outright. But it also confirms the sync schedule is set by Vanilla's priorities. Internal ownership must still be named before adoption: which team responds when a CVE drops on a Friday. If no team will own it, that is the answer.

Scaling. Unchanged. CPU-bound, pure-PHP string processing. Typical comment-sized input (a few KB) costs low single-digit milliseconds — fine inline for request-path writes at moderate volume. Two caveats: cost grows with input length and markup nesting, so hard-cap the input size (e.g., 256 KB) and reject beyond that; and pathological deeply-nested or unterminated-markup inputs can degrade non-linearly, a DoS vector if the sanitizer runs synchronously on untrusted uploads. For bulk imports or large documents, move sanitization to a queue.

Failure modes. Ranked by how quietly they fail: (a) over-stripping — legitimate markup silently deleted, discovered as user complaints weeks later; this release widens the exposure, since ten upstream versions of behavior change land at once; (b) bypass — new mutation XSS vector, discovered by an attacker; (c) config drift — a spec-string edit widens the allowlist without a code-review signal; (d) global function collision or PHP deprecation fatals on runtime upgrade; (e) abandonment — materially less likely after this release, but the failure mode becomes "abandonment after you have stopped watching," which is worse. Each needs a distinct detector; only (d) is loud.

Ramp-up. Mechanically trivial: a competent Laravel engineer wires this in a day and understands htmLawed's spec syntax within a week. The genuine ramp-up cost is on the reviewer side — someone must be able to read a sanitizer allowlist and judge whether it is safe, and read an upstream changelog and judge whether a behavior change matters. That skill is scarcer than the integration work suggests. Plan for one designated reviewer and a written sanitization policy doc before the first content type ships.

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.
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
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource