u mu# Security Notes
The md() helper function converts user-provided markdown to HTML with automatic XSS protection.
- Library:
league/commonmarkv2.8+ withHTMLPurifierv4.19+ - Sanitization: Two-stage approach
- CommonMark converts markdown to HTML with table support
- HTMLPurifier filters output to allow only safe tags
- Configuration:
html_input: 'allow'- Allows HTML processingallow_unsafe_links: false- Blocks javascript: and data: URLs- Allowed tags:
p, br, strong, em, u, h1-h6, ul, ol, li, a[href], table, thead, tbody, tr, th, td, span, div, blockquote, code, pre - Blocked: All script tags, iframe, object, embed, form, input, etc.
offer.additional_text- Rendered in PDF offer viewsinvoice.additional_text- Rendered in PDF invoice views
// Input (malicious)
$markdown = "Hello <script>alert('XSS')</script> [Click](javascript:alert('XSS'))";
md($markdown);
// Output: "<p>Hello </p>" (script tag removed, unsafe link stripped)// Tables work
$markdown = "| A | B |\n|---|---|\n| 1 | 2 |";
md($markdown);
// Output: <table><thead>...</thead><tbody>...</tbody></table>
// Line breaks work
$markdown = "Line 1<br/>Line 2";
md($markdown);
// Output: <p>Line 1<br />Line 2</p>
// Safe HTML allowed
$markdown = "Text with <strong>bold</strong> and <em>italic</em>";
md($markdown);
// Output: <p>Text with <strong>bold</strong> and <em>italic</em></p>OfferTermsRequest: Validatesadditional_textas string, max 65535 chars- No pre-storage sanitization needed - markdown is safe to store raw
- Sanitization happens at render time via
md()helper
# Test in tinker
php artisan tinker
$markdown = "# Test\n<script>alert('xss')</script>\n[link](javascript:alert('xss'))";
echo md($markdown);
# Should output: <h1>Test</h1> with script tags stripped2026-01-09