Back to Blog
high SEVERITY6 min read

How path traversal happens in Ruby YARD server and how to fix it

A high-severity path traversal vulnerability (CVE-2026-41493) in YARD versions prior to 0.9.42 allowed attackers to read arbitrary files from servers running `yard server`. This fix upgrades the yard gem from 0.9.26 to 0.9.42 in the Gemfile and Gemfile.lock, closing a dangerous information disclosure vector that could expose configuration files, credentials, and source code.

O
By Orbis AppSec
Published July 9, 2026Reviewed July 9, 2026

Answer Summary

CVE-2026-41493 is a path traversal vulnerability in YARD, a Ruby documentation generator, affecting versions before 0.9.42. When running `yard server`, attackers could craft malicious URLs with `../` sequences to escape the documentation directory and read arbitrary files from the server, potentially exposing secrets and source code. The fix is to upgrade the yard gem to version 0.9.42 or later by updating your Gemfile constraint and running `bundle update yard`.

Vulnerability at a Glance

cweCWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
fixUpgrade yard gem from 0.9.26 to 0.9.42 or later
riskUnauthorized file read access on servers running YARD documentation server
languageRuby
root causeYARD server did not properly sanitize file path parameters, allowing `../` traversal sequences
vulnerabilityPath Traversal / Directory Traversal

Introduction

In a Ruby project's Gemfile.lock, we discovered a high-severity path traversal vulnerability lurking in an outdated version of YARD—the popular Ruby documentation generator. The project was running yard version 0.9.26, which contained CVE-2026-41493, a flaw that could let attackers read arbitrary files from any server running yard server.

This isn't just a theoretical risk. YARD's built-in server is commonly used during development to browse generated documentation locally, but it's sometimes inadvertently exposed on staging or CI servers. The vulnerable code path didn't properly sanitize URL parameters, allowing an attacker to escape the documentation root directory using classic ../ traversal sequences.

Here's the vulnerable dependency declaration from the original Gemfile:

gem "yard", "~> 0.9.11"

This constraint allowed any version from 0.9.11 up to (but not including) 0.10.0, which meant the resolved version 0.9.26 in Gemfile.lock remained vulnerable to CVE-2026-41493.

The Vulnerability Explained

What is Path Traversal?

Path traversal occurs when an application accepts user input that specifies a file path without properly validating that the path stays within intended boundaries. Attackers exploit this by injecting directory traversal sequences like ../ (dot-dot-slash) to navigate up the directory tree and access files outside the allowed scope.

How YARD Server Was Vulnerable

YARD includes a built-in web server (yard server) that serves generated documentation over HTTP. When a user requests a documentation page, the server maps the URL path to files in the documentation directory. In versions prior to 0.9.42, the server failed to properly sanitize these path parameters.

An attacker could craft a malicious request like:

GET /../../../../etc/passwd HTTP/1.1
Host: vulnerable-yard-server:8808

Or on a Ruby application server:

GET /../../../config/database.yml HTTP/1.1
Host: vulnerable-yard-server:8808

The YARD server would resolve this path relative to the documentation root, but the ../ sequences would escape that directory entirely, allowing the attacker to read:

  • /etc/passwd — system user information
  • config/database.yml — database credentials
  • .env files — environment secrets
  • config/master.key — Rails encryption keys
  • Source code files — potentially revealing additional vulnerabilities

Real-World Attack Scenario

Imagine a CI/CD pipeline that runs yard server to generate and preview documentation before deployment. If this server is accessible on the internal network (or worse, exposed publicly), an attacker could:

  1. Discover the YARD server running on port 8808
  2. Send a traversal request: GET /../../../.env
  3. Retrieve AWS credentials, API keys, or database passwords
  4. Use those credentials to access production systems

The Gemfile.lock showed the project was locked to version 0.9.26:

yard (0.9.26)

This version was released years before the security fix, leaving a significant window of exposure.

