CVE-2025-27516
NoneCVSS
—
EPSS
0.5%
Published
Mar 5, 2025
CISA due date
—
Cloudanix analysis
Some applications that let users create their own templates could be tricked into running attacker-controlled code, so the template engine should be updated and exposed template features reviewed.
- 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 flaw affects Jinja sandboxed template execution before version 3.1.6. The sandbox is intended to prevent untrusted templates from reaching unsafe Python objects or methods, but the `|attr` filter could be used to retrieve a string object's native `format` method in a way that bypassed Jinja's protected attribute lookup. If an application allows an attacker to supply or edit template content that is rendered inside `SandboxedEnvironment`, the attacker may be able to escape the sandbox and execute arbitrary Python code in the context of the application process. The impact is therefore remote code execution, but only in applications that execute attacker-controlled or otherwise untrusted Jinja templates.
Why it matters to the business
Applications that let users submit, customize, import, or store Jinja templates may be exposed to full application compromise, including data theft, service disruption, credential access, and pivoting to other systems reachable from the application runtime. Risk is lower for applications that only render developer-controlled templates, and current public exploitation signals are limited: the issue is not in CISA KEV, is not known to be ransomware-used, has low EPSS, and has no listed exploit maturity. However, Jinja is widely used in Python web and automation ecosystems, so organizations should still prioritize inventory and remediation where untrusted template execution is a feature.
How an attack unfolds
An attacker first needs a path to control Jinja template source, such as a template editor, user-defined notification template, CMS-like customization feature, document generation workflow, email template system, automation platform, or any API that stores and renders user-provided template text. The attacker submits a malicious template that uses the `attr` filter to obtain access to a string formatting method in a way that avoids the sandbox's normal checks. Through that bypass, the template can traverse Python object relationships or invoke behavior that should have been blocked, eventually causing arbitrary Python code to run inside the process rendering the template. Successful exploitation gives the attacker the privileges, network access, filesystem access, environment variables, secrets, and service identity available to that process.
How to fix it
Upgrade Jinja to version 3.1.6 or later wherever untrusted or semi-trusted templates may be rendered. For source-based deployments of `pallets/jinja`, ensure the fix commit `15206881c006c79667fe5154fe80c01c65410679` or a later release is present. Regenerate and redeploy dependency lockfiles, containers, serverless packages, virtual environments, and base images so the patched library is actually used at runtime. If immediate upgrade is not possible, disable execution of user-controlled Jinja templates, restrict template editing to fully trusted administrators, block or remove access to dangerous filters such as `attr` in untrusted contexts, and isolate template rendering in a low-privilege sandboxed worker with no secrets, minimal filesystem access, and restricted outbound network access. Do not rely solely on Jinja's sandbox as a security boundary for hostile template authors.
How to confirm the fix worked
Confirm the installed Jinja package version is 3.1.6 or later using package inventory, lockfiles, SBOMs, container scans, and runtime checks such as `python -c "import jinja2; print(jinja2.__version__)"`. For source checkouts, verify that commit `15206881c006c79667fe5154fe80c01c65410679` or a descendant is present. Review application functionality to determine whether users can create or modify templates, not just template variables. In staging, verify that previously accepted templates using `|attr('format')` or equivalent access patterns no longer bypass sandbox attribute checks. Confirm deployed artifacts match the patched dependency version, because build-time lockfiles and runtime images often diverge.
Typical attack path
- Identify an application feature that accepts user-controlled Jinja template content rather than only simple variables.
- Confirm that the template is rendered server-side using Jinja's sandboxed environment and that the installed Jinja version is earlier than 3.1.6.
- Submit a probing template to verify expression evaluation and filter support, especially use of the `attr` filter.
- Craft a sandbox-escape template that abuses `|attr` to access the native string `format` method and bypass protected attribute lookup.
- Use the escaped execution context to run Python code within the application process.
- Read sensitive local files, environment variables, application secrets, or cloud credentials available to the process.
- Optionally execute system commands, establish persistence, or pivot to internal services reachable from the compromised application.
How to detect it
Investigate any application that rendered user-controlled Jinja templates while using a Jinja version earlier than 3.1.6. Useful log sources include application access logs, API audit logs for template creation or modification, database or object-storage records containing saved templates, template-rendering error logs, Python exception traces, container stdout/stderr, EDR process telemetry, web server logs, and outbound network connection logs from template-rendering services. Look for templates or requests containing `|attr` combined with `format`, Python dunder-style attribute traversal, attempts to reach globals or builtins, and suspicious command execution following template rendering. Also review for unexpected child processes spawned by Python application workers, unusual reads of environment files or credential files, and outbound callbacks from services that normally do not initiate external connections. Because there are no named threat actors, KEV listing, or confirmed ransomware use in the provided intelligence, detection should focus on generic sandbox-escape behavior and post-exploitation artifacts rather than actor-specific infrastructure.
- |attr('format')
- |attr("format")
- |attr(`format`)
- attr('format')
- attr("format")
- |attr('format_map')
- |attr("format_map")
- __class__
- __mro__
- __subclasses__
- __globals__
- __builtins__
- __import__
- os.popen
- subprocess.Popen
- subprocess.call
- subprocess.run
- eval(
- exec(
- open('/etc/passwd'
- open("/etc/passwd"
- /etc/passwd
- /proc/self/environ
- /root/.ssh/id_rsa
- /home/*/.ssh/id_rsa
- aws_access_key_id
- AWS_ACCESS_KEY_ID
- Traceback (most recent call last)
- jinja2.exceptions.SecurityError
- jinja2.sandbox
- SandboxedEnvironment
What your security team should do
- Inventory all Python applications, automation tools, document-generation systems, notification systems, and internal platforms that depend on Jinja or Jinja2.
- Prioritize remediation for systems that render user-supplied, tenant-supplied, plugin-supplied, imported, or administrator-configurable templates.
- Upgrade affected deployments to Jinja 3.1.6 or later, or to a source revision containing commit `15206881c006c79667fe5154fe80c01c65410679`.
- Treat any service that allowed untrusted template editing while running a vulnerable Jinja version as potentially compromised until reviewed.
- Search historical logs, stored templates, audit events, and application errors for suspicious use of the `attr` filter, string formatting access, Python object traversal, and command-execution artifacts.
- Reduce blast radius by running template rendering with least privilege, no long-lived secrets in the environment, restricted filesystem permissions, and constrained outbound network access.
- Add secure design review requirements for any feature that executes user-controlled templates; prefer safe template variables or constrained DSLs instead of general-purpose template execution.
The record
Jinja is an extensible templating engine. Prior to 3.1.6, an oversight in how the Jinja sandboxed environment interacts with the |attr filter allows an attacker that controls the content of a template to execute arbitrary Python code. To exploit the vulnerability, an attacker needs to control the content of a template. Whether that is the case depends on the type of application using Jinja. This vulnerability impacts users of applications which execute untrusted templates. Jinja's sandbox does catch calls to str.format and ensures they don't escape the sandbox. However, it's possible to use the |attr filter to get a reference to a string's plain format method, bypassing the sandbox. After the fix, the |attr filter no longer bypasses the environment's attribute lookup. This vulnerability is fixed in 3.1.6.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| PyPI | jinja2 | 0 | 3.1.6 |
| AlmaLinux:10 | python3-jinja2 | 0 | 3.1.6-1.el10_0 |
| AlmaLinux:10 | python3-jinja2+i18n | 0 | 3.1.6-1.el10_0 |
| AlmaLinux:9 | python3-jinja2 | 0 | 2.11.3-8.el9_5 |
| Alpine:v3.18 | py3-jinja2 | 0 | 3.1.6-r0 |
| Alpine:v3.19 | py3-jinja2 | 0 | 3.1.6-r0 |
| Alpine:v3.20 | py3-jinja2 | 0 | 3.1.6-r0 |
| Alpine:v3.21 | py3-jinja2 | 0 | 3.1.6-r0 |
| Alpine:v3.22 | py3-jinja2 | 0 | 3.1.6-r0 |
| Chainguard | checkov | 0 | 3.2.432-r0 |
| Chainguard | grafana-oncall | 0 | 1.15.2-r1 |
| Chainguard | grafana-oncall-compat | 0 | 1.15.2-r1 |
| Chainguard | jupyter-base-notebook | 0 | 7.3.2-r2 |
| Chainguard | jupyter-base-notebook-oci-entrypoint | 0 | 0.0.0_git20251013-r0 |
| Chainguard | nemo | 0 | 1.23.0-r11 |
| Chainguard | py3.10-torchvision-cuda-11.8 | 0 | 0.18.1-r3 |
| Chainguard | py3.10-torchvision-cuda-12.3 | 0 | 0.18.1-r4 |
| Chainguard | py3.10-vllm-cuda-11.8 | 0 | 0.7.3-r1 |
| Chainguard | py3.10-vllm-cuda-12.6 | 0 | 0.7.3-r1 |
| Chainguard | py3.10-wheels-torchvision-cuda-11.8 | 0 | 0.18.1-r3 |
| Chainguard | py3.10-wheels-torchvision-cuda-12.3 | 0 | 0.18.1-r4 |
| Chainguard | py3.10-wheels-vllm-cuda-11.8 | 0 | 0.7.3-r1 |
| Chainguard | py3.11-text-generation-inference | 0 | 3.3.6-r0 |
| Chainguard | py3.11-text-generation-inference | 0 | 3.3.6-r3 |
| Chainguard | py3.11-torchaudio-cuda-12.3 | 0 | 2.3.1-r1 |
| Chainguard | py3.11-torchvision-cuda-11.8 | 0 | 0.18.1-r4 |
| Chainguard | py3.11-torchvision-cuda-12.3 | 0 | 0.18.1-r4 |
| Chainguard | py3.11-wheels-torchaudio-cuda-12.3 | 0 | 2.3.1-r1 |
| Chainguard | py3.11-wheels-torchvision-cuda-11.8 | 0 | 0.18.1-r4 |
| Chainguard | py3.11-wheels-torchvision-cuda-12.3 | 0 | 0.18.1-r4 |
| Chainguard | py3.12-torchvision-cuda-12.3 | 0 | 0.18.1-r2 |
| Chainguard | py3.12-wheels-torchvision-cuda-11.8 | 0 | 0.18.1-r2 |
| Chainguard | py3.12-wheels-torchvision-cuda-12.3 | 0 | 0.18.1-r2 |
| Chainguard | py3.9-torchvision-cuda-11.8 | 0 | 0.18.1-r2 |
| Chainguard | py3.9-torchvision-cuda-12.3 | 0 | 0.18.1-r2 |
| Chainguard | py3.9-wheels-torchvision-cuda-11.8 | 0 | 0.18.1-r2 |
| Chainguard | py3.9-wheels-torchvision-cuda-12.3 | 0 | 0.18.1-r2 |
| Chainguard | reflex | 0 | 0.7.2-r0 |
| Chainguard | tensorflow-cpu-jupyter | 0 | 2.18.0-r1 |
| Chainguard | tensorflow-gpu-jupyter-2.18 | 0 | 2.18.0-r1 |
| Chainguard | text-generation-inference | 0 | 3.3.6-r0 |
| Chainguard | text-generation-inference | 0 | 3.3.6-r3 |
| Chainguard | text-generation-inference-compat | 0 | 3.3.6-r0 |
| Chainguard | text-generation-inference-compat | 0 | 3.3.6-r3 |
| Debian:11 | jinja2 | 0 | No fix |
| Debian:11 | jinja2 | 0 | 2.11.3-1+deb11u3 |
| Debian:12 | jinja2 | 0 | No fix |
| Debian:13 | jinja2 | 0 | No fix |
| Debian:14 | jinja2 | 0 | 3.1.6-1 |
| Mageia:9 | python-jinja2 | 0 | 3.1.6-1.mga9 |
| SUSE:Linux Enterprise Micro 5.1 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Micro 5.2 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Micro 5.3 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Micro 5.4 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Micro 5.5 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Module for Basesystem 15 SP6 | python-Jinja2 | 0 | 2.10.1-150000.3.21.1 |
| SUSE:Linux Enterprise Module for Public Cloud 15 SP4 | python-Jinja2 | 0 | 3.1.2-150400.12.14.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP6 | python-Jinja2 | 0 | 3.1.2-150400.12.14.1 |
| Wolfi | checkov | 0 | 3.2.432-r0 |
| Wolfi | grafana-oncall | 0 | 1.15.2-r1 |
| Wolfi | grafana-oncall-compat | 0 | 1.15.2-r1 |
| Wolfi | jupyter-base-notebook | 0 | 7.3.2-r2 |
| Wolfi | jupyter-base-notebook-oci-entrypoint | 0 | 0.0.0_git20251013-r0 |
| Wolfi | reflex | 0 | 0.7.2-r0 |
| Wolfi | tensorflow-cpu-jupyter | 0 | 2.18.0-r1 |
| openSUSE:Leap 15.6 | python-Jinja2 | 0 | 3.1.2-150400.12.14.1 |
Related vulnerabilities
- CVE-2024-56201 Jinja has a sandbox breakout through malicious filenames Also affects jinja2
- CVE-2024-56326 Jinja has a sandbox breakout through indirect reference to format method Also affects jinja2
- CVE-2024-34064 Jinja is an extensible templating engine. Also affects jinja2
- CVE-2026-34519 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Also affects checkov
- CVE-2026-34525 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Also affects checkov
- CVE-2026-34518 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Also affects checkov
- CVE-2026-34520 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Also affects checkov
- CVE-2026-34514 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Also affects checkov