VYPR
Moderate severityNVD Advisory· Published Nov 19, 2025· Updated Nov 20, 2025

esm.sh CDN service has JS Template Literal Injection in CSS-to-JavaScript

CVE-2025-65026

Description

esm.sh is a nobuild content delivery network(CDN) for modern web development. Prior to version 136, The esm.sh CDN service contains a Template Literal Injection vulnerability (CWE-94) in its CSS-to-JavaScript module conversion feature. When a CSS file is requested with the ?module query parameter, esm.sh converts it to a JavaScript module by embedding the CSS content directly into a template literal without proper sanitization. An attacker can inject malicious JavaScript code using ${...} expressions within CSS files, which will execute when the module is imported by victim applications. This enables Cross-Site Scripting (XSS) in browsers and Remote Code Execution (RCE) in Electron applications. This issue has been patched in version 136.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/esm-dev/esm.shGo
< 0.0.0-20251118065157-87d2f64975740.0.0-20251118065157-87d2f6497574

Affected products

1

Patches

1
87d2f6497574

Fix `*.css?module` XSS (#1237)

https://github.com/esm-dev/esm.shJe XiaNov 18, 2025via ghsa
2 files changed · +12 14
  • server/router.go+7 9 modified
    @@ -1069,17 +1069,15 @@ func esmRouter(db Database, esmStorage storage.Storage, logger *log.Logger) rex.
     				if err != nil {
     					return rex.Status(500, err.Error())
     				}
    +				css, err = minify(string(css), esbuild.LoaderCSS, esbuild.ES2022)
    +				if err != nil {
    +					return rex.Status(500, err.Error())
    +				}
     				buf := bytes.NewBufferString("/* esm.sh - css module */\n")
     				buf.WriteString("const stylesheet = new CSSStyleSheet();\n")
    -				if bytes.ContainsRune(css, '`') {
    -					buf.WriteString("stylesheet.replaceSync(`")
    -					buf.WriteString(strings.TrimSpace(string(utils.MustEncodeJSON(string(css)))))
    -					buf.WriteString(");\n")
    -				} else {
    -					buf.WriteString("stylesheet.replaceSync(`")
    -					buf.Write(css)
    -					buf.WriteString("`);\n")
    -				}
    +				buf.WriteString("stylesheet.replaceSync(")
    +				buf.WriteString(strings.TrimSuffix(string(utils.MustEncodeJSON(strings.TrimSuffix(string(css), "\n"))), "\n"))
    +				buf.WriteString(");\n")
     				buf.WriteString("export default stylesheet;\n")
     				ctx.SetHeader("Content-Type", ctJavaScript)
     				ctx.SetHeader("Content-Length", fmt.Sprintf("%d", buf.Len()))
    
  • test/issue-1191/test.ts+5 5 modified
    @@ -1,4 +1,4 @@
    -import { assert, assertEquals } from "jsr:@std/assert";
    +import { assert, assertEquals, assertStringIncludes } from "jsr:@std/assert";
     
     // related issue: https://github.com/esm-dev/esm.sh/issues/1191
     Deno.test(
    @@ -9,7 +9,7 @@ Deno.test(
         assert(res.ok);
         assertEquals(res.headers.get("content-type"), "application/javascript; charset=utf-8");
         assertEquals(res.headers.get("cache-control"), "public, max-age=31536000, immutable");
    -    assert(text.includes(`import("/aleman@1.0.7/style.css?module")`));
    +    assertStringIncludes(text, `import("/aleman@1.0.7/style.css?module")`);
       },
     );
     
    @@ -21,8 +21,8 @@ Deno.test(
         assert(res.ok);
         assertEquals(res.headers.get("content-type"), "application/javascript; charset=utf-8");
         assertEquals(res.headers.get("cache-control"), "public, max-age=31536000, immutable");
    -    assert(text.includes("const stylesheet = new CSSStyleSheet();"));
    -    assert(text.includes("stylesheet.replaceSync(`"));
    -    assert(text.includes("`);\nexport default stylesheet;"));
    +    assertStringIncludes(text, "const stylesheet = new CSSStyleSheet();");
    +    assertStringIncludes(text, "stylesheet.replaceSync(");
    +    assertStringIncludes(text, ");\nexport default stylesheet;");
       },
     );
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.