The Fix

The fix is straightforward but critical: upgrade the yard gem to version 0.9.42 or later, where the path traversal vulnerability has been patched.

Before (Vulnerable)

Gemfile:

gem "yard", "~> 0.9.11"

Gemfile.lock:

yard (0.9.26)

After (Fixed)

Gemfile:

gem "yard", "~> 0.9.42"

Gemfile.lock:

yard (0.9.42)

Why This Change Works

The version constraint change from ~> 0.9.11 to ~> 0.9.42 accomplishes two things:

  1. Immediate fix: Forces Bundler to resolve to at least version 0.9.42, which contains the security patch
  2. Future protection: The pessimistic constraint (~>) still allows patch updates (0.9.43, 0.9.44, etc.) while preventing breaking changes from a potential 0.10.0 release

The YARD maintainers fixed the vulnerability in version 0.9.42 by implementing proper path canonicalization and containment checks. The server now:

  • Resolves the full absolute path of any requested file
  • Verifies the resolved path starts with the documentation root directory
  • Rejects requests that would escape the allowed directory

Changes Made

File Change
Gemfile Updated version constraint from ~> 0.9.11 to ~> 0.9.42
Gemfile.lock Resolved version updated from 0.9.26 to 0.9.42

Both files needed updating because:
- Gemfile declares the dependency constraint (what versions are acceptable)
- Gemfile.lock records the exact resolved version (what's actually installed)

Prevention & Best Practices

1. Keep Dependencies Updated

Regularly audit and update your dependencies. Tools like bundle audit for Ruby can identify known vulnerabilities:

gem install bundler-audit
bundle audit check --update

2. Use Dependency Scanning in CI/CD

Integrate security scanners like Trivy, Dependabot, or Snyk into your pipeline to catch vulnerable dependencies before they reach production.

3. Minimize Exposure of Development Tools

YARD server is intended for local documentation browsing, not production use. Ensure development tools like yard server are:
- Never exposed to the internet
- Firewalled on CI/CD systems
- Disabled in production environments

4. Implement Defense in Depth

Even if you're running a patched version, apply additional protections:
- Use reverse proxies with path validation
- Run services in containers with minimal file system access
- Apply the principle of least privilege

5. Validate File Paths in Your Own Code

When building applications that handle file paths, always:

# Bad - vulnerable to path traversal
file_path = params[:filename]
File.read(file_path)

# Good - validate and contain the path
base_dir = Rails.root.join('public', 'documents')
requested_file = File.expand_path(params[:filename], base_dir)

unless requested_file.start_with?(base_dir.to_s)
  raise SecurityError, "Path traversal attempt detected"
end

File.read(requested_file)

Key Takeaways

  • YARD versions before 0.9.42 are vulnerable to CVE-2026-41493 — any project using yard server with an older version should upgrade immediately
  • The ~> 0.9.11 constraint was too permissive — it allowed vulnerable versions to be installed; pin to at least ~> 0.9.42 for security
  • Development tools can become attack vectors — even documentation generators like YARD can expose sensitive files if their servers are accessible
  • Path traversal in Ruby requires explicit containment checks — always verify resolved paths stay within allowed directories using File.expand_path() and prefix matching
  • Automated dependency scanning caught this issue — Trivy flagged the vulnerable version in Gemfile.lock, enabling a quick fix before exploitation

How Orbis AppSec Detected This

  • Source: HTTP request path parameter in YARD server URL routing
  • Sink: File system read operation in YARD's server request handler
  • Missing control: Path canonicalization and containment validation before file access
  • CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
  • Fix: Upgraded yard gem from 0.9.26 to 0.9.42, which implements proper path validation

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

CVE-2026-41493 serves as a reminder that even trusted development tools can harbor serious security vulnerabilities. A documentation generator might seem low-risk, but when it includes a web server that handles file paths, it becomes a potential attack vector for information disclosure.

The fix was simple—a one-line version constraint change in the Gemfile—but the impact of leaving it unfixed could have been severe: exposed credentials, leaked source code, and potential full system compromise.

Keep your dependencies updated, scan regularly for vulnerabilities, and remember that security applies to every component in your stack, not just your application code.

References

Frequently Asked Questions

What is path traversal?

Path traversal (also called directory traversal) is a vulnerability where an attacker manipulates file path inputs using sequences like `../` to access files outside the intended directory, potentially reading sensitive system files or application secrets.

How do you prevent path traversal in Ruby?

Validate and sanitize all user-supplied path inputs, use `File.basename()` to strip directory components, check that resolved paths stay within allowed directories using `File.expand_path()`, and keep dependencies like YARD updated to patched versions.

What CWE is path traversal?

Path traversal is classified as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

Is input validation enough to prevent path traversal?

Input validation helps but isn't always sufficient alone. You should combine validation with canonicalization (resolving the full path) and containment checks to verify the final path stays within allowed boundaries. Using patched libraries is also essential.

Can static analysis detect path traversal?

Yes, static analysis tools like Trivy, Semgrep, and Brakeman can detect path traversal patterns by tracking tainted input flowing into file system operations without proper sanitization.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #30117

Related Articles

critical

How Denial of Service via Gzip Bomb happens in Node.js and how to fix it

CVE-2026-59873 is a critical Denial of Service vulnerability in node-tar versions prior to 7.5.19, where a maliciously crafted gzip bomb can exhaust server resources when extracting archives. The fix upgrades the `tar` dependency from version 7.5.15 to 7.5.21 in `package-lock.json` and pins the version via an `overrides` block in `package.json`. Any application that processes user-supplied tar archives is at risk of resource exhaustion, making this an urgent upgrade.

high

How javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage happens in Express.js and how to fix it

An Express.js application in `src/server.js` was missing CSRF (Cross-Site Request Forgery) protection middleware, leaving all state-changing endpoints vulnerable to forged requests from malicious sites. The fix introduces the `csrf` package to generate and validate tokens on non-GET requests, while exempting API-key-authenticated clients. This defensive hardening raises the bar against automated exploit chaining.

high

How Client-Side Denial of Service happens in Node.js FTP clients and how to fix it

CVE-2026-44240 is a client-side Denial of Service vulnerability in the `basic-ftp` Node.js package (versions prior to 5.3.1) caused by improper handling of unterminated multiline FTP server responses. An attacker controlling an FTP server—or capable of intercepting FTP traffic—could send a malformed response that causes the client to hang indefinitely. Upgrading `basic-ftp` to 5.3.1 and adding a package override in `package.json` closes the attack surface entirely.

high

How javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage happens in Express.js and how to fix it

A publicly accessible Express.js API endpoint in `app/api/cameras.js` was missing CSRF protection, leaving state-changing requests (POST, PUT, DELETE, PATCH) vulnerable to cross-site request forgery attacks. The fix introduces Origin/Referer header validation middleware in `app/index.js` and removes a redundant Express instance from `cameras.js` that bypassed the application's middleware chain.

critical

How Command Injection via Unescaped Line Terminators Happens in Node.js and How to Fix It

A critical command injection vulnerability (CVE-2026-9277) was discovered in the shell-quote npm package version 1.8.3, where unescaped line terminators could allow attackers to execute arbitrary code. This fix upgrades shell-quote to version 1.9.0 using npm overrides to ensure all instances in the dependency tree are patched, eliminating the attack vector across the entire application.

critical

How Distributed Lock Takeover Happens in Node.js and How to Fix It

A critical vulnerability in `redis-lock/server.mjs` allowed any authenticated client to release another client's lock by guessing predictable holder identifiers like process IDs or hostnames. The fix implements cryptographically random `lockId` values that are minted on lock acquisition and validated on release, eliminating the exploit primitive entirely.