Skip to main content

Horilla HR CVE-2026-63432

| EUVDEUVD-2026-87363 MEDIUM
Code Injection (CWE-94)
2026-09-25 security-advisories@github.com
6.5
CVSS 3.1 · Vendor: github
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Authenticate to Horilla with low-priv account
  2. Delivery
    Obtain valid CSRF token
  3. Exploit
    Submit mail body with {{ request.user.password }} traversal
  4. Execution
    Server renders template with full request object
  5. Persist
    Harvest password hashes/META/PII
  6. Impact
    Crack hashes offline for account takeover

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Code injection prevention, sandbox exec
MITRE ATT&CK

2 techniques across 2 tactics: Execution, Initial Access

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Requires an authenticated Horilla session (any user) plus a valid CSRF token to reach the mail-preview endpoints /recruitment/get-mail-preview/ and /employee/get-employee-mail-preview in versions 1.0.0 through pre-1.6.0/2.0.0. The attacker supplies a user-controlled mail body containing Django template expressions; exploitation works against default configurations because the vulnerable handlers pass the full request object into the template context. Limiting factors: valid authentication (PR:L) and CSRF token are mandatory, and the Django template sandbox restricts the primitive to attribute reads (information disclosure) rather than code execution, so no arbitrary RCE is achievable.

Impact

The CVSS 3.1 vector (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N = 6.5 Medium) is well-supported by the description and the confirmed patch: a network-reachable, low-complexity flaw requiring only a valid authenticated session, yielding high confidentiality impact (password hashes, PII, request metadata) with no integrity or availability effect. No EPSS score, no CISA KEV listing, and no public POC are provided, so exploitation status is: no public exploit identified at time of analysis. The assigned CWE-94 (Code Injection) and the 'RCE' tag OVERSTATE the issue - the description explicitly notes Django template sandbox restrictions prevent arbitrary code execution, making the true weakness server-side template attribute traversal resulting in information disclosure (CWE-200/CWE-94-limited). This is therefore a genuine but bounded credential-exposure bug, not a code-execution priority; the C:H rating is justified because leaked password hashes enable offline cracking and downstream account compromise. Because exploitation requires authentication (PR:L) and there is no evidence of in-the-wild use, real-world urgency is moderate rather than critical - prioritize behind unauthenticated or actively-exploited issues but patch promptly given credential exposure.

Exploit ScenarioDerived

An attacker with any valid low-privilege Horilla account and a CSRF token submits a mail-preview body containing Django template expressions such as {{ request.user.password }} or {{ request.META }} to /recruitment/get-mail-preview/ or /employee/get-employee-mail-preview. The server renders these against the full request object and returns the leaked password hashes, personal data, and request metadata, which the attacker then cracks offline to escalate. No public POC is referenced, but the commit diff confirms the exact traversal primitive.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Sep 25, 2026

An authenticated user with a valid CSRF token can read Django password hashes, request metadata, and related-user attributes from Horilla HR/CRM mail-preview functionality in versions 1.0.0 through pre-1.6.0 and prior to 2.0.0. The get_mail_preview handlers at /recruitment/get-mail-preview/ and /employee/get-employee-mail-preview render a user-supplied mail body as a Django template while the full request object sits in the template context, so template attribute traversal such as request.user.password or request.META exposes the underlying data; the Django template sandbox limits this to information disclosure rather than code execution. Exploitation requires only a low-privileged authenticated session with a CSRF token (no public exploit identified at time of analysis), and the confidentiality impact is high because the leaked password hashes can be attacked offline or used to identify accounts for follow-on compromise; vendor fixes ship in 1.6.0 and 2.0.0.

RemediationAI

