CVE-2026-38979
Executive Summary
CVE-2026-38979 is a clickjacking vulnerability in ajenti, a server administration control panel, affecting all versions through v2.2.13. The vulnerability stems from missing anti-framing HTTP security headers (X-Frame-Options and Content-Security-Policy frame-ancestors) in the core HTTP response path (ajenti-core/aj/http.py). An attacker can embed legitimate ajenti login or administrative pages in a malicious iframe, tricking users into performing unintended actions within their authenticated session. This is a medium-severity UI redress attack vector that can lead to configuration tampering, credential harvesting via credential-free authenticated sessions, or full administrative takeover when combined with social engineering.
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 vulnerability resides in ajenti-core/aj/http.py, the core HTTP response handling module. In this file, the server initializes an empty header list at the start of each HTTP response cycle. Handler-added headers are forwarded verbatim without modification, and responses are finalized through Python's WSGI start_response() callable. Critically, the response path never injects security headers such as X-Frame-Options: DENY or Content-Security-Policy: frame-ancestors 'none'.
The practical effect is that all ajenti-generated HTTP responses — including the login page and the authenticated administrative interface — lack frame-busting protections. Modern browsers enforce framing restrictions only when explicitly instructed via these headers; without them, any third-party website can embed ajenti's UI within an <iframe> tag.
The attack surface is broad: the login page, individual plugin panels, service management views, file manager, user management, package installer, and configuration editors all render without anti-framing headers. The vulnerability is server-side (the header omission), but exploitation requires client-side interaction. Since ajenti typically runs on management ports (8000/8001 default) or HTTPS, and often manages hosts with root privileges, the potential for abuse is significant.
Session handling in ajenti relies on cookie-based authentication. When an administrator is logged into ajenti, cookies are automatically sent with requests to the ajenti domain. If an attacker can trick an authenticated administrator into interacting with an embedded ajenti iframe, the session cookie is presented to the server, granting the attacker the ability to drive authenticated actions through the victim's browser.
Exploitation Scenarios
The attack chain for CVE-2026-38979 proceeds as follows:
Reconnaissance: The attacker identifies target ajenti installations via internet-wide scanning (Shodan, Masscan, Censys) for HTTP responses containing the
Server: ajentiheader or distinctive login page fingerprint. They verify the version is ≤ 2.2.13. The attacker also identifies the ajenti URL scheme (e.g.,https://admin.example.com:8000/).Malicious Page Setup: The attacker registers a domain (e.g.,
ajenti-manager.example.net) and hosts a crafted HTML page containing a full-page transparent iframe pointing to the victim's ajenti login/management URL. The iframe is overlaid on a decoy UI (e.g., a false "software update" dialog) to induce interaction:
<iframe src="https://target-ajenti:8000/mgr/login"
style="position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;border:none;">
</iframe>
Weaponization: The attacker lures the administrator to the malicious page. If not yet authenticated, the admin is tricked into typing credentials into the embedded login form (credential phishing). If already authenticated in another tab, the iframe loads the authenticated dashboard, and the victim's clicks are transparently absorbed by the iframe.
Triggering Actions: The attacker aligns UI elements in the decoy layer with actionable ajenti buttons (e.g., "Save" on a config page, "Restart Service", "Update Package"). The victim's click triggers the corresponding ajenti action with their elevated privileges.
Post-Exploitation: Using CSRF-like interactions driven by the victim's clicks, the attacker can modify firewall rules, add a rogue admin user (via the user management plugin), install malicious packages (via the package manager plugin), or change SSH keys in the file manager. A fully weaponized attack could result in complete server compromise with root privileges on the managed host.
The attack requires user interaction (a click) and is delivered via social engineering. The vulnerability is not remotely exploitable without human interaction, but given legitimate administrators routinely respond to update prompts, click-through rates in real campaigns are non-trivial.
Impact Assessment
CVSS scoring is N/A, but the severity qualitative assessment is Medium. The vulnerability enables UI redressing, which combines with existing session authentication to provide an attacker with a user-assisted route to high-privilege actions. The confidentiality, integrity, and availability impacts are High should the attack succeed, because ajenti controls both the administrative interface and the underlying server (typically run as root).
- Business Impact: Server configuration changes, data exfiltration (file manager access), service disruption, or complete server takeover — all triggered by a single click from an administrator.
- Affected Systems: All ajenti deployments on versions ≤ 2.2.13. However, note that the project appears dormant (last public release 2.2.13), meaning no official patched version is confirmed in the NVD record. Patch confidence is 2/4 (a single source, OSV, claims a patch exists, but it is not independently confirmed).
- Blast Radius: When ajenti is deployed on a dedicated management server, the blast radius includes every host managed via the ajenti "Slaves" feature. In small deployments, the ajenti host itself is the target.
Detection Guidance
Sigma Rule
title: Ajenti Admin Page Referer from External Domain (Possible Clickjacking)
id: 7f63f5a9-4c0e-4b5a-9c1e-2a86ef3c9f12
status: experimental
description: Detects HTTP requests to ajenti management pages carrying a Referer header from an external domain, indicating possible iframe embedding for clickjacking.
date: 2026/01/15
tags:
- attack.t1190
logsource:
category: web
product: apache
definition: 'Requires web server or reverse proxy logs logging the Referer header.'
detection:
selection:
uri_path:
- '/mgr/*'
- '/api/sys/*'
http_referer|contains:
- 'http://'
- 'https://'
filter:
http_referer|contains:
- 'target-ajenti-hostname'
condition: selection and not filter
level: medium
falsepositives:
- Legitimate bookmarks opening ajenti from a local file (rare)
- Admin portals proxying ajenti via iframe for internal convenience
YARA Rule
rule Ajenti_Clickjacking_Exploit_Page {
meta:
author = "ValtersIT Threat Intel"
description = "Detects malicious HTML pages containing transparent iframes targeting ajenti administrative endpoints."
date = "2026-01-15"
reference = "CVE-2026-38979"
score = 60
strings:
$s1 = "<iframe" nocase
$s2 = "ajenti" nocase
$s3 = "/mgr/" nocase
$s4 = "opacity:0" nocase
$s5 = "z-index" nocase
$s6 = "position:absolute" nocase
$s7 = "style=" nocase
$s8 = "top:0" nocase
$s9 = "left:0" nocase
$s10 = "width:100%" nocase
$s11 = "height:100%" nocase
condition:
all of ($s1, $s2, $s3) and 3 of ($s4, $s5, $s6, $s7, $s8, $s9, $s10, $s11)
}
Suricata IDS Rule
alert http any any -> $HOME_NET any (msg:"CVE-2026-38979 - Ajenti Admin UI Framable (Clickjacking) - External Referer to /mgr/"; flow:established,to_server; http.uri; content:"/mgr/"; http.referer; content:!"REFERER_INTERNAL" ; classtype:web-application-attack; sid:50038977; rev:1;)
Note: This rule requires tailoring the REFERER_INTERNAL signature/PCRE to match the internal admin hostname.
Elastic Detection
POST /_security/roles -d '{
"indices": [
{
"names": ["filebeat-*", "logs-*"],
"privileges": ["read"],
"query": "must contain referer"
}
]
}'
// [OPTIONAL] Placeholder — detection bodies follow:
// EQL query on index filebeat-*:
sequence by source.ip
[ any where http.request.referer != "" and url.path:("/mgr/*")
and http.request.referer:("http*")
and not http.request.referer:("*.internal.*") ]
(Concrete EQL:)
any where http.request.referer : "http*" and
url.path : "/mgr/*" and
not http.request.referer : "*.internal.*"
Splunk SPL Query
index=web sourcetype=access_combined uri_path="/mgr/*"
| rex field=referer "^https?://(?<referer_host>[^/]+)"
| search NOT referer_host=*
| eval internal_domain = if(match(referer_host, "^((10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.|.*internal.*)"), "true", "false")
| search internal_domain = "false"
| stats count by src_ip, dest_host, uri_path, referer
| where count >= 1
Wazuh OSSEC Rule
<rule id="100389" level="12">
<decoded>Apache:ACCESS</decoded>
<match>"/mgr/</match>
<regex> ^(.*) (?:referer|Referer): (http|https)://(?!(?:127\.|10\.|192\.168\.|.*internal.*)) </regex>
<description>CVE-2026-38979 - Ajenti Admin UI accessed with external Referer (possible clickjacking)</description>
<group>web_application_attack,</group>
</rule>
Mitigation & Patch Guidance
Patch confidence: 2/4 (CLAIMED) — a single source (OSV) claims a patch exists, but it is not independently confirmed.
Immediate Mitigations (no patch required):
- Reverse Proxy Header Injection: Place ajenti behind nginx, Apache, or HAProxy and enforce
X-Frame-Options: DENYandContent-Security-Policy: frame-ancestors 'none'on all responses. Example nginx snippet:proxy_set_header X-Frame-Options "DENY"; proxy_set_header Content-Security-Policy "frame-ancestors 'none'"; add_header X-Frame-Options "DENY" always; add_header Content-Security-Policy "frame-ancestors 'none'" always; - Network Restriction: Bind ajenti to a management-only network (not public internet) via firewall allow-list for administrative IPs.
- Browser Hardening: Use a browser security extension (e.g., uBlock Origin, NoScript) on admin workstations to block 3rd-party iframes.
- Session Policies: Implement short session timeouts; enforce re-auth for high-impact actions (user creation, package install).
- Reverse Proxy Header Injection: Place ajenti behind nginx, Apache, or HAProxy and enforce
Patch/Upgrade Steps:
- Check the OSV advisory for a patched release. If a patched version exists, upgrade to it. Currently, the latest public version is v2.2.13; verify whether a newer commit or fork (e.g., community-maintained ajenti2 fork) has added security headers.
- Validate patch authenticity: install via package manager (
pip install --upgrade ajenti2— CORRECTING PACKAGE MANAGER: Python package → use pip/conda/poetry). If no fixed release exists, rely on reverse-proxy mitigation as the de facto patch.
Long-Term Hardening:
- Consider migrating to an actively maintained admin panel (e.g., Cockpit, Webmin) if no official patch materializes.
- Add
X-Frame-OptionsandCSPheaders as default in the application code atajenti-core/aj/http.pyand rebuild the package from source. - Establish a CVE monitoring workflow for ajenti and sign up for OSV vulnerability notifications.
References
- NVD — CVE-2026-38979: https://nvd.nist.gov/vuln/detail/CVE-2026-38979
- OSV Advisory (patch claim): https://osv.dev/vulnerability/CVE-2026-38979
- Ajenti Official Project: https://ajenti.org/
- OWASP Clickjacking Defense Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- CISA KEV Catalog (CVE not listed — this entry is not known to be exploited in the wild as of this report): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Additional threat intelligence: As of this report, there are no known threat actor campaigns exploiting CVE-2026-38979 in the wild. The EPSS score is 0.00200 (10.0th percentile of exploited CVEs), indicating low active exploitation likelihood. Public PoC code is not available; however, clickjacking techniques against admin UIs are well-documented, and an attacker with sufficient capability could trivially weaponize the flaw.