Back to Blog
high SEVERITY7 min read

How Arbitrary File Read happens in Python LangSmith SDK and how to fix it

A high-severity arbitrary server-side file read vulnerability (GHSA-f4xh-w4cj-qxq8) was discovered in LangSmith SDK's `TracingMiddleware`, affecting versions prior to 0.8.18. An attacker able to influence tracing requests could potentially read arbitrary files from the server's filesystem. Upgrading from version 0.8.15 to 0.8.18 in `poetry.lock` and `pyproject.toml` closes the attack surface entirely.

O
By Orbis AppSec
Published August 26, 2026Reviewed August 26, 2026

Answer Summary

GHSA-f4xh-w4cj-qxq8 is a high-severity arbitrary server-side file read vulnerability in the LangSmith Python SDK's `TracingMiddleware`, classified under CWE-22 (Path Traversal). Versions before 0.8.18 allowed attacker-controlled input to reach file-read logic without sufficient path sanitization. The fix is to upgrade LangSmith to 0.8.18 or later, which patches the middleware's input handling to prevent unauthorized filesystem access.

Vulnerability at a Glance

cweCWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
fixUpgrade langsmith from 0.8.15 to 0.8.18 in poetry.lock and pyproject.toml
riskAttacker can read arbitrary files from the server filesystem via crafted tracing requests
languagePython
root causeLangSmith SDK's TracingMiddleware processed user-influenced input without adequate path sanitization before performing file operations
vulnerabilityArbitrary Server-Side File Read (Path Traversal)

The Vulnerability That Hid in Your AI Observability Layer

When teams add LangSmith to their LLM applications for tracing and observability, they're adding middleware that sits directly in the request path. That's a privileged position — and in LangSmith SDK versions prior to 0.8.18, it turned out to be an exploitable one.

Security advisory GHSA-f4xh-w4cj-qxq8 describes a high-severity arbitrary server-side file read in LangSmith SDK's TracingMiddleware. The vulnerability meant that a crafted request could cause the middleware to read files from the server's local filesystem — files the requester was never meant to see. This post walks through what went wrong, how it was fixed, and what Python developers building on LangChain/LangSmith should understand about middleware-level security.


The Vulnerability Explained

What Is TracingMiddleware Doing?

LangSmith's TracingMiddleware is an ASGI/WSGI-compatible middleware layer that intercepts HTTP requests to log traces of LLM interactions. Because it processes incoming request data — headers, body content, route parameters — before passing control downstream, it handles attacker-influenced input very early in the request lifecycle.

The vulnerability is a path traversal / arbitrary file read (CWE-22). In the affected versions (≤ 0.8.15), the middleware processed certain input values and used them — directly or indirectly — in file operations without adequately restricting the resulting filesystem path.

The Classic Path Traversal Pattern

A path traversal vulnerability typically looks like this in Python:

# VULNERABLE — user-controlled value used directly in file open
def read_trace_artifact(artifact_name: str) -> str:
    base_dir = "/app/traces"
    path = os.path.join(base_dir, artifact_name)  # ← no canonicalization
    with open(path, "r") as f:
        return f.read()

If artifact_name is ../../../../etc/passwd, os.path.join produces /etc/passwd — completely outside /app/traces. Without a check that the resolved path still starts with the intended base directory, the application reads any file the server process can access.

In LangSmith's case, the TracingMiddleware component was the entry point where tainted request data could reach such file-read logic.

Real-World Impact for LangSmith Users

Applications using LangSmith for tracing are often:

  • Deployed in cloud environments with secrets mounted as files (e.g., /run/secrets/db_password, Kubernetes secret volumes)
  • Running alongside .env files containing API keys and database credentials
  • Hosting model weight files or proprietary prompt templates on the local filesystem

An attacker exploiting this vulnerability against a production LangSmith-instrumented application could potentially exfiltrate any of these resources by sending a crafted tracing request. Because TracingMiddleware is designed to receive external HTTP traffic, the attack surface is directly internet-exposed in many deployments.


The Fix

Upgrading from 0.8.15 to 0.8.18

The remediation is a targeted version upgrade. The poetry.lock diff shows the transition:

Before (vulnerable):

# poetry.lock — langsmith pinned at 0.8.15
name = "langsmith"
version = "0.8.15"

After (fixed):

# poetry.lock — langsmith upgraded to 0.8.18
name = "langsmith"
version = "0.8.18"

LangSmith 0.8.18 patches the TracingMiddleware to sanitize path-like values before they can reach any file-open operation. The fix in the upstream SDK ensures that user-influenced input is validated against an allowlist or canonicalized and checked against a restricted base path — preventing traversal sequences like ../ from escaping the intended directory.

