Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-33937 — Handlebars.js AST Injection Remote Code Execution Vulnerability | Kitploit
Tools/GitHubGitHub/eqstlab/cve-2026-33937
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPapers & ResearchLearning & EducationPayload DevelopmentLabs & Practice
GitHubeqstlab/cve-2026-33937

CVE-2026-33937

Handlebars.js AST Injection Remote Code Execution Vulnerability

View Repository
213 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

This post is a research article published by EQSTLab.

Referenced PoC: dinhvaren/cve-2026-33937

CVE-2026-33937

★ CVE-2026-33937 Handlebars.js AST Injection Remote Code Execution PoC ★

https://github.com/user-attachments/assets/99e383e7-e71f-4e10-8c62-f50abff8b4f5


Description

CVE-2026-33937 : Handlebars.js AST Injection Remote Code Execution Vulnerability

Affected Versions4.0.0 – 4.7.8
Patched Version4.7.9
CVSS Score9.8 (Critical)

A Type Confusion vulnerability in Handlebars.js arises from the fact that Handlebars.compile() accepts not only a template string but also a pre-parsed AST object (JSON) as its input. An attacker who controls the value passed to compile() can supply a crafted AST object in which the value field of a NumberLiteral node is replaced with an arbitrary JavaScript string. Because the internal code generator inserts that field directly into the emitted JavaScript function body without sanitization, the resulting function executes attacker-controlled code when rendered — achieving Remote Code Execution on the server.


Lab Setup

Build and run the vulnerable environment using Docker:

Build Image

root@kitploit:~
docker build -t cve-2026-33937-server .

Run Container

root@kitploit:~
docker run --name cve-2026-33937 -p 12701:12701 -p 9229:9229 cve-2026-33937-server

Or use the provided npm scripts:

root@kitploit:~
npm run docker:up   # build + run in one step

The application is served at http://localhost:12701.


How to Use

Web UI

Open http://localhost:12701 in a browser. The page presents a B2B email builder interface. User-supplied field values are interpolated into a Handlebars template string on the client side and then posted to the server for rendering. Inject a malicious Handlebars payload via the input fields or directly via the API.

Direct API

root@kitploit:~
# POST crafted template to the vulnerable endpoint
curl -s -X POST http://localhost:12701/api/email/preview \
  -H "Content-Type: application/json" \
  -d '{"subject":"test","editorTemplateData":"<PAYLOAD>"}'

Replace <PAYLOAD> with an AST injection payload targeting Handlebars.compile().


Analysis

Vulnerable Endpoint

root@kitploit:~
POST /api/email/preview

The server accepts a JSON body containing editorTemplateData and passes it directly to Handlebars.compile() with no sanitization or allowlist enforcement:

root@kitploit:~
// app.js
const renderEmail = Handlebars.compile(editorTemplateData);

Technical Root Cause

Handlebars.compile() is documented as accepting a template string, but its internal type check also allows a pre-parsed AST object to be passed directly. Inside javascript-compiler.js, the NumberLiteral() visitor emits the node's value field verbatim into the generated JavaScript source without any type validation or sanitization:

root@kitploit:~
// javascript-compiler.js (simplified)
NumberLiteral(number) {
  this.pushStackLiteral(number.value);   // value inserted as-is into emitted JS
}

If an attacker supplies a crafted AST object where number.value is a string containing arbitrary JavaScript (e.g., "1; require('child_process').execSync(...)") instead of a numeric literal, the emitted function body contains and executes that code at render time.

The dangerous pattern in the vulnerable application is:

root@kitploit:~
const render = Handlebars.compile(userInput);  // userInput may be a crafted AST object
render(safeContextData);                        // attacker code runs here

Note on exploitation technique: Existing public PoCs (including the referenced one) achieve the injection via a NumberLiteral node combined with a lookup helper. This PoC confirms the same RCE primitive using a BooleanLiteral node combined with the log built-in helper, demonstrating that the type confusion is not limited to a single node type or helper function.

Attack Flow

  1. The attacker submits a POST request to /api/email/preview with a crafted editorTemplateData value.
  2. The server calls Handlebars.compile() on the attacker-controlled AST object.
  3. The compiler skips parsing and directly processes the attacker-supplied AST object, passing the injected literal node to the code generator.
  4. Code generation produces a JavaScript function that breaks out of the template sandbox.
  5. Calling render() triggers execution of arbitrary JavaScript in the server process.

Why This Matters

When Handlebars is implemented in a Node.js backend environment, this vulnerability leads to a server-side code execution path, unlike standard client-side XSS. The attack does not require any output to be reflected to a user; the payload executes within the Node.js process with the same privileges as the application. Depending on the deployment:

  • Sensitive files (e.g., application secrets, /etc/passwd) can be read and exfiltrated.
  • Outbound connections can be initiated for a reverse shell.
  • Persistence mechanisms can be installed if the process has sufficient filesystem access.

Scenario

root@kitploit:~
+-------------------------------------------+
|                  Attacker                 |
+-------------------------------------------+
                      |
                      | POST /api/email/preview
                      | {"editorTemplateData": "<malicious payload>"}
                      v
+-------------------------------------------+
|   Handlebars.compile(editorTemplateData)  |
|   (No sanitization — app.js:17)           |
+-------------------------------------------+
                      |
                      | AST node injection
                      | breaks template sandbox
                      v
+-------------------------------------------+
|  Arbitrary JS Execution (Server Process)  |
+-------------------------------------------+
                      |
                      | Read sensitive files, spawn shell,
                      | exfiltrate secrets, etc.
                      v
+-------------------------------------------+
|        Remote Code Execution (RCE)        |
+-------------------------------------------+

Mitigation

  1. Upgrade Handlebars.js to 4.7.9 or later.
    Version 4.7.9 introduces strict input type validation in compile(), rejecting non-string arguments before code generation begins.

  2. Enforce a type check before calling compile().
    If an immediate upgrade is not possible, validate that the argument is always a string at the call site:

    root@kitploit:~
    if (typeof templateInput !== 'string') throw new TypeError('Template must be a string');
    const render = Handlebars.compile(templateInput);
    
  3. Use handlebars/runtime for build-time pre-compilation.
    Pre-compile templates at build time with the Handlebars CLI and ship only the runtime bundle. The runtime build does not include compile(), eliminating the attack surface entirely for production deployments.


Disclaimer

This repository is intended solely for security research, education, and controlled vulnerability demonstration. It must not be used to test or exploit systems without explicit written authorization from the system owner. The purpose of this project is to help security researchers, defenders, and developers understand the vulnerability, validate exposure in controlled lab environments, and apply effective mitigations.


References

  • https://handlebarsjs.com/
  • https://github.com/handlebars-lang/handlebars.js
Download Tool