Chrome removes XSLT on 17 November 2026: audit and migrate before Chrome 158
Summary. Chrome 158, scheduled for 17 November 2026, stops running XSLT on Stable for everyone except origin trial and enterprise policy participants, and those two escape hatches themselves expire with Chrome 176 on 17 August 2027. Both browser XSLT entry points go: the XSLTProcessor JavaScript class and the <?xml-stylesheet type="text/xsl" ?> processing instruction. Console warnings started in Chrome 142 on 28 October 2025 and the official deprecation landed in Chrome 143 on 2 December 2025. Chrome measures XSLT on roughly 0.02% of page loads, with under 0.001% using the processing instruction, so most teams will find nothing. The ones that find something usually find it in a place nobody owns: a styled RSS feed, a sitemap, a device status page, or a government-facing XML portal.
Firefox and WebKit have both indicated plans to remove XSLT too, so there is no browser to fall back to.
The timeline, verbatim from Chrome
The Chrome deprecation document by Mason Freed and Dominik Röttsches, published 29 October 2025, sets out seven dated milestones. Four have already passed.
| Chrome version | Date | What changes |
|---|---|---|
| 142 | 28 October 2025 | Early warning console messages added |
| 143 | 2 December 2025 | Official deprecation: warnings in the console and in Lighthouse |
| 145 | 2 December 2025 (Canary) | Canary, Dev and Beta begin disabling XSLT by default |
| 146 | 10 March 2026 | Enterprise policy goes live for testing and for continued use past removal |
| 152 | 25 August 2026 | Origin trial goes live, letting sites continue past removal |
| 158 | 17 November 2026 | XSLT stops functioning on Stable for everyone else |
| 176 | 17 August 2027 | Origin trial and enterprise policy stop; XSLT disabled for all users |
Two dates matter for planning. 25 August 2026 is three weeks away and is when the origin trial opens, which is the mechanism that buys you nine extra months if the migration will not land in time. 17 August 2027 is the real deadline, because after Chrome 176 there is no supported way to keep client-side XSLT running.
The scope is narrower than the headline suggests. Chrome is removing the XSLTProcessor class and the XSLT processing instruction. It is not removing XML. The same <?xml-stylesheet ?> processing instruction keeps working with type="text/css", so raw XML styled with CSS renders exactly as it does today. Chrome also plans to replace libxml2, its XML parser, with a memory-safe parser written in Rust, and states that change is intended to be transparent to developers.
Why it is going
The reasoning is a security argument, not a usage argument, though usage supports it. Client-side XSLT in Chromium runs on libxslt, an aging C/C++ codebase of the kind that produces memory safety bugs. Chrome's document cites CVE-2025-7425 and CVE-2022-22834, both in libxslt, and notes that because client-side XSLT is a niche feature, these libraries get far less maintenance and security scrutiny than JavaScript engines while still processing untrusted web content.
The version numbers tell the rest of the story. XSLT was a W3C recommendation on 16 November 1999. The language moved on, with XSLT 2.0 in 2007 and XSLT 3.0 in 2017. Browsers did not: every major engine still ships only XSLT 1.0 from 1999. A 27-year-old parser with no upgrade path, running on untrusted input, for 0.02% of page loads, is a difficult trade to defend.
Removal is coordinated. Chrome's page links positions from the Firefox and WebKit projects, both supporting removal, alongside the WHATWG HTML discussion where the concrete use cases were argued out. Chrome's own deprecation policy says a feature is not usually removed if other engines plan to keep supporting it. Here they do not.
Step 1: find out whether you are affected
Do this before you plan anything. Most teams are not affected, and the ones that are usually have exactly one or two files.
The fastest first pass is a repository grep. Three patterns cover both APIs and the common wrappers:
grep -rIn --include='*.xml' --include='*.xsl' --include='*.xslt' \
--include='*.js' --include='*.ts' --include='*.html' \
-e 'type="text/xsl"' \
-e 'XSLTProcessor' \
-e 'transformToFragment\|transformToDocument\|importStylesheet' .
Grep misses anything generated at runtime or served by a system you do not build. For that, Chrome exposes the deprecation through the Reporting API. Instrument a page and let real traffic tell you:
new ReportingObserver((reports, observer) => {
reports.forEach((report) => {
if (report.body.id === "XSLT") {
// XSLT usage was detected - report it back here.
}
});
}, {types: ["deprecation"], buffered: true}).observe();
That snippet is Chrome's own, and buffered: true matters: without it you miss reports fired before the observer attached. Ship the reporting call to whatever endpoint already collects your client errors, and give it a week of production traffic before you conclude you are clean.
For managed fleets there is a third option. Chrome's enterprise Legacy Technology Report collects deprecated-feature usage across the organisation and reports it centrally, which catches the internal admin console and the vendor appliance that no repository grep would ever see. That is usually where XSLT actually lives.
Check these five places specifically, because they are the ones teams forget:
RSS and Atom feeds with a stylesheet attached to make them readable in a browser. Sitemaps and other generated XML that got a stylesheet for human inspection. Embedded devices and appliances on the local network that serve a single XML endpoint transformed into HTML. Government, banking and healthcare portals built in the 2000s that still transform XML server responses client-side. Internal reporting tools where XSLT was used as a lazy templating language outside the JavaScript ecosystem.
Step 2: choose a path for each dependency
There is no single migration. Pick per dependency, based on whether you control the producer, the consumer, or neither.
| Path | Do this when | Effort | Lifespan | Watch out for |
|---|---|---|---|---|
| Move the transform server-side | You control the server and the XML is generated there | Medium | Permanent | Adds server CPU and a caching decision on every request |
| Migrate the endpoint to JSON and render client-side | You control both ends and the XML is really just data | High | Permanent | A wire-format change with real consumer coordination cost |
| SaxonJS from Saxonica | You need genuine XSLT and want to stop depending on the browser | Medium | Permanent | A third-party runtime dependency and its licence terms |
| WASM XSLT polyfill | You control the document but cannot rewrite the pipeline now | Low | Permanent, but you own the polyfill | Adds a script tag and a WASM download to every XML page |
| Chrome extension polyfill | You control neither the device nor the document | Low | Permanent, per client install | Requires every viewer to install it; no good for public pages |
| Origin trial or enterprise policy | Migration will not land before 17 November 2026 | Low | Expires 17 August 2027 | It is a delay, not a fix, and the second deadline is hard |
Two of those deserve detail.
The polyfill route is the cheapest thing that works. Chrome's page describes a WASM-based replacement for the XSLTProcessor class, so existing JavaScript keeps working after one script tag:
<script src="xslt-polyfill.min.js"></script>
<script>
const xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsltDoc);
const fragment = xsltProcessor.transformToFragment(xmlDoc, document);
</script>
For a document that uses the processing instruction rather than the JavaScript API, the polyfill can be invoked from inside the XML itself with a single added element:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="demo.xsl"?>
<ROOT>
<script src="xslt-polyfill.min.js"
xmlns="http://www.w3.org/1999/xhtml"></script>
...content...
The script detects the document type and the processing instruction and transforms the document in place.
SaxonJS from Saxonica is the serious option when XSLT is load-bearing rather than cosmetic. Chrome's own page names it as by far the largest client-side XSLT library and notes it goes well beyond the browsers' XSLT 1.0, implementing the full XSLT 3.0 standard with the in-progress 4.0 specification to follow. Moving to SaxonJS is an upgrade, not a workaround, and it is the only path that leaves you with more capability than you started with.
The RSS feed case, which is most of them
If your only exposure is a stylesheet on an RSS or Atom feed, the problem you are solving is narrow: a human clicked a feed link and should not see raw XML.
Chrome's recommended fix is to stop offering the link at all. Put <link rel="alternate" type="application/rss+xml"> in the HTML head rather than a visible <a href="feed.xml"> that people click by accident. Feed readers find the feed from the site URL; humans stay on the HTML page. Chrome frames this as the normal web split, HTML for humans and XML for machines.
That does not cover the case where somebody already has your feed URL and pastes it into a browser. For that, the one-line polyfill in the feed keeps the current behaviour, and because the <script> sits as a direct child of the root element, feed readers keep parsing the XML normally.
There is also a user-side fallback worth knowing about, because it changes how support tickets will read: when XSLT is disabled, Chrome shows a warning banner linking to an extension search page so users can install a polyfill extension themselves. Expect confused users on that banner before you expect them to file a clear bug.
What to do in the next three weeks
The 25 August 2026 origin trial opening is the next actionable date, so work backwards from it.
Run the grep this week and add the ReportingObserver snippet to any property where the grep is inconclusive. A week of production data is enough to know.
If you find nothing, write it down and close the item. This is a real outcome for most teams and the cost of re-checking every quarter is not worth it once the Reporting API says zero.
If you find something you control, pick between server-side rendering and the polyfill on effort alone. Both are permanent. Do not start a JSON migration to hit a November deadline; that is a product decision on a different clock.
If you find something you do not control, an appliance, a vendor portal, a partner feed, open the ticket with the vendor now and register for the origin trial when it opens on 25 August as the fallback. Vendor timelines on 2000s-era software are the reason the Chrome 176 date in August 2027 exists.
Then test on a pre-Stable channel. Chrome 145 onward already disables XSLT by default in Canary, Dev and Beta, so you can confirm the fix without waiting for November. Running Dev alongside Stable is Chrome's own standing advice for exactly this class of change, and it is the same discipline we apply to framework migrations like the Next.js 16 async request APIs change.
India-specific considerations
Client-side XSLT shows up more often in Indian enterprise and public-sector systems than the global 0.02% figure suggests, because a lot of that estate was built in the XML era and has not been rewritten. Bank statement portals, insurance policy viewers, examination and results portals, and B2B partner integrations that exchange XML over SFTP with a browser-viewable rendering layer are the recurring patterns.
Two practical notes. First, where the XML carries personal data, a client-side transform means that data lands in the browser in full even when the rendered page shows a subset. Moving the transform server-side reduces what leaves your boundary, which is the easier position to defend under the Digital Personal Data Protection Act 2023. Second, if the affected system is a vendor appliance under an annual maintenance contract, check whether browser-compatibility fixes are in scope before November rather than after, because the negotiation is cheaper now than during an outage.
Where XML endpoints are also being consumed by machines, this is a good moment to look at the whole integration rather than just the stylesheet, which is the argument we make in our API integration and modernisation work. The wider platform-change picture for 2026 is in our Interop 2026 web platform guide.
FAQ
When exactly does Chrome stop supporting XSLT?
Chrome 158, dated 17 November 2026, stops XSLT functioning on Stable releases for all users other than origin trial and enterprise policy participants. Those two mechanisms continue until Chrome 176 on 17 August 2027, after which XSLT is disabled for every user with no supported way to re-enable it.
What exactly is being removed?
Two browser APIs: the XSLTProcessor JavaScript class and the XSLT processing instruction, written as <?xml-stylesheet type="text/xsl" ?>. XML itself is not being removed, and the same processing instruction continues to work with type="text/css", so XML styled with CSS renders exactly as it does today.
How do I detect XSLT usage in my own codebase?
Grep for type="text/xsl", XSLTProcessor and the transform methods first. Then attach a ReportingObserver filtering for report.body.id === "XSLT" with buffered reports, and give it a week of production traffic. Enterprise fleets can use Chrome's Legacy Technology Report for centralised collection.
Will switching to Firefox or Safari help?
No. Chrome's deprecation document links positions from both the Firefox and WebKit projects indicating plans to remove XSLT from their engines as well. Chrome's stated policy is that a feature is not usually removed if other engines plan to keep it, so cross-engine agreement is part of why this is proceeding.
What is the fastest fix for a styled RSS feed?
Add one script element loading the WASM polyfill as a direct child of the feed's root element, which preserves the current rendering without affecting feed readers. The alternative Chrome recommends is removing the visible feed link and declaring the feed with <link rel="alternate" type="application/rss+xml"> instead.
Why is Chrome removing a working feature?
Security. Client-side XSLT runs on libxslt, an aging C and C++ codebase prone to memory safety bugs, with CVE-2025-7425 and CVE-2022-22834 cited as examples. Because the feature appears on roughly 0.02% of page loads, the library gets far less security scrutiny than JavaScript engines while still processing untrusted content.
Is SaxonJS a drop-in replacement?
Not drop-in, but it is the most capable path. Chrome names Saxonica's library as by far the largest client-side XSLT implementation, supporting the full XSLT 3.0 standard rather than the XSLT 1.0 that browsers shipped. It is a third-party runtime dependency, so check licensing and bundle size before committing.
What if the XSLT lives in a device or vendor product we cannot change?
Chrome's own recommendation for that case is the polyfill extension, which applies the transform client-side for any raw XML page without touching the device. Open a vendor ticket now, and register for the origin trial when it opens on 25 August 2026 as a dated fallback.
How eCorpIT can help
eCorpIT runs platform-migration work for teams carrying legacy web estate, and this class of change is a small, bounded piece of it: audit the codebase and live traffic, classify each dependency by who controls it, and pick the cheapest permanent fix rather than the most modern one. We are a Gurugram-based organisation founded in 2021, CMMI Level 5, MSME certified and ISO 27001:2022 certified, with senior engineers across web platform, API and cloud work, and we design data-handling changes aligned with DPDP Act 2023 requirements. If you have XML portals or feeds and no clear owner for them, talk to our team about scoping the audit before the origin trial opens.
References
- Chrome for Developers, "Removing XSLT for a more secure browser", 29 October 2025
- Chrome for Developers, "Feature deprecation and removal in Chrome"
- MDN, XSLTProcessor
- MDN, Transforming XML with XSLT
- WHATWG HTML issue 11523, removal of XSLT from the web platform
- Mozilla standards-positions issue 1287, XSLT removal
- NVD, CVE-2025-7425 in libxslt
- NVD, CVE-2022-22834 in libxslt
- GNOME/libxslt source repository
- W3C, XSL Transformations (XSLT) Version 1.0, 16 November 1999
- W3C, XSL Transformations (XSLT) Version 3.0
- Saxonica, SaxonJS documentation
- MDN, Reporting API
- Google Workspace Admin Help, Legacy Technology Report
Last updated: 3 August 2026.
Top comments (0)