Vendor-released patch: upgrade to Horilla 1.6.0 or 2.0.0 (the latter at https://github.com/horilla/horilla-hr/releases/tag/2.0.0), which introduce sanitize_mail_template_placeholders() to allowlist mail placeholders, strip all {% %} tags, and substitute a sanitized request proxy via build_safe_template_request(), and which also gate the recruitment view behind recruitment.view_candidate with a scoped candidate queryset; the underlying fixes are the commits bd3eed2168b0167f273a8dd7f218f1b37320ac39 and f1ca7cbc6216cb5bf19fc0174f49994ce5ffc2ad. If immediate upgrade is not possible, compensating controls include restricting /recruitment/get-mail-preview/ and /employee/get-employee-mail-preview at the reverse proxy or WAF to trusted HR/superuser roles only (trades away the mail-preview feature for ordinary employees), disabling or unregistering the mail-preview views until patched (loss of template preview functionality but not core HR data), and filtering inbound mail-template bodies for '{{' / '{%' sequences that reference 'request.' or 'META' (blocking the traversal payloads while allowing benign placeholders, at the cost of false positives on legitimate templates). Because password hashes are directly readable, treat any post-1.0.0 deployment that was internet-reachable as potentially compromised: force password resets for affected users, rotate any secrets or tokens present in request.META, and review access logs for suspicious get-mail-preview traffic. The exploitation path mandates a valid session plus a CSRF token, so tightening single-sign-on session issuance does not remove the risk and should not be relied on as a mitigation.

Affected VersionsENISA

horilla-hr 2.0.0-beta.1, < 2.0.0
horilla-hr 1.0.0, < 1.6.0

Affected Packages

euvd horilla_hr_1_0_0 fix: 1.6.0
euvd horilla_hr_2_0_0_beta_1 fix: 2.0.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Horilla is a Django-based HR/CRM application, and the flaw lives in the mail-preview rendering path: the get_mail_preview handlers in recruitment/views/actions.py and employee/not_in_out_dashboard.py passed the entire Django HttpRequest object into the template context and rendered a body the user controls. Because Django's template language resolves dotted attribute lookups (request.user.password, request.META, request.user.employee_get and similar relations) against arbitrary objects, an attacker who can place template expressions in the mail body or in the get_template 'word' parameter can walk from the request object into the ORM model behind request.user and read any attribute reachable that way. The CWE-94 (code injection) classification reflects that user-controlled input reaches template rendering, but Django's template sandbox does not evaluate Python code and blocks attribute access that raises exceptions, so the demonstrated primitive is data exfiltration, not remote code execution - a distinction the exploit tags overstate. The upstream fix is instructive: base/methods.py adds sanitize_mail_template_placeholders(), which strips all {% %} tags and removes any {{ }} expression not present in the MailTemplateForm placeholder allowlist (normalizing whitespace so '{{ instance . get_full_name }}' cannot bypass it), plus build_safe_template_request(), which keeps a 'request' name in the context but replaces it with a SimpleNamespace exposing only method, path, and a safe user proxy limited to id, username, is_authenticated, is_staff, and is_superuser. The recruitment view additionally gained a permission_required('recruitment.view_candidate') decorator and a queryset filter restricting candidate lookups to records the requesting employee manages.

Know when Django 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

Vendor (github) PRIMARY 6.5 MEDIUM
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
vuln.today AI 6.5 MEDIUM

Network-reachable mail-preview endpoint needs an authenticated session (PR:L) with no user interaction; template traversal leaks password hashes/PII (C:H) but cannot modify or disrupt (I:N/A:N).

3.1 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (github).

CVSS VectorVendor: github

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

1
Patch available
Sep 25, 2026 - 23:19 EUVD

DescriptionCVE.org

Horilla is an HR and CRM software. From 1.0.0 until 1.6.0 and 2.0.0, the get_mail_preview handlers in recruitment/views/actions.py and employee/not_in_out_dashboard.py render a user-controlled body at /recruitment/get-mail-preview/ and /employee/get-employee-mail-preview with the full request object in the Django template context. An authenticated user with a valid CSRF token can use template attribute traversal to read request.user.password, request.META, and related-user attributes, exposing password hashes, personal data, and server request metadata. Django template restrictions prevent arbitrary code execution through this primitive, so the demonstrated impact is information disclosure and possible offline password cracking or account compromise. This issue is fixed in versions 1.6.0 and 2.0.0.

Threat Intelligence Overview

EPSS Score
0.3%
Top 78% exploitable
Prevalence
Low
niche open-source HR/CRM application, limited enterprise deployment footprint
Data Quality
7 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GitHub VulDB

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.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact· derived
Medium
Technical Impact
Partial

Priority Score

32
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +32
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Cross-Site Request Forgery exploits the automatic credential inclusion behavior of web browsers.

Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.

Code Injection CRITICAL

Code injection occurs when an application accepts user input and passes it directly into a language interpreter or evaluator without proper sanitization.

More in Django

View all
CVE-2021-23336 MEDIUM POC
5.9 Feb 15

The package python/cpython from 0 and before 3.6.13, from 3.7.0 and before 3.7.10, from 3.8.0 and before 3.8.8, from 3.9

CVE-2017-12794 MEDIUM POC
6.1 Sep 07

In Django 1.10.x before 1.10.8 and 1.11.x before 1.11.5, HTML autoescaping was disabled in a portion of the template for

CVE-2022-34265 CRITICAL POC
9.8 Jul 04

An issue was discovered in Django 3.2 before 3.2.14 and 4.0 before 4.0.6. Rated critical severity (CVSS 9.8), this vulne

CVE-2021-35042 CRITICAL POC
9.8 Jul 02

Django 3.1.x before 3.1.13 and 3.2.x before 3.2.5 allows QuerySet.order_by SQL injection if order_by is untrusted input

CVE-2019-19844 CRITICAL POC
9.8 Dec 18

Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. Rated critical severity (CVSS 9.8

CVE-2026-61594 CRITICAL POC
9.1 Sep 16

An authentication/authorization bypass in the djust Python live-view framework (versions prior to 1.0.7) lets unauthenti

CVE-2026-61599 HIGH POC
8.8 Sep 16

Unauthenticated arbitrary Python module import in djust before 1.0.7 lets any client that can reach the WebSocket or SSE

CVE-2020-9402 HIGH POC
8.8 Mar 05

Django 1.11 before 1.11.29, 2.2 before 2.2.11, and 3.0 before 3.0.4 allows SQL Injection if untrusted data is used as a

CVE-2016-6186 MEDIUM POC
6.1 Aug 05

Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/j

CVE-2026-93456 HIGH POC
8.4 Sep 18

Forged content modification in django-page-cms through 2.0.13 lets unauthenticated remote attackers exploit five CSRF-ex

CVE-2026-61593 HIGH POC
8.1 Sep 16

Cross-site request forgery in djust's Server-Sent-Events transport affects all versions prior to 1.0.7 and allows a cros

CVE-2026-61590 HIGH POC
7.4 Sep 16

Unauthenticated remote attackers can read live Django view and session state and invoke server-side handlers through dju

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy