← Back to Feed CACHED · 2026-09-26 17:56:43 · CACHE_KEY CVE-2026-41948
CVE-2026-41948 · CWE-23 · Disclosed 2026-05-18

Dify Plugin Daemon Path Traversal via Unsanitized Filename Parameter

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Imagine every tenant in your AI apartment building shares one unlocked mailroom, and any stranger who signs up for a free PO box can read everyone's letters

CVE-2026-41948 is a relative path traversal (CWE-23) in Dify's Plugin Daemon internal REST API, affecting all versions through 1.14.1. When a user requests a plugin icon or manages plugin tasks, the Dify backend proxies the request to an internal Plugin Daemon service on port 5002. The filename query parameter in the GET endpoint (/console/api/workspaces/current/plugin/icon) and the identifier path segment in the POST endpoint (/console/api/workspaces/current/plugin/tasks/<task_id>/delete/<identifier>) are injected directly into the internal URL path without any sanitization. By supplying unencoded or URL-encoded dot-dot-slash sequences (e.g., ../../../debug/pprof), an attacker escapes the tenant-scoped asset directory and reaches arbitrary internal Plugin Daemon endpoints — including debug interfaces and other tenants' environments. On Dify Cloud, free self-registration means any attacker can create an account in seconds, making the PR:N CVSS classification operationally accurate. Affected versions span 0 through 1.14.1; the partial fix shipped in v1.14.2 (May 19, 2026) and the complete fix in v1.15.0 (June 25, 2026).

The vendor's CRITICAL / 9.4 rating is well-calibrated and, if anything, undersells the operational impact. The CVSS vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L accurately captures the unauthenticated, low-complexity, no-interaction attack profile. Zafran Labs' *DifyTap* research demonstrated that the path traversal is just one primitive in a four-CVE cluster that enables persistent cross-tenant wiretapping of all AI conversations, document exfiltration, and access to internal debug APIs. With tens of thousands of internet-facing Dify instances, 10 million+ Docker pulls, and enterprise customers like Volvo, Maersk, and Panasonic, the blast radius is substantial. The EPSS score at the 79th percentile reflects growing attacker interest, and a merged Nuclei template means automated scanning is already happening. This is a genuine CRITICAL that deserves immediate attention.

"Cross-tenant AI wiretap via trivial path traversal in Dify Plugin Daemon API — patch now"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Create free Dify account

On Dify Cloud (cloud.dify.ai), the attacker creates a free account with no verification or approval gate. On self-hosted instances with open registration (the default), the same applies. This gives the attacker a valid session token and console API access. For self-hosted instances behind SSO, this step requires a legitimate org credential — a meaningful friction point.
Conditions required:
  • Internet access to the Dify instance
  • Registration endpoint is open (default on Cloud and many self-hosted deployments)
Where this breaks in practice:
  • Self-hosted instances behind SSO/SAML with closed registration block this step
  • Internal-only Dify deployments require network access
STEP 02

Discover target tenant UUID

The attacker needs the UUID of a victim tenant to craft the traversal path. Tenant UUIDs may leak through API responses, URL patterns in shared application links, or error messages. On Dify Cloud, where applications are publicly accessible, tenant identifiers are often embedded in application URLs or can be enumerated.
Conditions required:
  • Valid authenticated session from Step 1
  • Target tenant has at least one publicly accessible application, or UUID is discoverable via API enumeration
Where this breaks in practice:
  • UUIDs are not sequential — pure brute-force is impractical
  • Enterprises with private-only applications reduce UUID leakage
Detection/coverage: Monitor for unusual enumeration patterns against application listing APIs
STEP 03

Craft path traversal via plugin icon endpoint (GET primitive)

