GHSA-q2c6-c6pm-g3gh
NoneCVSS
—
EPSS
—
Published
Sep 4, 2020
CISA due date
—
Cloudanix analysis
A vulnerable template library can let someone turn a text-rendering feature into a way to run commands inside the application.
- Exploitation
- Remote Authenticated
- Attacker needs
- Low Privilege
- Complexity
- Moderate
- Impact
- Remote Code Execution
- Component
- Library
- Class
- RCE
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
This vulnerability in the npm package Handlebars can allow arbitrary code execution when an application compiles and renders attacker-controlled templates or unsafe template input. Handlebars is normally designed to render data into templates, but vulnerable versions can be abused to escape intended template sandboxing and reach JavaScript execution primitives in the Node.js process. Successful exploitation can execute code with the privileges of the application process, potentially enabling file access, command execution, secret exposure, or further compromise of the hosting environment.
Why it matters to the business
Applications that allow users, integrations, plugins, content editors, or external data sources to influence Handlebars templates may be exposed to full application compromise. The operational impact can include theft of application secrets, unauthorized access to customer or business data, service disruption, tampering with generated content, and movement into adjacent systems using credentials available to the Node.js process. Although this issue is old and not listed in CISA KEV, Handlebars is widely used in JavaScript ecosystems, so lingering vulnerable transitive dependencies remain a realistic supply-chain exposure.
How an attack unfolds
An attacker first identifies an application feature that uses Handlebars to compile or render templates, especially where template text, partials, helpers, layout content, or theme/plugin components can be supplied or modified by an untrusted user. The attacker submits a malicious Handlebars expression designed to bypass template restrictions and access JavaScript object constructors or similar execution paths. When the vulnerable Handlebars version compiles or renders that payload, the expression executes within the application’s Node.js runtime. From there, the attacker may run operating-system commands, read local files, exfiltrate environment variables and credentials, alter rendered output, deploy persistence in writable application directories, or pivot using the application’s network access and service credentials.
How to fix it
Upgrade Handlebars to a fixed version immediately: for the 3.x line use 3.0.8 or later, and for the 4.x line use 4.5.3 or later. Prefer upgrading to the latest supported Handlebars release compatible with the application rather than only the minimum fixed version. Review direct and transitive dependencies by running package-manager audit tooling and dependency tree inspection, because vulnerable Handlebars versions are often introduced through frameworks, static-site generators, email templating packages, documentation tools, or build systems. If immediate upgrade is not possible, prevent untrusted users from controlling template source, partials, helpers, layouts, or precompiled template artifacts; treat user-supplied content strictly as data, not template code; disable or remove dynamic template compilation from untrusted locations; and isolate rendering services with least-privilege filesystem, network, environment variable, and OS permissions.
How to confirm the fix worked
Confirm that all deployed and build-time dependency trees resolve Handlebars to fixed versions: 3.0.8 or later for 3.x and 4.5.3 or later for 4.x. Use commands such as `npm ls handlebars`, `npm audit`, `yarn why handlebars`, `pnpm why handlebars`, lockfile review, and software composition analysis to identify both direct and transitive copies. Validate container images, serverless bundles, build artifacts, and vendored `node_modules` directories, not only source repositories. Functionally test application areas that render templates to ensure upgrades did not break expected output. Confirm that user-controlled content is rendered as data only and cannot introduce new Handlebars template syntax that is compiled server-side.
Typical attack path
- Discover that the target application uses Handlebars for server-side template rendering, email rendering, document generation, theming, or plugin-based content.
- Find an input path where template source, partials, helpers, layout definitions, or trusted-looking content blocks can be influenced by an attacker.
- Submit or store a crafted Handlebars payload that attempts to escape normal template evaluation and reach JavaScript execution capabilities.
- Trigger rendering or compilation of the malicious template in the vulnerable Handlebars runtime.
- Execute code in the context of the Node.js application process.
- Collect environment variables, configuration files, application secrets, tokens, database credentials, or cloud metadata accessible from the process.
- Use obtained access to modify application behavior, exfiltrate data, disrupt service, or move laterally to connected services.
How to detect it
To assess prior exploitation, focus on applications that used vulnerable Handlebars versions and accepted user-controlled templates, themes, snippets, emails, documents, CMS content, or plugin definitions. Review web access logs, application logs, WAF events, API request bodies, stored content records, support-uploaded files, template repositories, and audit trails for Handlebars expressions containing suspicious JavaScript object traversal, constructor access, prototype manipulation, or attempts to invoke process and child-process APIs. Correlate suspicious template submissions with Node.js process behavior, including unexpected child process creation, shell execution, file reads from sensitive paths, outbound connections, or environment variable access. On hosts or containers, inspect process execution telemetry, EDR events, shell history, temporary directories, modified template files, unexpected JavaScript files, and package or startup script changes. Because there are no universally unique indicators for this library flaw, detection should combine vulnerable-version exposure, attacker-controlled template paths, suspicious Handlebars payload syntax, and post-exploitation behavior from the Node.js runtime.
- {{#with "s" as |string|}}
- {{#with "e"}}
- constructor.constructor
- lookup string.sub "constructor"
- this.constructor.constructor
- return process
- process.env
- process.mainModule
- require('child_process')
- require("child_process")
- child_process.exec
- child_process.execSync
- child_process.spawn
- child_process.spawnSync
- global.process
- Function("return this")
- {{constructor.constructor
- {{this.constructor
- {{#each
- /etc/passwd
- /bin/sh
- cmd.exe
- powershell.exe
What your security team should do
- Inventory all applications, services, build pipelines, and packaged artifacts that include the npm package `handlebars`.
- Prioritize remediation for internet-facing applications, multi-tenant systems, admin portals, content-management features, email/document generators, theme/plugin systems, and any service that compiles templates from user-modifiable input.
- Upgrade to Handlebars 3.0.8 or later for 3.x or 4.5.3 or later for 4.x; preferably move to the latest supported release.
- Inspect lockfiles and transitive dependency chains to ensure older vulnerable versions are not retained by nested packages.
- Block or redesign features that allow untrusted users to submit Handlebars template source, partials, helpers, or layout definitions.
- Harden runtime permissions for template-rendering services by limiting filesystem write access, outbound network access, environment secrets, and operating-system command execution capability where feasible.
- Add SCA checks in CI/CD to fail builds that introduce vulnerable Handlebars versions.
- Review historical logs and artifacts for suspicious template payloads and unexpected Node.js child process execution from applications that used vulnerable versions.
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.3 |
| 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