What Else Changed in the Lock File?

The poetry.lock diff also reveals that several previously optional dependencies — asyncpg, backoff, boto3, botocore — were promoted from optional = true to optional = false. This reflects LangSmith 0.8.18 making these dependencies unconditional (likely because features requiring them are now always enabled). The markers = "extra == \"postgres\"" and markers = "extra == \"langfuse\"" guards were removed accordingly.

 name = "asyncpg"
 version = "0.31.0"
-optional = true
+optional = false
 python-versions = ">=3.9.0"
 groups = ["main"]
-markers = "extra == \"postgres\""

This is a packaging change, not a security change — but it's worth noting if your deployment environment has restrictions on which packages can be installed.

Why This Fix Is Sufficient

Because the vulnerability lives entirely within the LangSmith SDK's own middleware code (not in your application code), upgrading the package is a complete fix. Your application does not need to add its own path sanitization on top — though defense-in-depth is always worthwhile.


Prevention & Best Practices

1. Canonicalize Before You Check

Whenever user input influences a filesystem path, resolve it to its canonical form before validating:

import os

def safe_read(base_dir: str, user_input: str) -> str:
    # Resolve symlinks and normalize the path
    resolved = os.path.realpath(os.path.join(base_dir, user_input))
    # Enforce the path is still inside base_dir
    if not resolved.startswith(os.path.realpath(base_dir) + os.sep):
        raise ValueError(f"Path traversal detected: {user_input!r}")
    with open(resolved, "r") as f:
        return f.read()

Using pathlib (Python 3.6+):

from pathlib import Path

def safe_read_pathlib(base_dir: str, user_input: str) -> str:
    base = Path(base_dir).resolve()
    target = (base / user_input).resolve()
    target.relative_to(base)  # raises ValueError if outside base
    return target.read_text()

2. Audit Third-Party Middleware

Middleware components are uniquely dangerous because they process all requests, including unauthenticated ones. When evaluating any middleware — especially in AI/ML observability tooling that's newer and may have less security review history — check:

  • Does it perform any file I/O?
  • Does it use request data to construct paths?
  • Is it receiving data before authentication middleware runs?

3. Keep AI/ML Dependencies Pinned and Monitored

The LangChain ecosystem (langchain, langsmith, langgraph) moves extremely fast. New versions ship frequently, and security patches are often bundled with feature releases. Use tools like:

  • Trivy — flagged this exact vulnerability via rule GHSA-f4xh-w4cj-qxq8
  • pip-audit — scans installed packages against PyPI advisory database
  • Dependabot / Renovate — automated PRs for dependency updates
  • GitHub Advisory Database — subscribe to advisories for your dependencies

4. Apply Least-Privilege Filesystem Permissions

Even if a path traversal bug exists, its blast radius is limited if the application process can't read sensitive files. Run your application as a non-root user with read access only to directories it legitimately needs.

5. OWASP & CWE References


Key Takeaways

  • TracingMiddleware in LangSmith ≤ 0.8.15 processed request data without sufficient path sanitization, creating a direct path from attacker input to server filesystem reads.
  • AI observability libraries deserve the same security scrutiny as any other web middleware — they sit in the request path and handle raw, potentially hostile input.
  • The poetry.lock file is your ground truth for what's actually installed; pinning to 0.8.15 while a patched 0.8.18 exists left this vulnerability open unnecessarily.
  • Trivy's GHSA-f4xh-w4cj-qxq8 rule can detect this specific vulnerable version range in your dependency lock files — integrate it into CI to catch regressions.
  • Upgrading to 0.8.18 is the complete fix — no application-level code changes are required because the vulnerability is entirely within the SDK's middleware.

How Orbis AppSec Detected This

  • Source: Attacker-controlled HTTP request data (headers, body, or route parameters) processed by TracingMiddleware in the LangSmith SDK
  • Sink: File-read operations within TracingMiddleware that consumed path values derived from request input without adequate sanitization
  • Missing control: No path canonicalization or base-directory enforcement before the file-open call, allowing ../ traversal sequences to escape the intended directory scope
  • CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
  • Fix: Upgraded langsmith from 0.8.15 to 0.8.18 in poetry.lock and pyproject.toml, replacing the vulnerable TracingMiddleware implementation with the patched version from the upstream SDK

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

GHSA-f4xh-w4cj-qxq8 is a sharp reminder that the observability and tracing layers we bolt onto AI applications aren't exempt from classic web security vulnerabilities. An arbitrary file read in TracingMiddleware could expose secrets, configuration files, or sensitive data to any attacker who can send a crafted HTTP request — a low bar in any internet-facing deployment.

