CVE-2026-86066
Executive Summary
CVE-2026-86066 is a Cross-Site Request Forgery (CSRF) vulnerability in Horilla, an open-source HR and CRM application, affecting all versions prior to 2.0.0. The approve_validate_attendance_request endpoint at /attendance/approve-validate-attendance-request/ performs a state-changing attendance approval via HTTP GET, bypassing Django's CSRF protections, which apply only to unsafe methods. An unauthenticated attacker can lure a logged-in manager holding attendance.change_attendance permission into a crafted request that silently approves attendance records under the victim's session and identity.
The impact is integrity-focused: unauthorized, fraudulent approval of attendance requests, with the approval misattributed to the victim manager in the audit trail. No public proof-of-concept, nuclei template, or exploit code is currently available, and the vulnerability is not listed in CISA KEV.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The core defect is a violation of two foundational web security principles combined: the use of HTTP GET for a state-changing operation, and the consequence that Django's built-in CSRF middleware does not enforce token validation on GET requests.
Per the NVD description, the function approve_validate_attendance_request at the URL path /attendance/approve-validate-attendance-request/ mutates several persistence-layer fields — specifically attendance_validated, is_validate_request_approved, approved_by, and "related pending-request state" — and then calls attendance.save() to commit those changes to the database. Because this state transition is reachable through an HTTP GET request, Django's CSRF framework, which by design validates only unsafe methods (POST, PUT, PATCH, DELETE), provides no protection. The attacker therefore does not need to obtain or predict a CSRF token.
A secondary and critical facilitator is the session cookie's SameSite attribute. The description states the victim's session cookie is SameSite=Lax. Under the Lax policy, browsers do not attach cookies to most cross-site requests, but they do attach them to top-level navigations performed with safe methods such as GET. This means a simple top-level GET navigation initiated from an attacker-controlled page will carry the victim manager's session cookie to the Horilla origin, authenticating the forged request transparently.
The attacker is unauthenticated — they need no Horilla account and no knowledge of the victim's credentials. The only privilege requirement is that the victim be a logged-in manager who possesses the attendance.change_attendance permission. The description explicitly notes that the request "carries the manager's SameSite=Lax session cookie," and the resulting approval is "attributed to the victim in the audit trail," because the application records approved_by based on the authenticated session rather than any independent authorization check at the request layer.
The attack surface is the attendance approval workflow of the Horilla HR module. There is no injection, memory-corruption, or authentication-bypass primitive here; the vulnerability class is purely authorization-binding failure (state change without CSRF token enforcement). No further code-level details (view decorator behavior, URL routing specifics beyond the one provided path, or models beyond the named fields) are available from the supplied data, and none should be assumed.
Exploitation Scenarios
No public PoC is available; the attack chain below is inferred strictly from the described vulnerability class (CSRF via state-changing GET) and the technical facts provided.
Reconnaissance / target identification. The attacker identifies Horilla instances prior to 2.0.0 exposed to users, for example via a web search or by fingerprinting pages that render Horilla's HR/CRM interface. The attacker only needs to confirm the instance is running a vulnerable version and uses the
/attendance/module.Victim condition establishment. The attacker identifies or waits for a scenario where a manager holding the
attendance.change_attendancepermission is logged in. This is a normal operational state for HR/line managers who routinely approve attendance. TheSameSite=Laxsession cookie is already present in the victim's browser.Triggering the flaw class. The attacker constructs a request to the vulnerable GET endpoint
https://<horilla-host>/attendance/approve-validate-attendance-request/with whatever parameters the application expects to identify the attendance record(s) to approve. Because the state change is served over GET, no CSRF token is generated or checked. The attacker embeds this URL into a top-level navigation — for example an<a href>link, a page redirect, or an image/link that the victim clicks — delivered by email, chat, or a malicious site.Session cookie carriage and execution. When the victim performs the top-level navigation, the browser applies the
SameSite=Laxpolicy and attaches the manager's session cookie to the GET request. Horilla authenticates the request as the victim manager, executesapprove_validate_attendance_request, setsattendance_validatedandis_validate_request_approved, records the victim inapproved_by, updates the related pending-request state, and callsattendance.save(). The approval is committed without the victim's knowledge.Post-exploitation impact. The attacker has achieved unauthorized approval of attendance records with no direct account access and no malware. Because
approved_bystores the victim's identity, the fraudulent approval is attributed to the victim manager — enabling loss of audit integrity, potential internal-fraud scenarios (e.g., approving manipulated or unauthorized attendance), and reputational or disciplinary exposure for the falsely-attributed manager.
Impact Assessment
CVE-2026-86066 is an integrity-only vulnerability. No confidentiality impact (attendance data is not disclosed to the attacker) and no availability impact (the application continues to function) are described. The primary impacts are:
- Audit-trail corruption. Because
approved_byis populated with the victim's identity, the record of who authorized the attendance is factually false. This compromises the evidentiary value of attendance and payroll-adjacent records. - Transactional fraud enablement. Unauthorized approvals may directly affect worked-hours records, which in mature HR deployments feed payroll, overtime, and compliance calculations. The blast radius is therefore the downstream systems and processes consuming approved attendance — not the Horilla database alone.
- Reputational and compliance exposure. Falsely attributed approvals can implicate innocent managers in disciplinary investigations, undermine labor-law compliance evidence, and complicate HR dispute resolution.
- Blast radius. Limited to organizations running Horilla < 2.0.0 with the attendance approval workflow in active use. Impact scales with the number of managers holding
attendance.change_attendanceand the number of pending approval requests at any time.
CVSS mapping. The vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N reflects: network reachable (AV:N), no special conditions (AC:L), attacker unauthenticated (PR:N), victim must perform a user action such as a navigation (UI:R), scope unchanged (S:U), no confidentiality loss (C:N), partial/low integrity loss (I:L, limited to approval state), and no availability loss (A:N). Note: no official CVSS score was provided in the source data, so no numeric score is asserted.
Detection Guidance
Sigma Rule
title: Horilla Attendance Approval via GET CSRF (CVE-2026-86066)
id: 3d9c1f2a-77b4-4e6a-9c1e-9horilla86066
status: experimental
description: Detects GET requests to the Horilla attendance approval endpoint, which performs a state change and is exploitable for CSRF prior to Horilla 2.0.0.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-86066
author: valtersit.com Threat Intelligence
logsource:
category: webserver
product: generic
detection:
selection_method:
cs-method: 'GET'
selection_uri:
cs-uri-stem|contains: '/attendance/approve-validate-attendance-request/'
condition: selection_method and selection_uri
falsepositives:
- Legitimate application UI calls if Horilla front-end uses GET internally (verify against 2.0.0 behavior)
level: medium
YARA Rule
rule CVE_2026_86066_Horilla_CSRF_URI
{
meta:
description = "Detects the vulnerable Horilla attendance approval URI in logs, traffic captures, or proxied artifacts (CVE-2026-86066)"
author = "valtersit.com Threat Intelligence"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-86066"
date = "2026-01-01"
severity = "medium"
strings:
$uri = "/attendance/approve-validate-attendance-request/" ascii wide nocase
$f1 = "attendance_validated" ascii wide
$f2 = "is_validate_request_approved" ascii wide
$f3 = "approved_by" ascii wide
condition:
$uri or (2 of ($f*))
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-86066 Horilla Attendance CSRF Approval via GET"; flow:established,to_server; http.method; content:"GET"; http.uri; content:"/attendance/approve-validate-attendance-request/"; nocase; classtype:web-application-attack; reference:cve,2026-86066; sid:202686066; rev:1;)
Elastic Detection
sequence by source.ip with maxspan=5m
[network where network.protocol == "http" and http.request.method == "GET" and
url.path : "/attendance/approve-validate-attendance-request/*"]
Note: In environments where Horilla is fronted by a reverse proxy, adapt the EQL to target the proxy access-log index and the url.path field accordingly. A single matching event followed by a subsequent state-change confirmation on the same attendance record can corroborate exploitation.
Splunk SPL Query
index=web OR index=proxy
| search method=GET uri_path="/attendance/approve-validate-attendance-request/*"
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, uri_path, user_agent, referer
| where count >= 1
| sort - count
To highlight cross-site referrers (a strong CSRF signal), add:
| eval suspicious=if(match(referer,"(?i)^https?://(?!<your-horilla-domain>)"),1,0)
| where suspicious=1
Wazuh OSSEC Rule
<group name="web,horilla,cve-2026-86066,">
<rule id="100860" level="10">
<decoded_as>web-accesslog</decoded_as>
<if_sid>31100</if_sid>
<url>/attendance/approve-validate-attendance-request/</url>
<method>GET</method>
<description>CVE-2026-86066: Horilla attendance approval requested via GET (CSRF attempt)</description>
<mitre>
<id>T1204.001</id>
</mitre>
<group>cve_2026_86066,csrf,web_attack,</group>
</rule>
<rule id="100861" level="12">
<if_sid>100860</if_sid>
<referer>^https?://</referer>
<description>CVE-2026-86066: Horilla attendance GET approval with external referrer (probable CSRF)</description>
<group>cve_2026_86066,csrf,high_confidence,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source). The NVD description states the issue is fixed in version 2.0.0, but no tracked source has supplied a patch URL, commit hash, or vendor advisory link. The guidance below reflects that gap.
Immediate mitigations (compensating controls).
- Restrict network access to the Horilla web interface to trusted internal ranges or a VPN, reducing the ability of external attacker pages to reach victim managers in a session-carrying top-level navigation.
- At the reverse proxy / WAF layer, block or challenge
GETrequests to/attendance/approve-validate-attendance-request/that carry an external or absentReferer/Originheader. Note that some browsers suppressReferer; do not rely on it as a sole control. - Consider short session timeouts and re-authentication for approval workflows to narrow the exploitation window, though this does not close it.
- Educate managers with
attendance.change_attendancenot to click unsolicited links while logged into Horilla.
Patch / upgrade steps.
- Upgrade Horilla to version 2.0.0 or later, the version identified as containing the fix. Validate by reviewing the release notes and confirming the approval action no longer executes via GET and requires a CSRF token.
- Because no tracked patch reference exists, verify the fix directly: after upgrade, confirm the endpoint rejects state changes on GET and that the approval UI issues a POST (or equivalent) with a valid CSRF token.
Long-term hardening.
- Enforce Django-native CSRF protection on all state-changing views, and never perform mutations on GET. Adopt
django.views.decorators.http.require_POST(or equivalent method restriction) for approval and similar workflows. - Set session cookies to
SameSite=Strictwhere feasible to eliminate the top-level-navigation cookie carriage thatLaxpermits. - Add Origin/Referer validation middleware for privileged, state-changing endpoints as defense in depth.
- Codify REST/HTTP semantics in code review: GET must be idempotent and side-effect free.
- Enforce Django-native CSRF protection on all state-changing views, and never perform mutations on GET. Adopt
References
- NVD — CVE-2026-86066: https://nvd.nist.gov/vuln/detail/CVE-2026-86066
- Horilla project (vendor/product source): Horilla HR and CRM software — consult the project's official release channel for the 2.0.0 release notes confirming the fix.
- CWE-352 — Cross-Site Request Forgery: https://cwe.mitre.org/data/definitions/352.html
- OWASP — Cross-Site Request Forgery Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
- FIRST — EPSS (not yet scored at time of writing): https://www.first.org/epss/
Exploit-in-the-wild / threat actor evidence: None observed. CVE-2026-86066 is not listed in CISA KEV, no public proof-of-concept, nuclei template, or exploit code is available, and no named threat actor campaigns have been associated with this CVE in the supplied intelligence data. The attack is a straightforward, low-sophistication CSRF technique typical of opportunistic, targeted, or insider-adjacent abuse rather than a nation-state or ransomware TTP.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.