Weave Code
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

Purify Laravel Package

stevebauman/purify

Laravel wrapper for HTMLPurifier to sanitize user-submitted HTML. Clean strings or arrays via a simple facade, with support for dynamic per-call configuration, published config, and caching options to keep output safe and consistent.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require stevebauman/purify
    php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"
    
    • Verify config/purify.php exists and is configured.
  2. First Use Case:

    use Stevebauman\Purify\Facades\Purify;
    
    $dirtyHtml = '<script>alert("XSS")</script><p>Hello</p>';
    $cleanHtml = Purify::clean($dirtyHtml); // Returns: `<p>Hello</p>`
    

Where to Look First

  • Facade: Stevebauman\Purify\Facades\Purify (for quick usage).
  • Config: config/purify.php (default rules, custom configs).
  • Casts: Stevebauman\Purify\Casts\PurifyHtmlOnGet (Eloquent integration).
  • Definitions: Stevebauman\Purify\Definitions\* (extend HTML/CSS rules).

Implementation Patterns

Core Workflows

  1. Basic Sanitization:

    // Single string
    $clean = Purify::clean($userInput);
    
    // Array of strings
    $cleanArray = Purify::clean($userInputs);
    
  2. Dynamic Configurations:

    $customConfig = ['HTML.Allowed' => 'div,p,a[href]'];
    $clean = Purify::config($customConfig)->clean($input);
    
  3. Named Configs (via config/purify.php):

    // config/purify.php
    'configs' => [
        'comments' => ['HTML.Allowed' => 'p,strong,em'],
    ];
    
    // Usage
    $clean = Purify::config('comments')->clean($comment);
    
  4. Eloquent Integration:

    // Model (Laravel 11+)
    protected function casts(): array
    {
        return [
            'content' => PurifyHtmlOnGet::class, // Uses default config
            'description' => PurifyHtmlOnGet::class.':comments', // Uses 'comments' config
        ];
    }
    
  5. API Request Sanitization:

    // Middleware or Controller
    public function store(Request $request)
    {
        $request->merge([
            'clean_content' => Purify::clean($request->content),
        ]);
    }
    

Integration Tips

  • Forms: Sanitize request()->input() or request()->all() before storage.
  • Blade: Use {{ $model->content }} (auto-sanitized via PurifyHtmlOnGet).
  • API Responses: Sanitize before returning JSON:
    return response()->json(['content' => Purify::clean($model->content)]);
    
  • Queue Jobs: Sanitize payloads in job handlers to prevent XSS in delayed processing.

Gotchas and Tips

Pitfalls

  1. Cache Stale Definitions:

    • After updating definitions in config/purify.php, run:
      php artisan purify:clear
      
    • Symptom: Old HTML tags/attributes persist despite config changes.
  2. Overly Restrictive Configs:

    • Default HTML.Allowed may break legitimate markup (e.g., style attributes).
    • Fix: Extend Html5Definition or use HTML.ForbiddenElements to whitelist.
  3. Performance in Loops:

    • Caching is enabled by default. Disable for debugging:
      'serializer' => null, // config/purify.php
      
    • Warning: Disabling caching impacts performance in production.
  4. Nested Config Overrides:

    • Dynamic Purify::config() replaces default settings, not merges.
    • Workaround: Merge configs manually:
      $mergedConfig = array_merge(config('purify.configs.default'), ['HTML.Allowed' => '...']);
      Purify::config($mergedConfig)->clean($input);
      
  5. CSS Property Gaps:

    • Default CSS.AllowedProperties lacks modern values (e.g., text-align: start).
    • Fix: Extend CSSDefinition:
      $definition->info['text-align'] = new \HTMLPurifier_AttrDef_Enum(['start', 'end', 'center']);
      

Debugging

  • Log Raw/Processed HTML:
    \Log::debug('Dirty HTML:', [$dirtyHtml]);
    \Log::debug('Clean HTML:', [Purify::clean($dirtyHtml)]);
    
  • Validate Configs: Use HTMLPurifier’s config validator to check syntax.

Extension Points

  1. Custom Definitions:

    • Extend Html5Definition for new elements/attributes (e.g., Trix editor):
      class TrixDefinition implements Definition {
          public static function apply($definition) {
              Html5Definition::apply($definition);
              $definition->addElement('figure', 'Inline', 'Flow', 'Common');
              // ...
          }
      }
      
    • Register in config/purify.php:
      'definitions' => \App\TrixDefinition::class,
      
  2. CSS Overrides:

    • Allow custom properties like gap or grid-template:
      class CustomCssDefinition implements CssDefinition {
          public static function apply($definition) {
              $definition->info['gap'] = new \HTMLPurifier_AttrDef_Length(['px', 'em']);
          }
      }
      
    • Register in config/purify.php:
      'css-definitions' => \App\CustomCssDefinition::class,
      
  3. Fallback for Missing Tags:

    • Use HTML.ForbiddenElements to whitelist instead of blacklisting:
      'HTML.ForbiddenElements' => 'script,iframe,object',
      

Pro Tips

  • Test Edge Cases:
    $testCases = [
        '<script>alert(1)</script>' => '<p>alert(1)</p>', // If 'p' is allowed
        '<div style="background:red">' => '<div style="background:red">', // If CSS is allowed
    ];
    
  • Benchmark Performance:
    $start = microtime(true);
    Purify::clean($largeHtml);
    $time = microtime(true) - $start;
    \Log::info("Purify time: {$time}s");
    
  • Use PurifyHtmlOnSet for Input Sanitization:
    protected $casts = [
        'content' => PurifyHtmlOnSet::class, // Sanitize on save
    ];
    
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai