SVGO's removeScripts plugin (disabled by default) removes scripts from the SVG, however executable scripts were left intact in some cases. If a consumer relied on this plugin for sanitization and served them to users, these SVGs could open up doors to XSS.
SVGO has a plugin for removing scripts from an SVG, which removes:
<script> elementson… event handlers (v4 and v3 only)While SVGO is not a sanitization library, SVGO continues to maintain the plugin for those already using it for this purpose.
However, there were two problems:
script elements, for example if one declared an explicit prefix for the SVG namespace ( <svg:script>) instead of using the default namespace ( <script>), the <svg:script> tag would be left intact.import { optimize } from 'svgo';
/** Presume that this string was obtained in some other way, such as network. */
const original = `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:uwu="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" version="1.1">
<a uwu:href="JavaScript:(() =&gt; { alert(document.cookie) })();"><text y="30">uwu</text></a>
<svg:script>
alert(document.cookie);
</svg:script>
</svg>
`;
optimize(original, {
plugins: ['removeScripts']
});
// Did not remove <svg:script> or uwu:href="JavaScript:…—still executed by browsers.
If you run SVGO on untrusted input (e.g., user uploads to a web application) and you depended on removeScripts, then some scripts may still be present. If that SVG was then opened directly by another user on the same domain, it could invoke scripts that could read local storage or cookies.
This may affect you if you have enabled one of the following:
| SVGO Version | Plugin Name | |---|---| | v4 | removeScripts | | v3 | removeScriptElement | | v2 | removeScriptElement | | v1 | removeScriptElement |
It's unlikely to impact users who just use SVGO locally on their own SVGs or in build pipelines.
SVGO patched v4.0.2 and v3.3.4. Just upgrade the dependency using your preferred package manager! For example:
yarn up svgo
# or if SVGO is a nested dependency
yarn up -R svgo
The proposed fix is to improve our namespace-aware handling to explicitly act on the default namespace, SVG namespace, and XHTML namespace only. This handles all scripts that are executed by browsers, but will leave intact custom prefixes that happen to have an element called <*:script> which clients shouldn't treat as executable.
SVGO patched v2.8.3, however SVGO v2 explicitly only implements and documents that it will remove <script> elements and nothing more. It has the namespace aware handling for tags like <svg:script> or <xhtml:script>, but has not been updated to remove JavaScript URIs or event handlers like >= v3. If this is something you need, please upgrade to v4 or v3, or reach for one of the documented workarounds at the end.
SVGO v1 has been deprecated for a while now and won't be patched. Please upgrade to a more recent version! If something is preventing you from doing so, please reach out! We're happy to expand our migration guides or support you if you're having trouble.
If your motivation for enabling the plugin is SVG sanitization, consider reaching for a dedicated SVG sanitization tool and invoke it before passing the SVG to SVGO.
| Software | From | Fixed in |
|---|---|---|
@types / svgo
|
1.0.0 | 2.8.3 |
@types / svgo
|
3.0.0 | 3.3.4 |
@types / svgo
|
4.0.0 | 4.0.2 |
A security vulnerability is a weakness in software, hardware, or configuration that can be exploited to compromise confidentiality, integrity, or availability. Many vulnerabilities are tracked as CVEs (Common Vulnerabilities and Exposures), which provide a standardized identifier so teams can coordinate patching, mitigation, and risk assessment across tools and vendors.
CVSS (Common Vulnerability Scoring System) estimates technical severity, but it doesn't automatically equal business risk. Prioritize using context like internet exposure, affected asset criticality, known exploitation (proof-of-concept or in-the-wild), and whether compensating controls exist. A "Medium" CVSS on an exposed, production system can be more urgent than a "Critical" on an isolated, non-production host.
A vulnerability is the underlying weakness. An exploit is the method or code used to take advantage of it. A zero-day is a vulnerability that is unknown to the vendor or has no publicly available fix when attackers begin using it. In practice, risk increases sharply when exploitation becomes reliable or widespread.
Recurring findings usually come from incomplete Asset Discovery, inconsistent patch management, inherited images, and configuration drift. In modern environments, you also need to watch the software supply chain: dependencies, containers, build pipelines, and third-party services can reintroduce the same weakness even after you patch a single host. Unknown or unmanaged assets (often called Shadow IT) are a common reason the same issues resurface.
Use a simple, repeatable triage model: focus first on externally exposed assets, high-value systems (identity, VPN, email, production), vulnerabilities with known exploits, and issues that enable remote code execution or privilege escalation. Then enforce patch SLAs and track progress using consistent metrics so remediation is steady, not reactive.
SynScan combines attack surface monitoring and continuous security auditing to keep your inventory current, flag high-impact vulnerabilities early, and help you turn raw findings into a practical remediation plan.