CVE-2026-33940
High · 8.1CVSS
8.1
EPSS
0.8%
Published
Mar 27, 2026
CISA due date
—
Cloudanix analysis
A flaw in a widely used template library could let attackers take over certain servers if those applications render attacker-controlled data in an unsafe way.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- High
- Impact
- Remote Code Execution
- Component
- Library
- Class
- RCE
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Handlebars versions 4.0.0 through 4.7.8 can mishandle dynamic partial resolution when a crafted non-primitive object is supplied through the template context. If that object can be returned by a dynamic partial lookup, it can bypass conditional checks in resolvePartial(), cause invokePartial() to treat the unresolved partial as compileable input, and pass an attacker-controlled Handlebars AST into env.compile(). In applications using the full Handlebars build with runtime compilation enabled, this can lead to server-side JavaScript execution and, in the worst case, arbitrary command execution in the privileges of the affected application process.
Why it matters to the business
Successful exploitation can allow an unauthenticated remote attacker to execute code on an application server if the application renders attacker-controlled data through vulnerable dynamic partial behavior. The practical risk depends heavily on application design because exploitation requires control over a value used in a dynamic partial lookup, but the impact is high where reachable: service compromise, data theft, credential exposure, lateral movement from the application host, and application downtime. The issue is not currently listed in CISA KEV, is not marked as ransomware-associated, has low EPSS at 0.00703, and has no indicated public exploit maturity, but affected Handlebars versions are common in JavaScript dependency trees, so organizations should still prioritize inventory and upgrade work.
How an attack unfolds
An attacker first identifies an application path that renders Handlebars templates using the full Handlebars package rather than the runtime-only build. The attacker then looks for a template that performs a dynamic partial lookup, such as a partial selected from context data, and finds an input field, request body, API value, stored profile field, CMS content value, or other data path that can influence the rendered context. The attacker supplies a specially structured object instead of ordinary primitive data. When the application renders the template, the crafted object is returned by the dynamic partial lookup and bypasses the expected guard logic in partial resolution. The runtime fails to resolve the partial normally, falls back to compilation, and passes the attacker-controlled AST-like object to env.compile(). The generated JavaScript can then execute under the server-side Node.js process, potentially allowing command execution, file access, environment variable theft, or further compromise depending on process privileges and sandboxing.
How to fix it
Upgrade Handlebars to version 4.7.9 or later wherever the package is used directly or transitively. If an immediate upgrade is not possible, use the runtime-only build, require('handlebars/runtime'), so the vulnerable fallback compilation path is unavailable. Disable or remove dynamic partial lookups when the rendered context includes user-controlled data. Sanitize all context data before rendering and reject non-primitive objects in fields that can influence partial selection. Ensure dependency lockfiles are regenerated and deployed so production systems actually consume the fixed package. Where Handlebars is bundled into frameworks, build tools, plugins, or downstream packages, update the dependent component that embeds or pins Handlebars rather than only changing the top-level dependency declaration.
How to confirm the fix worked
Confirm that dependency manifests and lockfiles no longer resolve handlebars to versions 4.0.0 through 4.7.8. Validate with package managers and software composition analysis tooling, for example npm ls handlebars, yarn why handlebars, pnpm why handlebars, or equivalent SBOM scans. Inspect application code and templates for dynamic partial lookup patterns and verify that any remaining use cannot be influenced by untrusted context data. Confirm that server-side code imports the fixed full package or the runtime-only build where compilation is not required. Run regression tests for template rendering and partial resolution after the upgrade. For high-risk applications, add a negative security test that attempts to pass non-primitive objects into partial-selection context fields and verifies they are rejected or rendered harmlessly.
Typical attack path
- Identify a Node.js or JavaScript server-side application using Handlebars 4.0.0 through 4.7.8.
- Find routes, API endpoints, stored-content workflows, or template-rendering features where user-controlled data is included in the Handlebars render context.
- Determine whether templates use dynamic partial lookup behavior, especially patterns similar to {{> (lookup ...)}} or other context-driven partial names.
- Submit a crafted non-primitive object through a controllable data path so it can be returned during dynamic partial resolution.
- Trigger server-side template rendering so the vulnerable resolvePartial() and invokePartial() flow is reached.
- Cause the unresolved partial fallback path to pass the crafted object to env.compile().
- Execute attacker-controlled JavaScript in the application process, then use that access to read secrets, modify data, run system commands, or pivot further.
How to detect it
There are no universal, reliable indicators of compromise for this issue because exploitation occurs inside application-specific Handlebars rendering paths and the attacker-controlled object may not be logged verbatim. To assess possible prior exploitation, review web, API gateway, WAF, and application logs for requests that submitted unusual nested JSON objects, unexpected object-valued fields where strings are normally expected, or payloads that preceded template-rendering failures. Correlate those events with Node.js process telemetry, EDR data, auditd, Sysmon, container runtime logs, and cloud workload logs for unexpected child processes launched by the application process, such as shells, curl/wget, scripting runtimes, or system utilities. Review application error logs for Handlebars partial-resolution or compilation errors around suspicious requests. Inspect deployments for evidence of runtime template compilation, dynamic partial usage, and vulnerable package versions to determine whether the vulnerable path was reachable. Also investigate outbound network connections, new or modified files, environment variable access, credential use anomalies, and lateral movement activity from affected application hosts after suspicious rendering events.
What your security team should do
- Inventory all applications, build pipelines, server-side rendering services, CMS integrations, email-template systems, and internal tools that use Handlebars.
- Prioritize internet-facing and multi-tenant services that accept user-controlled JSON, profile data, content blocks, template variables, or API payloads rendered through Handlebars.
- Upgrade all affected Handlebars installations to 4.7.9 or later and verify lockfile resolution, container images, and deployed artifacts.
- Search templates for dynamic partial lookup patterns such as {{> (lookup ...)}} and review whether any lookup values can be controlled by users or external systems.
- Where upgrade timing is constrained, switch to require('handlebars/runtime') and disable runtime compilation for untrusted templates.
- Add input validation that prevents non-primitive objects from being used in fields that select partials or influence template structure.
- Review application logs and endpoint telemetry for suspicious template-rendering errors, unexpected child process execution, and unusual outbound network activity from Node.js application processes.
- Because there is no current KEV listing, ransomware association, named threat actor activity, or known mature public exploit signal, treat this as a high-impact targeted-risk issue rather than confirmed broad exploitation, while still remediating promptly due to potential server-side code execution.
The record
Handlebars provides the power necessary to let users build semantic templates. In versions 4.0.0 through 4.7.8, a crafted object placed in the template context can bypass all conditional guards in `resolvePartial()` and cause `invokePartial()` to return `undefined`. The Handlebars runtime then treats the unresolved partial as a source that needs to be compiled, passing the crafted object to `env.compile()`. Because the object is a valid Handlebars AST containing injected code, the generated JavaScript executes arbitrary commands on the server. The attack requires the adversary to control a value that can be returned by a dynamic partial lookup. Version 4.7.9 fixes the issue. Some workarounds are available. First, use the runtime-only build (`require('handlebars/runtime')`). Without `compile()`, the fallback compilation path in `invokePartial` is unreachable. Second, sanitize context data before rendering: Ensure no value in the context is a non-primitive object that could be passed to a dynamic partial. Third, avoid dynamic partial lookups (`{{> (lookup ...)}}`) when context data is user-controlled.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | handlebars | 4.0.0 | 4.7.9 |
| Chainguard | kibana-8.17 | 0 | 8.17.10-r15 |
| Chainguard | kibana-8.17-bitnami | 0 | 8.17.10-r15 |
| Chainguard | kibana-8.17-iamguarded | 0 | 8.17.10-r15 |
| Chainguard | kibana-8.18 | 0 | 8.18.8-r11 |
| Chainguard | kibana-8.18-bitnami | 0 | 8.18.8-r11 |
| Chainguard | kibana-8.18-iamguarded | 0 | 8.18.8-r11 |
| Chainguard | kibana-8.19 | 0 | 8.19.13-r5 |
| Chainguard | kibana-8.19-bitnami | 0 | 8.19.13-r5 |
| Chainguard | kibana-8.19-iamguarded | 0 | 8.19.13-r5 |
| Chainguard | kibana-9.0 | 0 | 9.0.8-r16 |
| Chainguard | kibana-9.0-bitnami | 0 | 9.0.8-r16 |
| Chainguard | kibana-9.0-iamguarded | 0 | 9.0.8-r16 |
| Chainguard | kibana-9.1 | 0 | 9.1.10-r9 |
| Chainguard | kibana-9.1-iamguarded | 0 | 9.1.10-r9 |
| Chainguard | kibana-9.2 | 0 | 9.2.7-r2 |
| Chainguard | kibana-9.2-iamguarded | 0 | 9.2.7-r2 |
| Chainguard | kibana-9.3 | 0 | 9.3.2-r2 |
| Chainguard | kibana-9.3-iamguarded | 0 | 9.3.2-r2 |
| Chainguard | lerna | 0 | 9.0.7-r2 |
| Chainguard | opensearch-dashboards-2 | 0 | 2.19.5-r5 |
| Chainguard | opensearch-dashboards-2-fips | 0 | 2.19.5-r4 |
| Chainguard | opensearch-dashboards-3 | 0 | 3.5.0-r12 |
| Chainguard | opensearch-dashboards-3-fips | 0 | 3.5.0-r9 |
| Chainguard | pelias-api | 0 | 7.6.0-r5 |
| Chainguard | prism | 0 | 5.14.3-r13 |
| Chainguard | rancher-api-ui | 0 | 1.2.3-r8 |
| Chainguard | tileserver-gl-fips | 0 | 5.5.0-r11 |
| Chainguard | wazuh-dashboard | 0 | 4.14.4-r1 |
| Wolfi | lerna | 0 | 9.0.7-r2 |
| Wolfi | opensearch-dashboards-2 | 0 | 2.19.5-r5 |
| Wolfi | opensearch-dashboards-3 | 0 | 3.5.0-r12 |
| Wolfi | prism | 0 | 5.14.3-r13 |
| Wolfi | rancher-api-ui | 0 | 1.2.3-r8 |
Related vulnerabilities
- GHSA-xhpv-hc6g-r9c6 Handlebars.js has JavaScript Injection via AST Type Confusion when passing an object as… Same vulnerability
- 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-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