The attacker sends a GET request to /console/api/workspaces/current/plugin/icon?tenant_id=<VICTIM_UUID>&filename=../../../debug/pprof. The backend blindly concatenates the filename into the internal Plugin Daemon URL: http://<DAEMON>:5002/plugin/<TENANT_ID>/asset/../../../debug/pprof. The path resolves upward, escaping the asset directory and reaching arbitrary internal endpoints. No additional authentication is checked on the Plugin Daemon side. Nuclei template (v10.4.9, by DhiyaneshGeek) automates this exact check.
Conditions required:
  • Valid session token
  • Knowledge of at least one target tenant UUID
  • Plugin Daemon service running (default in all Dify deployments)
Where this breaks in practice:
  • WAF rules blocking ../ sequences in query parameters will catch naive payloads
  • URL-encoded variants (%2E%2E%2F) may bypass basic WAF rules but are caught by decode-then-inspect WAFs
Detection/coverage: Nuclei template CVE-2026-41948 in v10.4.9; Zafran-published Snort signatures for GET and POST traversal patterns; WAF log analysis for ../ or %2E%2E in filename parameter
STEP 04

Exploit POST primitive for write operations

The attacker sends a POST to /console/api/workspaces/current/plugin/tasks/<TASK_ID>/delete/<IDENTIFIER> where IDENTIFIER contains URL-encoded traversal sequences (%2E%2E). This converts internally to http://<DAEMON>:5002/plugin/<TENANT_ID>/management/install/tasks/<TASK_ID>/delete/../../<target_path>. This primitive enables write-side operations against internal Plugin Daemon APIs, including management endpoints that can modify plugin configurations across tenants.
Conditions required:
  • Valid session token
  • Ability to URL-encode traversal sequences past input filters
Where this breaks in practice:
  • POST requests to management endpoints may trigger anomaly detection in API gateways
  • Some reverse proxies normalize URL encoding before forwarding
Detection/coverage: Snort signatures from Zafran; API gateway logs showing encoded traversal in path segments
STEP 05

Cross-tenant data exfiltration

Combining the GET and POST primitives with CVE-2026-41947 (trace configuration hijack), the attacker redirects all AI conversations and LLM responses from victim applications to an attacker-controlled trace endpoint, creating a persistent exfiltration channel. Even without chaining, the path traversal alone exposes internal debug data (pprof), cross-tenant plugin configurations, and daemon internals. Zafran named this combined attack chain DifyTap — a silent wiretap on enterprise AI workflows.
Conditions required:
  • Successful traversal from Steps 3-4
  • Target tenants actively using Dify applications with sensitive data
Where this breaks in practice:
  • Exfiltration to external trace endpoints may be blocked by egress filtering
  • Debug endpoints may be disabled in hardened production deployments
Detection/coverage: Monitor outbound connections from Plugin Daemon for unexpected trace destinations; audit trace configuration changes across tenants
03 · Compensating Control

1
CRITICAL 9.4→IGNORE 0.0
SEVERITY REDUCED
Upgrade to Dify v1.15.0 immediately — The complete fix shipped in v1.15.0 (June 25, 2026). v1.14.2 is a partial fix — v1.15.0 is required for complete remediation of the entire DifyTap cluster (CVE-2026-41947 through -41950). Under the noisgate mitigation SLA for CRITICAL, deploy within 3 days. For Docker deployments: docker pull langgenius/dify:1.15.0 and update your compose file.
2
CRITICAL 9.4→MEDIUM 5.5
SEVERITY REDUCED
Deploy WAF rules blocking path traversal in Dify plugin endpoints — Add WAF rules that decode-then-inspect the filename query parameter on /console/api/workspaces/current/plugin/icon and the path segments on /console/api/workspaces/current/plugin/tasks/*/delete/* for traversal sequences (../, ..\, %2E%2E, %2e%2e, ..%2F, ..%5C). Zafran published Snort signatures for both GET and POST primitives. This is a stopgap — deploy within 3 days per the noisgate mitigation SLA while scheduling the upgrade.
3
CRITICAL 9.4→HIGH 8.6
SEVERITY REDUCED
Disable open self-registration on self-hosted instances — If you run self-hosted Dify, disable public registration and require SSO/SAML authentication. This elevates the effective PR from None to Low (requires org credential), which reduces the CVSS to ~8.6 and blocks opportunistic internet attackers. This does NOT protect against insider threats or compromised credentials. Deploy within 3 days.
4
CRITICAL 9.4→HIGH 7.5
SEVERITY REDUCED
Place Dify behind a reverse proxy with authentication — If upgrading is delayed, put the Dify console API behind an authenticating reverse proxy (e.g., OAuth2 Proxy, Cloudflare Access, Tailscale Funnel) so that only authorized users can reach the /console/api/ endpoints. This adds a pre-authentication layer that the path traversal cannot bypass. Residual risk remains for authenticated insiders.
5
CRITICAL 9.4→HIGH 8.0
SEVERITY REDUCED
Network-segment the Plugin Daemon — Ensure the Plugin Daemon (port 5002) is not directly accessible from any network other than the Dify API server. In Kubernetes, use NetworkPolicy to restrict ingress to the daemon pod to only the API pod. This doesn't fix the traversal but limits what an attacker can reach if they pivot beyond the daemon's intended endpoints.
What doesn't work
  • Rate limiting on the icon endpoint — the attack requires only a single request to exfiltrate data; rate limiting does not prevent exploitation, only slows enumeration of tenant UUIDs.
  • Disabling the Plugin Daemon — the daemon is a core component required for Dify's plugin ecosystem to function; disabling it breaks plugin functionality entirely and is not a viable compensating control in production.
  • IP allowlisting on Dify Cloud — you do not control Dify Cloud's infrastructure; this control only applies to self-hosted deployments. If you use Dify Cloud, you are dependent on LangGenius applying the patch.
  • Content Security Policy headers — this is a server-side path traversal, not a client-side injection; CSP headers are irrelevant.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild StatusNo confirmed mass exploitation campaigns. Not on CISA KEV as of 2026-09-27. One source (CIRCL) listed KEV status as confirmed September 1, 2026, but this is not corroborated by CISA alerts — treat as unverified. The detailed *DifyTap* research from Zafran Labs provides a roadmap that significantly lowers the exploitation barrier.
Proof-of-ConceptFunctional PoC exists. Zafran Labs' DifyTap writeup contains exact endpoint paths, payload construction, and exploitation methodology — effectively a walkthrough PoC. A Nuclei template by DhiyaneshGeek was merged into nuclei-templates v10.4.9 (September 15, 2026) enabling automated scanning. No standalone exploit repos found on GitHub or pocindex.io at time of assessment.
EPSS0.01892 (1.892%) — 79th percentile. This places it in the top quintile of all scored CVEs for 30-day exploitation probability, consistent with low-complexity network-accessible vulns with published research.
KEV StatusNot listed as of 2026-09-27. User-provided intel confirmed; CISA KEV catalog additions through September 18 do not include this CVE.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L — 9.4 CRITICAL. Network-accessible, no privileges, no interaction, high confidentiality and integrity impact. The PR:N is operationally accurate for Dify Cloud (free self-registration). CVSS 4.0 score is 9.3.
Affected VersionsDify 0 through 1.14.1 (all versions). Partial fix in v1.14.2 (May 19, 2026); complete fix in v1.15.0 (June 25, 2026). Docker images tagged ≤1.14.1 are vulnerable.
Scanning / ExposureZafran identified tens of thousands of internet-facing Dify instances. Dify has 10M+ Docker Hub pulls and 140K+ GitHub stars. Enterprise customers include Volvo, Maersk, Panasonic across 60+ industries. Shodan fingerprinting via http.title:"Dify" or http.favicon.hash will identify exposed instances.
Disclosure TimelineReported December 14, 2025 → Final report April 7, 2026 → Disclosed May 18, 2026 → Partial patch v1.14.2 May 19, 2026 → Full patch v1.15.0 June 25, 2026 → Nuclei template merged September 15, 2026
Researcher / OrgIdo Shani and Gal Zaban of Zafran Labs. Part of the four-CVE *DifyTap* cluster (CVE-2026-41947 through CVE-2026-41950). Reported via HackerOne.
Related CVEsPart of the DifyTap cluster: CVE-2026-41947 (CVSS 9.1, trace config hijack), CVE-2026-41949 (CVSS 7.5, file preview IDOR), CVE-2026-41950 (CVSS 6.5, file attachment IDOR), CVE-2024-5846 (CVSS 8.8, PDFium UAF triggered via preview endpoint). All four should be patched together.

Sources.

  1. GitHub Advisory — GHSA-h666-98mq-949j
  2. Zafran Labs — DifyTap Research
  3. The Hacker News — DifyTap Coverage
  4. Nuclei Template PR — DhiyaneshGeek
  5. Strix AI — CVE-2026-41948 Analysis
  6. CIRCL Vulnerability Lookup
  7. Dify v1.15.0 Release (Full Fix)
  8. OpenCVE — CVE-2026-41948
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.4/10)

Why this verdict

  • Unauthenticated remote access with zero friction: Dify Cloud's free self-registration makes PR:N operationally real — any attacker on the internet can obtain a valid session in seconds. Self-hosted instances with open registration (the default) are equally exposed. This eliminates the single largest friction factor that typically downgrades web application CVEs.
  • Cross-tenant blast radius is fleet-scale data exposure: This is not a single-user or single-application bug. The path traversal breaks tenant isolation on a platform processing AI conversations, uploaded documents, and LLM responses for potentially thousands of organizations on a single instance. Zafran demonstrated persistent wiretapping of *all* conversations across tenants — this is mass data exfiltration, not a confined read.
  • Low complexity with automation available: The attack requires only a GET request with ../ sequences in a query parameter. The Nuclei template (v10.4.9) automates discovery and validation. The Zafran writeup provides a step-by-step exploitation guide. No memory corruption, no race conditions, no exotic prerequisites.
  • Role multiplier: Dify occupies a data-tier / AI orchestration role in enterprise deployments. (a) *Low-value role:* Dev sandbox for testing prompts — limited data exposure. (b) *Typical role:* Internal AI application builder serving business teams — moderate sensitive data (internal docs, customer queries). (c) *High-value role:* Production AI applications processing customer PII, financial data, healthcare queries, or legal documents; RAG systems indexing proprietary knowledge bases; customer-facing chatbots. In high-value deployments, the cross-tenant wiretap creates mass data egress equivalent to a production database breach. Dify's 10M+ Docker pulls and enterprise customer list (Volvo, Maersk, Panasonic) confirm ≥10% of the installed base occupies production data-processing roles. The blast radius in these deployments is tenant-scale to platform-scale. Verdict floor: CRITICAL.
  • Large exposed attack surface: Zafran identified tens of thousands of internet-facing instances. Unlike niche enterprise tools behind VPNs, Dify is deliberately exposed to serve AI applications to end users. This is not a theoretical network-accessible vuln — the instances are already on the internet.

Why not higher?

CVSS 9.4 is already near the ceiling. The only factor preventing a 10.0 would be if the vulnerability enabled arbitrary code execution on the host OS — this bug is confined to the Dify application layer and Plugin Daemon APIs. It enables data exfiltration and configuration tampering but not direct RCE on the underlying infrastructure. The Scope is Unchanged (S:U), correctly reflecting that the blast radius stays within the Dify trust boundary.

Why not lower?

Downgrading would require either (a) the vulnerability being reachable only from an internal network — it is not, tens of thousands of instances are internet-facing — or (b) exploitation requiring high-privilege access — it does not, free registration eliminates this barrier — or (c) the impact being confined to the attacker's own tenant — it is not, the traversal breaks cross-tenant isolation. Every friction-reducing factor works in the attacker's favor here. The 79th-percentile EPSS and merged Nuclei template confirm this is within automated scanning range.

06 · Verification

Crowdsourced verification payload.

Run this script on any machine with curl and network access to the target Dify instance. Pass the Dify base URL as the first argument: ./check_cve_2026_41948.sh https://your-dify-instance.example.com. No authentication or special privileges required — the script tests the unauthenticated traversal path.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-41948 Dify Plugin Daemon Path Traversal Check
# Tests whether the /console/api/workspaces/current/plugin/icon endpoint
# is vulnerable to path traversal via the filename parameter.
# Usage: ./check_cve_2026_41948.sh <DIFY_BASE_URL>
# Exit codes: 0 = VULNERABLE, 1 = PATCHED, 2 = UNKNOWN

set -euo pipefail

if [ $# -lt 1 ]; then
  echo "Usage: $0 <DIFY_BASE_URL>"
  echo "Example: $0 https://dify.example.com"
  exit 2
fi

BASE_URL="${1%/}"
TEST_PATH="/console/api/workspaces/current/plugin/icon"
# Use a dummy tenant_id and traverse to debug/pprof
PAYLOAD="?tenant_id=00000000-0000-0000-0000-000000000000&filename=../../../debug/pprof"
FULL_URL="${BASE_URL}${TEST_PATH}${PAYLOAD}"

echo "[*] Testing CVE-2026-41948 against: ${BASE_URL}"
echo "[*] Request: GET ${TEST_PATH}${PAYLOAD}"

HTTP_CODE=$(curl -sk -o /tmp/cve_2026_41948_resp.txt -w '%{http_code}' \
  --max-time 10 \
  "${FULL_URL}" 2>/dev/null) || {
  echo "[!] Connection failed. Verify the URL is reachable."
  echo "UNKNOWN"
  exit 2
}

RESP_BODY=$(cat /tmp/cve_2026_41948_resp.txt 2>/dev/null || echo "")
rm -f /tmp/cve_2026_41948_resp.txt

echo "[*] HTTP Response Code: ${HTTP_CODE}"

# Check for pprof indicators in response (Go runtime debug output)
if echo "${RESP_BODY}" | grep -qiE '(goroutine|heap|allocs|block|mutex|profile|pprof|cmdline|trace)'; then
  echo "[!] VULNERABLE — path traversal reached internal debug/pprof endpoint."
  echo "[!] Response contains Go pprof debug data."
  echo "VULNERABLE"
  exit 0
fi

# Check for other indicators of successful traversal
if [ "${HTTP_CODE}" = "200" ] && echo "${RESP_BODY}" | grep -qiE '(plugin|daemon|tenant|internal|debug)'; then
  echo "[!] VULNERABLE — path traversal returned internal API data."
  echo "VULNERABLE"
  exit 0
fi

# Check for explicit path traversal rejection (patched behavior)
if echo "${RESP_BODY}" | grep -qiE '(path.traversal|invalid.path|forbidden|rejected|blocked)'; then
  echo "[+] PATCHED — server rejected the path traversal attempt."
  echo "PATCHED"
  exit 1
fi

# 400/403/404 without traversal content likely means patched or not applicable
if [[ "${HTTP_CODE}" =~ ^(400|403|404|422)$ ]]; then
  echo "[+] PATCHED — server returned ${HTTP_CODE} without internal data leakage."
  echo "PATCHED"
  exit 1
fi

# 401 means auth required before reaching the endpoint
if [ "${HTTP_CODE}" = "401" ]; then
  echo "[?] Authentication required. Test with a valid session token:"
  echo "    curl -H 'Authorization: Bearer <TOKEN>' '${FULL_URL}'"
  echo "UNKNOWN"
  exit 2
fi

echo "[?] Inconclusive. HTTP ${HTTP_CODE}. Manual review recommended."
echo "UNKNOWN"
exit 2