The fix is straightforward: upgrade LangSmith to 0.8.18. But the broader lesson is architectural — middleware that processes unauthenticated request data and performs file I/O is a high-risk combination that deserves careful review, regardless of the vendor or framework. Build dependency scanning into your CI pipeline, subscribe to advisories for your AI/ML dependencies, and apply filesystem least-privilege so that even if a traversal bug slips through, its impact is contained.


References

Frequently Asked Questions

What is an arbitrary server-side file read vulnerability?

It's a flaw where an attacker can supply crafted input (often a path or filename) that causes the server to open and return the contents of files outside the intended directory — including sensitive files like /etc/passwd or application secrets.

How do you prevent path traversal vulnerabilities in Python?

Validate and sanitize all user-supplied paths, use os.path.realpath() or pathlib.Path.resolve() to canonicalize paths, and enforce that resolved paths stay within an allowed base directory before opening any file.

What CWE is arbitrary file read?

CWE-22 — Improper Limitation of a Pathname to a Restricted Directory (Path Traversal). Related identifiers include CWE-73 (External Control of File Name or Path).

Is upgrading the package enough to prevent this vulnerability?

Yes, in this case upgrading LangSmith to 0.8.18 patches the vulnerable TracingMiddleware code directly. No additional application-level changes are required, though defense-in-depth measures like filesystem permissions are always recommended.

Can static analysis detect arbitrary file read vulnerabilities?

Yes. Tools like Trivy (which flagged this issue), Semgrep, and Bandit can detect tainted data flowing from HTTP inputs to file-open sinks. Trivy's GHSA-f4xh-w4cj-qxq8 rule identified this specific pattern in the LangSmith dependency.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #46

Related Articles

critical

How Archive Path Traversal Happens in Node.js and How to Fix It

CVE-2026-53486 is a critical path traversal vulnerability in the Decompress library, where crafted archive entries can write files and symbolic links outside the intended extraction directory. This vulnerability was transitively introduced through `@vitest/browser` and related packages pinned at version 4.1.5, and was resolved by upgrading to 4.1.6 and 5.0.0-beta.3. Left unpatched, an attacker who controls an archive file processed by any downstream consumer of this dependency chain could overwr

high

How Path Traversal happens in Python Flask apps and how to fix it

A path traversal vulnerability in `WAVE2SCORE/app.py` allowed attackers to supply a crafted file path that escaped the application's intended working directory, potentially enabling access to arbitrary files on the server. The fix resolves the absolute path and validates it against the expected `WORK_DIR` boundary before any processing occurs. This kind of boundary check is a critical safeguard in any application that processes user-supplied file paths.

critical

How Command Injection happens in Python PopClip Extensions and how to fix it

A critical command injection vulnerability was discovered in `contrib/Klipz.popclipext/Klipz.py`, where user-controlled clipboard content was concatenated directly into shell commands executed via `osascript`. The fix replaces unsafe string concatenation with `subprocess` and proper argument lists, and replaces the unsafe `pickle` serialization with `json` to eliminate a secondary deserialization risk. Together, these changes close two distinct attack surfaces in a single file.

high

How Path Traversal happens in PostCSS Source Map Auto-Loading and how to fix it

A high-severity path traversal vulnerability in PostCSS versions before 8.5.18 allowed attackers to manipulate `sourceMappingURL` directives to load arbitrary `.map` files from the filesystem, potentially disclosing sensitive source code and build metadata. The fix upgrades PostCSS from 8.5.15 to 8.5.18 in `console/web/package-lock.json`, closing the path traversal vector in the source map auto-loading feature. This change protects applications that process untrusted CSS input through their Post

critical

How Path Traversal happens in Node.js agents and how to fix it

A path traversal vulnerability in `skills/baoyu-design/agents/import-design-system.mjs` allowed attackers to escape the intended design system directory by supplying absolute paths, bypassing a guard that only checked for `..` prefixes. The fix adds an `isAbsolute()` check alongside the existing relative-path guard, closing the bypass with a single targeted change. This matters because the `dsDir` argument is user-controlled, meaning any caller of the script could redirect file operations to sen

high

How Denial of Service via infinite loop happens in Node.js dependencies and how to fix it

A high-severity Denial of Service vulnerability in the nanoid package (CVE-2026-67213) was discovered in the project's dependency tree, where crafted input could trigger an infinite loop during random ID generation. The fix upgrades nanoid from 3.3.17 to 3.3.18 and adds an npm override to ensure all transitive dependencies use the patched version.