GHSA-2cf5-4w76-r9qv
High · 7.3CVSS
7.3
EPSS
—
Published
Sep 4, 2020
CISA due date
—
Cloudanix analysis
A vulnerable template library can let someone who can edit templates make the application run their own code on the server.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Moderate
- Impact
- Remote Code Execution
- Component
- Library
- Class
- RCE
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
This vulnerability affects the npm handlebars template engine and can permit arbitrary code execution when an application compiles or renders attacker-controlled Handlebars templates. The issue is a sandbox-escape class flaw: specially crafted template expressions can reach JavaScript object constructors or helper behavior that should not be exposed to templates, allowing execution of attacker-supplied JavaScript in the context of the Node.js process. Impact depends on how the library is used; applications that only render trusted, developer-controlled templates are much less exposed, while systems that accept user-supplied templates, themes, email templates, document templates, CMS snippets, or plugin-defined templates are at higher risk.
Why it matters to the business
Successful exploitation can let an attacker take over the application process, read or modify application data, access secrets available to the runtime, pivot to connected services, or disrupt service availability. Because Handlebars is a widely used npm package and this issue has been public for years, organizations should assume vulnerable versions are well understood by attackers even though this advisory is not listed in CISA KEV and has no indicated ransomware association.
How an attack unfolds
An attacker first needs a path to influence a Handlebars template, not merely the normal data values inserted into a safe template. Common exposure points include user-editable notification templates, CMS/theme functionality, report builders, document-generation workflows, low-code customization, or administrative template-preview features. The attacker submits a crafted Handlebars template that abuses expression resolution and JavaScript object access to escape the intended template sandbox. When the vulnerable application compiles or renders that template with an affected handlebars version, the payload can execute JavaScript inside the Node.js runtime. From there, the attacker may run system commands if the process permits it, read environment variables, access credentials, make outbound network connections, alter rendered content, or establish persistence through modified templates or application files.
How to fix it
Upgrade handlebars to a fixed version. For the npm package, use handlebars 3.0.8 or later on the 3.x line, or handlebars 4.5.2 or later on the 4.x line. Prefer upgrading to the latest supported release compatible with the application. After upgrading, regenerate lockfiles and rebuild/redeploy artifacts so vulnerable transitive copies are removed. If immediate upgrade is not possible, mitigate by preventing untrusted users from creating, editing, importing, or previewing Handlebars templates; restrict template customization to trusted administrators; disable dynamic template compilation where feasible; precompile trusted templates during build time; run the Node.js service with least privilege; block unnecessary outbound network access from the application; and ensure secrets are not exposed unnecessarily through environment variables or process-accessible files.
How to confirm the fix worked
Confirm dependency resolution with package-manager tooling such as `npm ls handlebars`, `npm audit`, `yarn why handlebars`, `pnpm why handlebars`, or software composition analysis results. Verify that every resolved handlebars instance is 3.0.8 or later for 3.x, or 4.5.2 or later for 4.x, and that no vulnerable copy remains in nested dependencies or bundled application artifacts. Review lockfiles such as `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml` for vulnerable versions. Functionally test template-rendering features after upgrade. For exposure validation, inventory features that allow users, administrators, plugins, or integrations to submit or edit templates, and confirm untrusted template compilation is disabled or restricted.
Typical attack path
- Identify an application feature that accepts or stores custom Handlebars templates, themes, snippets, email layouts, document templates, or template-preview content.
- Submit benign template expressions to confirm that Handlebars syntax is evaluated server-side.
- Craft a malicious template that attempts to escape Handlebars' intended execution constraints and reach JavaScript runtime capabilities.
- Trigger rendering or preview of the malicious template so the server compiles and executes it using a vulnerable handlebars package.
- Execute commands or JavaScript in the context of the Node.js application process.
- Collect secrets, application data, environment variables, or service credentials available to that process.
- Use obtained access to move laterally, modify templates or application content, deploy additional payloads, or disrupt service operations.
How to detect it
Investigate whether any application feature allowed untrusted or semi-trusted users to submit Handlebars templates before the fixed version was deployed. Review application logs, template-edit audit logs, CMS/theme/plugin logs, request bodies captured by WAF or API gateways, and database-backed template histories for suspicious Handlebars expressions referencing JavaScript internals, constructors, module loading, process access, or command execution. On hosts and containers, review process telemetry for unexpected child processes spawned by Node.js, such as shells, curl/wget, PowerShell, Python, Perl, or netcat. Examine EDR, container runtime, and operating-system logs for Node.js processes invoking command interpreters or making unusual outbound network connections. Review web access logs for requests to template-preview, template-save, theme, email-template, notification-template, report-template, or document-generation endpoints followed by errors, outbound callbacks, new processes, or changes to stored templates. Because no single universal IOC exists for this library flaw, prioritize behavioral evidence: malicious template content, unexpected Node.js child processes, credential access, and suspicious outbound traffic after template rendering.
- constructor.constructor
- process.mainModule
- require('child_process')
- require("child_process")
- child_process.exec
- child_process.execSync
- child_process.spawn
- execSync(
- Function("return this")
- Function('return this')
- {{lookup
- __proto__
- prototype.constructor
- process.env
- /bin/sh -c
- cmd.exe /c
- powershell.exe
- curl http://
- wget http://
- nc -e
- bash -i
What your security team should do
- Prioritize upgrading all applications and build artifacts that include vulnerable handlebars versions, especially internet-facing services and systems with user-editable templates.
- Search dependency inventories, lockfiles, container images, serverless packages, and frontend/backend bundles for handlebars versions older than the fixed releases.
- Identify application features that compile templates dynamically and restrict them to trusted users or replace them with precompiled, developer-controlled templates.
- Review historical template content and template-edit audit logs for suspicious JavaScript runtime access patterns.
- Harden Node.js runtime permissions: run as a non-root user, minimize filesystem access, restrict outbound egress, and avoid exposing high-value secrets through environment variables where possible.
- Add detection for suspicious Handlebars template strings that reference JavaScript constructors, process access, child process execution, or module loading.
- If suspicious exploitation is found, rotate credentials accessible to the affected process, preserve forensic artifacts, and investigate outbound connections and child processes spawned by the application.
The record
Arbitrary Code Execution in handlebars
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | handlebars | 0 | 3.0.8 |
| npm | handlebars | 4.0.0 | 4.5.2 |
| Chainguard | code-server | 0 | 0 |
| Chainguard | code-server-compat | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.9 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.9 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.0 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.1 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.0 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.1 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.9 | 0 | 0 |
| Wolfi | code-server | 0 | 0 |
| Wolfi | code-server-compat | 0 | 0 |
Related vulnerabilities
- GHSA-7rx3-28cr-v5wh Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSetter__… Also affects handlebars
- GHSA-442j-39wm-28r2 Handlebars.js has a Property Access Validation Bypass in container.lookup Also affects handlebars
- CVE-2026-33940 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33941 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33939 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33937 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33938 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33916 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars