← Back to Feed CACHED · 2026-09-26 17:50:50 · CACHE_KEY CVE-2026-41947
CVE-2026-41947 · CWE-639 · Disclosed 2026-05-18

Dify Cross-Tenant Authorization Bypass via Trace Configuration Endpoints (DifyTap)

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

Someone left the conference room speakerphone forwarding all calls to a stranger's voicemail

CVE-2026-41947 is an Insecure Direct Object Reference (IDOR) in Dify's trace configuration endpoints (/console/api/apps/<app_id>/trace-config). Versions prior to 1.14.2 accept authenticated requests to GET, POST, PATCH, or DELETE trace configurations for *any* app_id without verifying that the caller belongs to the same tenant as the target application. An attacker who obtains a victim app's app_id — trivially extracted from the JWT returned when accessing the app as a client — can bind their own LLM trace provider (LangSmith, Opik, Langfuse, etc.) to the victim app. From that moment on, every inbound prompt and outbound model response is silently copied to the attacker's observability backend. Dify ≤ 1.14.1 is affected; the fix landed in commit 55d05fe via PR #35793. The platform powers 1M+ deployed applications and is used by enterprises including Volvo, Maersk, Panasonic, and Thermo Fisher.

The vendor rates this CRITICAL 9.1 (CVSS 3.1) and 9.3 (CVSS 4.0), anchored on PR:N — no privileges required. That score is *defensible for Dify Cloud*, where unauthenticated free self-registration means anyone can create an editor account in seconds. But it overstates reality for self-hosted deployments, where the attacker must already hold an editor-role credential inside the instance. Even on Cloud, the impact is bounded to data confidentiality and trace-config integrity within Dify — there is no code execution, no lateral movement to infrastructure, and no supply-chain pivot. The CVSS vector's I:H captures the ability to overwrite trace configs, but it is not arbitrary write across the system. noisgate downgrades from CRITICAL to HIGH 8.2: the attack is devastatingly simple on Cloud but the blast radius is application-tier data exfiltration, not infrastructure compromise.

"Trivially weaponizable cross-tenant wiretap on Dify Cloud; self-hosted needs editor creds."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Create attacker account on Dify Cloud

The attacker registers a free Dify Cloud account at cloud.dify.ai. Self-registration is unauthenticated and unrestricted — no invitation, corporate email, or payment required. On self-hosted instances this step requires an existing editor-level credential, which is substantially higher friction.
Conditions required:
  • Internet access to Dify Cloud (or existing editor credential on self-hosted)
Where this breaks in practice:
  • Self-hosted deployments require pre-existing editor credentials, blocking anonymous attackers
  • Enterprise SSO-gated self-hosted instances further narrow this to insider threat only
STEP 02

Obtain victim application's app_id

The attacker accesses the victim's published AI application as a normal end-user client. Dify returns a JWT token in the response that contains the internal app_id UUID. Alternatively, the attacker can enumerate app_ids if other IDOR vectors (CVE-2026-41949, CVE-2026-41950) are chained. No special tooling is needed — browser DevTools suffice.
Conditions required:
  • Victim application must be published and accessible to the attacker as a client
  • Attacker can parse JWT from the application's API response
Where this breaks in practice:
  • If the victim app is restricted (e.g., API-key gated or VPN-only), the attacker cannot obtain the JWT
  • Internal-only apps on self-hosted instances behind network segmentation are unreachable
Detection/coverage: Anomalous client access patterns to published apps could be logged but are rarely alerted on
STEP 03

Call trace-config endpoints with victim's app_id

Using their authenticated console session, the attacker sends a POST to /console/api/apps/<victim_app_id>/trace-config with their own trace provider credentials (e.g., LangSmith API key and project name). The server accepts the request because ops_trace.py authenticates the caller but never validates that app_id belongs to the caller's tenant. The trace config is written to the victim app's settings.
Conditions required:
  • Authenticated console session (editor role minimum)
  • Knowledge of victim app_id from step 2
Where this breaks in practice:
  • None on Dify Cloud — the API call is a single HTTP POST
  • Self-hosted: requires console access, which may be IP-restricted
Detection/coverage: Audit logging of trace configuration changes per-app would catch this, but Dify's default logging does not surface cross-tenant writes as anomalies
STEP 04

Enable persistent exfiltration channel

Once the attacker's trace provider is configured and enabled on the victim app, all subsequent messages and model responses flow to the attacker's observability backend in real time. This is not a one-time read — it is a persistent wiretap that continues until the victim notices and removes the rogue trace config. The attacker receives full prompt text, model completions, tool-call payloads, and metadata. No weaponized exploit toolkit exists publicly; the attack requires only curl or any HTTP client.
Conditions required:
  • Attacker has an account on a supported trace provider (LangSmith, Opik, Langfuse — all have free tiers)
Where this breaks in practice:
  • Victim may notice the trace config in their app settings dashboard
  • Organizations with change-management workflows on app configs would detect the addition
Detection/coverage: No known scanner (Nuclei, Nessus, Qualys) has a check for this specific IDOR as of September 2026. Manual audit of trace configurations across all apps is the only detection method.
03 · Compensating Control

1
HIGH 8.2→IGNORE 0.0
SEVERITY REDUCED
Upgrade to Dify 1.14.2 immediately on Cloud; within 30 days on self-hosted — The patch adds tenant-scoping via @get_app_model to all trace-config endpoints, returning 404 for cross-tenant requests. Dify Cloud users should confirm they are on the latest managed version. Self-hosted operators should upgrade per the noisgate remediation SLA for HIGH (≤ 180 days), but given the trivial exploitability, target 30 days. Docker Compose deployments: docker compose pull && docker compose up -d.
2
HIGH 8.2→HIGH 7.5
Audit all existing trace configurations across every app — Before or immediately after patching, enumerate trace configs on all applications (GET /console/api/apps/<app_id>/trace-config for each app). Any trace provider you do not recognize — especially newly added LangSmith, Opik, or Langfuse configs — is a strong indicator of compromise. Remove unauthorized configs. Deploy within the noisgate mitigation SLA for HIGH (≤ 30 days), ideally within 72 hours.
3
HIGH 8.2→MEDIUM 5.5
SEVERITY REDUCED
Restrict console access to trusted networks (self-hosted) — Place the Dify console (/console/*) behind a VPN, zero-trust proxy, or IP allowlist. This breaks step 1 of the attack path for external attackers on self-hosted instances. Does not help Dify Cloud users. Deploy within 30 days per the noisgate mitigation SLA.
4
HIGH 8.2→MEDIUM 5.0
SEVERITY REDUCED
Enforce SSO with MFA for all console accounts — Requiring SSO (SAML/OIDC) with MFA for Dify console access eliminates the free-registration vector on self-hosted instances and ensures that editor accounts are tied to verified corporate identities. On Dify Cloud, this is a Dify Enterprise feature — contact LangGenius to enable. Deploy within 30 days.
5
HIGH 8.2→HIGH 7.0
Monitor trace-config change events via API audit logging — If Dify's audit logs or a reverse-proxy WAF can capture POST/PATCH/DELETE to /console/api/apps/*/trace-config, alert on any modification. This converts the persistent wiretap into a detectable event. Not a preventive control — purely detective.
What doesn't work
  • WAF rules on the trace-config path — the requests are legitimate authenticated API calls with valid JSON bodies; no signature or payload anomaly for a WAF to match.
  • Network segmentation of the Dify application tier — the IDOR is in the *console API*, not the public app-serving layer; segmenting the app frontend does not protect the console.
  • Rotating LLM API keys — this vulnerability is in Dify's console layer, not in the LLM provider integration; rotating OpenAI/Anthropic keys does not affect the trace-config IDOR.
  • Disabling tracing entirely — while this would prevent the attack, it removes a critical observability capability; patching is strictly preferable.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo confirmed exploitation. Not listed on CISA KEV. No GreyNoise or Shadowserver tags observed. Zafran Security disclosed responsibly; no reports of active campaigns.
Proof-of-ConceptNo public PoC code. The vulnerability was reported via the huntr bounty program by Zafran Security. No repos on GitHub named CVE-2026-41947. pocindex.io shows no indexed PoC from ExploitDB, Nuclei, or Metasploit. However, exploitation requires only a single curl POST — weaponization is trivial for anyone who reads the Zafran blog post.
EPSS Score0.00605 (0.45%) — 36.1st percentile. Low predicted exploitation probability, consistent with no observed in-the-wild activity.
CISA KEV StatusNot listed as of 2026-09-27.
CVSS 3.1 VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N — Network-reachable, low complexity, no privileges (on Cloud), no user interaction. High confidentiality and integrity impact, no availability impact. The PR:N is accurate for Cloud (free registration) but overstates self-hosted risk.
CVSS 4.0 Score9.3 — CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
Affected VersionsDify < 1.14.2 (all versions through 1.14.1). Both Dify Cloud and self-hosted community/enterprise editions.
Fixed VersionDify 1.14.2 — released with tenant-scoping enforcement via @get_app_model decorator. Fix commit: 55d05fe. PR #35793.
Scanning / ExposureNo dedicated Nuclei template, Nessus plugin, or Qualys QID exists for this CVE. Shodan/Censys/FOFA queries for exposed Dify instances (http.title:"Dify") can identify attack surface, but the IDOR itself is not externally detectable without authentication. Dify has 138K+ GitHub stars and 1M+ deployed apps.
Researcher / DisclosureIdo Shani and Gal Zaban of Zafran Security. Published as part of the "DifyTap" research cluster (4 CVEs) on 2026-06-22. Reported via huntr. GHSA: GHSA-48xc-wmw8-3jr3.

Sources.

  1. Zafran Security — DifyTap Research Blog
  2. The Hacker News — DifyTap Coverage
  3. VulnCheck Advisory — Dify Trace Config Authorization Bypass
  4. GitHub PR #35793 — Tenant-Scoping Fix
  5. GitHub GHSA-48xc-wmw8-3jr3
  6. Dify Release v1.14.2 — Security Fixes
  7. CyberPress — DifyTap Cross-Tenant Flaws
  8. Strix AI — CVE-2026-41947 Detail
05 · The Call

Final Verdict
↓ DOWNGRADED to HIGH (8.2/10)

Why this verdict

  • Dify Cloud friction is near-zero: Free self-registration, JWT-exposed app_ids, and single-POST exploitation make this trivially weaponizable on cloud.dify.ai. No public PoC is needed — the Zafran blog provides a complete recipe. This anchors the floor.
  • Self-hosted friction is materially higher: Editor credentials are required, console access may be IP-restricted or SSO-gated, and internal-only apps are unreachable from the internet. Roughly half of enterprise Dify deployments are self-hosted with access controls that break step 1.
  • Impact is bounded to application-tier data exfiltration: The attacker gains a persistent wiretap on AI conversations (C:H) and can overwrite trace configs (I:H), but there is no code execution, no privilege escalation, no lateral movement to underlying infrastructure. The blast radius is Dify-internal, not fleet-scale.
  • Role multiplier: Dify occupies the *application tier / AI platform* role. (a) Low-value: dev sandboxes and prototyping — impact is minimal. (b) Typical: team AI app builder with internal data — impact is sensitive data exfiltration, bounded to the application. (c) High-value: production AI applications processing regulated data (PII, financial, healthcare) for enterprises like Volvo, Maersk, Panasonic — the wiretap could expose regulated data streams, triggering compliance obligations (GDPR, HIPAA). However, Dify is NOT a canonical high-value infrastructure component (not identity, hypervisor, PAM, backup, CA, or network edge). The worst-case blast radius is *tenant-level data breach*, not domain takeover or fleet compromise. This sets a HIGH floor, not CRITICAL.
  • No exploitation evidence compounds the downgrade: Zero KEV entries, no GreyNoise/Shadowserver tags, EPSS at 36th percentile. The attack surface is real but untouched so far.

Why not higher?

CRITICAL would require either infrastructure-level impact (RCE, privilege escalation, lateral movement) or the affected component being a canonical high-value role (identity provider, hypervisor, domain controller). Dify is an application-tier AI platform — even in the worst case, compromise yields data exfiltration within the Dify boundary, not fleet-wide or domain-wide control. The I:H in the CVSS vector represents trace-config tampering, not arbitrary system writes. The attack cannot pivot beyond Dify.

Why not lower?

MEDIUM would understate the risk for Dify Cloud deployments, where the full chain (register → extract app_id → POST trace config → wiretap) completes in minutes with zero friction. The persistent, silent nature of the exfiltration — capturing *every future conversation* — elevates this above a typical IDOR. Enterprises running production AI apps with sensitive data face real regulatory exposure if this is exploited. The 1M+ app install base and named enterprise customers (Volvo, Maersk, Panasonic) ensure the vulnerable population is not trivially small.

06 · Verification

Crowdsourced verification payload.

Run this script on the host running Dify (or any machine with curl access to the Dify API). It checks the Dify instance version via the /console/api/setup or version endpoint. Usage: chmod +x check_cve_2026_41947.sh && ./check_cve_2026_41947.sh https://your-dify-instance.example.com. No authentication required for the version check.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_41947.sh — Detect CVE-2026-41947 (Dify trace-config IDOR)
# Usage: ./check_cve_2026_41947.sh <DIFY_BASE_URL>
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN

set -euo pipefail

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

BASE_URL="${1%/}"
FIXED_MAJOR=1
FIXED_MINOR=14
FIXED_PATCH=2

# Try multiple version-discovery endpoints
VERSION=""
for endpoint in "/console/api/version" "/api/version" "/version"; do
  RESP=$(curl -sf --max-time 10 "${BASE_URL}${endpoint}" 2>/dev/null || true)
  if [[ -n "$RESP" ]]; then
    VERSION=$(echo "$RESP" | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' 2>/dev/null || true)
    [[ -n "$VERSION" ]] && break
  fi
done

# Fallback: check HTML page for version string
if [[ -z "$VERSION" ]]; then
  RESP=$(curl -sf --max-time 10 "${BASE_URL}/" 2>/dev/null || true)
  VERSION=$(echo "$RESP" | grep -oP 'dify[/ ]v?\K[0-9]+\.[0-9]+\.[0-9]+' 2>/dev/null | head -1 || true)
fi

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN — could not determine Dify version at ${BASE_URL}"
  echo "Manual check: verify Dify version >= 1.14.2"
  exit 2
fi

echo "Detected Dify version: ${VERSION}"

IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
MAJOR=${MAJOR:-0}; MINOR=${MINOR:-0}; PATCH=${PATCH:-0}

if (( MAJOR > FIXED_MAJOR )) || \
   (( MAJOR == FIXED_MAJOR && MINOR > FIXED_MINOR )) || \
   (( MAJOR == FIXED_MAJOR && MINOR == FIXED_MINOR && PATCH >= FIXED_PATCH )); then
  echo "PATCHED — Dify ${VERSION} >= 1.14.2 (CVE-2026-41947 fixed)"
  exit 0
else
  echo "VULNERABLE — Dify ${VERSION} < 1.14.2 (CVE-2026-41947 applies)"
  echo "Action: Upgrade to Dify >= 1.14.2 and audit all app trace configurations."
  exit 1
fi