rhukster/dom-sanitizer
MIT-licensed PHP 7.3+ DOM/SVG/MathML sanitizer using DOMDocument and DOMPurify-based allowlists. Remove dangerous tags/attributes, strip namespaces and PHP/HTML/XML tags, and optionally compress output. Supports HTML, SVG, and MathML modes.
composer require rhukster/dom-sanitizer
use Rhukster\DomSanitizer\DOMSanitizer;
$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
$cleanHtml = $sanitizer->sanitize($userInput);
DOMSanitizer::HTML, DOMSanitizer::SVG, or DOMSanitizer::MATHML for context-specific sanitization.$options in the README for remove-namespaces, remove-php-tags, etc.// Laravel Form Request Example
public function store(Request $request) {
$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
$cleanContent = $sanitizer->sanitize($request->input('content'));
// Save $cleanContent to DB
}
// For SVG uploads (e.g., Laravel File Upload)
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
$cleanSvg = $sanitizer->sanitize($svgFileContent);
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
$sanitizer->addAllowedAttributes(['xlink:href' => ['href']]); // Whitelist SVG-specific attributes
// app/Http/Middleware/SanitizeInput.php
public function handle($request, Closure $next) {
$request->merge([
'sanitized_content' => (new DOMSanitizer(DOMSanitizer::HTML))
->sanitize($request->content)
]);
return $next($request);
}
// config/app.php
'bindings' => [
Rhukster\DomSanitizer\DOMSanitizer::class => function ($app) {
return new DOMSanitizer(DOMSanitizer::HTML);
},
];
use Illuminate\Validation\Rule;
$validator = Validator::make($data, [
'content' => [
'required',
function ($attribute, $value, $fail) {
$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
if ($sanitizer->sanitize($value) !== $value) {
$fail('Invalid HTML detected.');
}
},
],
]);
class AppSanitizer extends DOMSanitizer {
public function __construct() {
parent::__construct(DOMSanitizer::HTML);
$this->addAllowedTags(['custom-tag']);
$this->addAllowedAttributes(['custom-tag' => ['data-custom']]);
}
}
// Process multiple user-generated SVGs asynchronously
SanitizeSvgJob::dispatch($svgContents)->onQueue('sanitize');
// Job class
public function handle() {
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
$cleanSvg = $sanitizer->sanitize($this->svgContents);
// Store or send $cleanSvg
}
XXE Risks in Legacy Code:
simplexml_load_string or DOMDocument::loadHTML directly, bypassing this sanitizer, XXE attacks may still occur.DOMSanitizer::sanitize() before DOM manipulation.// ❌ Vulnerable
$dom = new DOMDocument();
$dom->loadHTML($userInput);
// ✅ Secure
$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
$dom->loadHTML($sanitizer->sanitize($userInput));
False Positives in SVG:
feGaussianBlur) may be stripped if not properly whitelisted (see release/1.0.9.md).$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
$sanitizer->addAllowedTags([
'feGaussianBlur', 'feBlend', 'feColorMatrix',
// ... other SVG filter tags
]);
CSS Injection in <style> Tags:
<style> tags may contain malicious CSS (e.g., url('javascript:...')).<style> tags entirely or use the package’s built-in CSS sanitization:$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
$sanitizer->addDisallowedTags(['style']);
Performance with Large XML:
compress-output: false to reduce memory usage:$sanitizer->sanitize($largeXml, ['compress-output' => false]);
Inspect Allowed/Disallowed Lists:
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
dump($sanitizer->getAllowedTags()); // Debug allowed tags
dump($sanitizer->getDisallowedAttributes()); // Debug blocked attributes
Log Sanitization Failures:
$original = $userInput;
$clean = $sanitizer->sanitize($original);
if ($original !== $clean) {
\Log::warning('Sanitization modified input', [
'original' => $original,
'clean' => $clean,
]);
}
Test Edge Cases:
<!DOCTYPE ... [ <!ENTITY ...> ]> and <!ENTITY % ...> declarations.<style>@import 'https://evil.com';</style>.	javascript:alert(1)).Custom Validation Logic:
$sanitizer = new DOMSanitizer(DOMSanitizer::HTML);
$sanitizer->addAllowedAttributes(['custom' => ['data-*']]); // Allow data-* attributes
Pre/Post-Processing:
// Pre-process: Strip known malicious patterns
$preProcessed = preg_replace('/<script.*?>.*?<\/script>/is', '', $input);
$clean = $sanitizer->sanitize($preProcessed);
// Post-process: Re-add safe elements
$final = str_replace('{{placeholder}}', $safeElement, $clean);
Laravel Service Provider:
// app/Providers/AppServiceProvider.php
public function boot() {
\Blade::directive('sanitize', function ($expression) {
return "<?php echo (new \\Rhukster\\DomSanitizer\\DOMSanitizer(\\Rhukster\\DomSanitizer\\DOMSanitizer::HTML))->sanitize($expression); ?>";
});
}
Usage in Blade:
{!! sanitize($userInput) !!}
How can I help you explore Laravel packages today?