Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessSubmit attacker content for indexing
-
DeliveryEmbed Python expression in aliased field
-
ExploitDocument stored in Elasticsearch under alias
-
ExecutionTrigger search returning the document
-
Persisteval() in _to_python runs payload
-
ImpactArbitrary code execution in Django process
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Eval input sanitization
MITRE ATT&CK
1 technique across 1 tactic: Execution The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Requires the django-haystack Elasticsearch backend (not Solr/Whoosh/Simple) on a version below 3.4.0, AND at least one SearchField declared with an index_fieldname alias that differs from its logical field name - this alias mismatch is what makes the lookup fall through to _to_python()→eval(). The attacker must be able to get a malicious string indexed into that aliased field (e.g. via user-controlled content the application indexes) and must cause or wait for a search that returns the document. Limiting factors: it is a second-order/stored injection (payload only fires on result deserialization, not at index time), it does not apply to default installations lacking the alias configuration or using non-Elasticsearch backends, and the ability to inject indexed content typically presupposes some application-level access. Input CVSS marks PR:H, so under the provided vector exploitation is treated as authenticated. |
| Impact | Signals conflict sharply and must be weighed carefully. CWE-95 (eval injection) and the vendor GHSA advisory (GHSA-r3hx-x5rh-p9vv) describe unauthenticated-to-authenticated remote code execution via eval() in the Elasticsearch result deserializer, and GHSA self-assigns CVSS 3.1 of 8.5 (High). The input CVSS, however, is a VulDB-assigned CVSS 4.0 vector scoring only 2.0, with PR:H and VC:L/VI:L/VA:L - which materially UNDERSTATES a confirmed RCE sink; this is a clear severity/impact disagreement that defenders should resolve in favor of the vendor advisory. A public exploit exists (GHSA marked as exploit, POC=YES), but there is no CISA KEV listing and no EPSS score was provided, so exploitation status is 'publicly available exploit code exists' - NOT active exploitation. Crucially, exploitation is second-order and config-dependent (see exploitation_conditions), so despite RCE potential this is not a drop-everything internet-wide bug; prioritize it where the Elasticsearch backend is used with field aliases and attacker-influenced indexed content. Net: real and patch-worthy, but the raw VulDB 2.0 score is misleading and the GHSA 8.5 is the more credible impact anchor. |
| Exploit ScenarioDerived | An attacker submits user-generated content (e.g. a profile name or comment) containing a Python expression such as __import__('os').system(...), which the application indexes into Elasticsearch under a SearchField whose index_fieldname alias differs from its logical name. When any subsequent search returns that document, the backend's field lookup misses the alias key and passes the raw value to _to_python()→eval(), executing the payload in the Django process. A public POC/advisory exists, and because the CVSS shows AV:N the delivery and trigger are both achievable remotely. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 05, 2026
Remote code execution in Django Haystack's Elasticsearch backend affects versions up to and including 3.3.0, where an attacker-controlled string reaching the result-deserialization path is passed to eval() inside _to_python() and executed in the Django application process. Exploitation is conditional rather than blanket: it requires the Elasticsearch backend, at least one SearchField declared with an index_fieldname alias that differs from its logical field name, and the ability to get a malicious payload indexed into that aliased field and returned by a subsequent search - a second-order/stored injection rather than a direct request-driven one. Publicly available exploit code exists (a GHSA advisory with source-level walkthrough was published alongside the fix), and the input CVSS vector marks PR:H, so under that vector exploitation is treated as authenticated; there is no CISA KEV entry indicating confirmed active exploitation. The vulnerability is patched in 3.4.0, and the reporting signals conflict sharply and must be weighed carefully: VulDB's CVSS 4.0 base of 2.0 contrasts with the upstream advisory's CVSS 3.1 base of 8.5, reflecting the gap between the mild vector assumptions and the full RCE impact when the alias configuration is present.
RemediationAI
Vendor-released patch: upgrade django-haystack to 3.4.0, which replaces the eval(value) call in _to_python() with ast.literal_eval(value); the specific change is commit eb05f193c9771a68dcc8cfac6674a0d48a52ee9d and the release is tagged v3.4.0 (see https://github.com/django-haystack/django-haystack/commit/eb05f193c9771a68dcc8cfac6674a0d48a52ee9d and https://github.com/django-haystack/django-haystack/releases/tag/v3.4.0). If immediate upgrade is not possible, the most effective compensating control is to eliminate the alias mismatch that makes the sink reachable: remove or align any index_fieldname values so they match the logical field names in index.fields, since without a diverging alias the convert branch is taken and _to_python() is not reached - the trade-off is that alias names are often load-bearing for existing index mappings and may require a reindex or mapping change. Because this is a second-order injection, restricting who can write into the Elasticsearch index (tightening application authorization around content that is indexed, and limiting direct Elasticsearch write access at the network layer) raises the bar for delivering the payload, though it does not remove the flaw and can break legitimate ingestion pipelines. Backporting the one-line ast.literal_eval change into a pinned older release is a viable stopgap for teams that cannot move to 3.4.0, but it leaves the deployment diverging from upstream and should be tracked. Full details and the vendor's own remediation guidance are in GHSA-r3hx-x5rh-p9vv (https://github.com/django-haystack/django-haystack/security/advisories/GHSA-r3hx-x5rh-p9vv).
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The root cause is CWE-95 (Improper Neutralization of Directives in Dynamically Evaluated Code, i.e. Eval Injection). In haystack/backends/elasticsearch_backend.py, _to_python() validates a raw field value by calling eval(value) before any type-safety check, so an attacker-supplied Python expression executes unconditionally. This sink is normally unreachable because _process_results() first checks whether the incoming key exists in index.fields and has a convert method; index.fields is keyed by the logical field name, while Elasticsearch stores and returns the document under the index_fieldname alias. When a SearchField declares an alias that differs from its logical name (for example name stored as name_s), the membership test fails and control falls through to self._to_python(value). The data flow runs from haystack/indexes.py where prepared data is written under field.index_fieldname, through the bulk write into Elasticsearch under that alias key, and back through _process_results() reading raw_result['_source'] - meaning the payload is stored at index time and executes only when a search deserializes the result. The official fix replaces eval(value) with ast.literal_eval(value), confining parsing to Python literals so arbitrary expressions can no longer execute; the affected CPE record cpe:2.3:a:n/a:django-haystack:*:*:*:*:*:*:*:* covers the whole package range below the fix. Non-Elasticsearch backends (Solr, Whoosh, Simple) do not contain this sink, and default installations that do not use diverging index_fieldname aliases are not reachable.
Know when Python gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P
RCE in the app process gives C/I/A:H and S:U; the required non-default index_fieldname alias config makes AC:H, and the need to inject indexed content warrants PR:L.
Primary rating from Vendor (VulDB).
CVSS VectorVendor: VulDB
Lifecycle Timeline
3DescriptionCVE.org
A vulnerability has been found in django-haystack up to 3.3.0. Affected is the function _to_python of the file haystack/backends/elasticsearch_backend.py of the component more_like_this Template Tag Handler. Such manipulation of the argument result_class leads to improper neutralization of directives in dynamically evaluated code. The attack can be launched remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 3.4.0 is able to address this issue. The name of the patch is eb05f193c9771a68dcc8cfac6674a0d48a52ee9d. It is suggested to upgrade the affected component.
Blast Radius
ecosystem impact- 97 pypi packages depend on django-haystack (42 direct, 58 indirect)
Ecosystem-wide dependent count for version 3.4.0.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
Code injection occurs when an application accepts user input and passes it directly into a language interpreter or evaluator without proper sanitization.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
EUVD-2026-92429
GHSA-5x9v-pqqg-p8jg
NVD
CVE.org
EPSS
Vulnrichment
VulDB
Exploit-DB