twig/markdown-extra
Twig extension that adds markdown_to_html and html_to_markdown filters for converting Markdown blocks to HTML and HTML back to Markdown directly in your Twig templates, with configurable parsers.
Secure Content Moderation Systems:
Build vs. Buy Tradeoffs:
parsedown/parsedown, michelf/php-markdown) with a maintained, Symfony-backed solution. Avoids technical debt from forks or abandoned packages.markdown-extra now supports tempest/markdown alongside its existing engine(s) (#4890). This is a strategic de-risking signal: rendering backends are pluggable, so we are not hard-locked to a single parser supply chain. Useful when a team already standardizes on Tempest components, or when we want a lighter-weight engine for high-volume, low-complexity rendering paths (e.g., comment streams) while keeping the heavier engine for docs.markdown_to_html to support MathJax via a wrapper filter.Use Cases by Laravel Domain:
markdown_to_html in Blade.GET /posts/{id}/rendered) with XSS-proof HTML.tempest/markdown support, we can A/B or tier rendering by content class — e.g., Tempest engine for volume-heavy short-form (comments, chat transcripts) and CommonMark for long-form docs — without adopting a second rendering stack.Developer Productivity Gains:
{{ $comment|e }}) for Markdown content. Example: A support ticket system can render user comments directly without sanitization steps.Adopt when:
tempest/markdown is now a supported backend, so this is a low-friction fit for teams standardizing on that ecosystem.Look elsewhere if:
markdown-extra’s scope. Consider:
tempest/markdown backend expands choices but does not add extensions — evaluate it on parsing behavior/performance, not feature breadth.*"This update closes a critical security gap in how our platform handles user-generated Markdown—directly impacting customer trust, compliance, and operational risk—and the newest release adds rendering-engine flexibility, which lowers our long-term vendor lock-in. Here’s why it’s a top priority:
- Risk Elimination: Blocks XSS attacks in high-impact areas (e.g., public forums, API documentation, support tickets), reducing liability and support costs.
- Compliance Alignment: Meets OWASP Top 10, PCI DSS, and GDPR requirements for untrusted input handling, critical for industries like finance, healthcare, or SaaS.
- Cost Savings: Avoids custom security patches or third-party tools (e.g., HTML Purifier), saving $X/year in engineering overhead.
- Reduced Lock-In (v3.29.0): Support for an additional Markdown engine (
tempest/markdown) means we can swap rendering backends without a rewrite — a direct hedge against future cost or supply-chain risk.- Competitive Differentiation: Enables secure Markdown workflows (e.g., Git-based docs, collaborative editing) without sacrificing safety—a gap many competitors overlook.
Ask: Should we prioritize this update for [specific high-risk areas, e.g., our public forum or API docs] in the next sprint? Both the security fix and v3.29.0 are non-breaking, require minimal effort, and have high ROI in security and scalability.
Business Impact:
- Forums/Support: Reduces moderation overhead and security incidents from malicious scripts in user posts.
- APIs/Docs: Safeguards technical documentation, critical for enterprise adoption and developer trust.
- Multi-Tenant SaaS: Prevents cross-tenant XSS attacks, protecting SLA compliance and customer data.
- Platform Strategy: Pluggable engines preserve architectural optionality as we scale content volume."*
*"This release track patches CVE-2026-46637 in
twig/markdown-extra(an XSS vulnerability in Markdown-to-HTML rendering), and v3.29.0 adds a new renderer backend:tempest/markdown(#4890). Here’s how it impacts our Laravel stack:
- Critical Fix (already in): The package auto-escapes untrusted input by default, preventing XSS in user-generated Markdown (e.g., forum posts, comments). This is enabled for all
markdown_to_htmlcalls without configuration changes.- New in v3.29.0:
tempest/markdownis now a supported engine inmarkdown-extra. It is an additive capability — no change to default behavior, no new required dependency unless we opt in. Treat it as an alternative renderer, not a replacement.- Non-Breaking: Existing Twig filters (
markdown_to_html,html_to_markdown) work as before but are now safer. No API changes required in v3.28.0 → v3.29.0.- Performance: Negligible overhead from the security fix. Engine selection may shift per-request cost — benchmark if we adopt
tempest/markdownfor high-volume paths.- Caching: Safe for cached outputs (e.g., blog posts), as the package handles escaping internally. Pin the engine in cache keys if we ever run more than one backend, since output can differ byte-for-byte between engines.
Action Items:
- Update immediately to
twig/markdown-extra:^3.29.0in all environments (supersedes^3.26.0).- Audit high-risk areas:
- User-generated Markdown (forums, wikis, comments).
- Bidirectional pipelines (HTML ↔ Markdown migrations).
- Evaluate (optional, low priority): Spike
tempest/markdownon one low-risk surface (e.g., comment rendering) to compare output parity, performance, and extension coverage before any adoption decision.- Test edge cases:
- Verify custom Twig filters or extensions using raw Markdown input.
- Check if legacy content (e.g., migrated HTML) renders correctly.
- If switching engines anywhere, diff rendered output against the current baseline.
- Document the change: Note that input is now pre-escaped, so manual escaping in templates is redundant and may break formatting. Also record which engine each surface uses.
Key Considerations:
- Custom Filters: If you’ve created filters that bypass escaping (e.g., for trusted content), re-verify them against the patched version — and confirm they behave identically on any engine you enable.
- Engine Parity: Do not assume
tempest/markdownand the existing engine produce identical HTML; treat any switch as a formatting-change event requiring visual regression checks.- Dependency Hygiene:
tempest/markdownis opt-in — keep it out ofcomposer.jsonuntil a spike justifies it, so we don't grow the vendor footprint without a decision."*
How can I help you explore Laravel packages today?