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

high

How Quadratic CPU Consumption Vulnerabilities Happen in JavaScript YAML Parsers and How to Fix Them

A high-severity denial-of-service vulnerability in js-yaml versions 3.x and 4.x allowed attackers to trigger quadratic CPU consumption through specially crafted YAML documents using the !!omap tag. This fix upgrades js-yaml from 4.1.1 to 4.3.1 and from 3.14.2 to 3.15.1, eliminating the algorithmic complexity attack vector that could freeze Node.js applications processing untrusted YAML input.

high

How javascript.lang.security.detect-child-process.detect-child-process happens in Node.js and how to fix it

A high-severity command injection vulnerability was discovered in `scripts/build.js` where `execSync` was called with string-interpolated arguments (`sourceDir` and `outputPath`) inside a shell command. By replacing `execSync` with `spawnSync` using an argument array (no shell), the fix eliminates the possibility of shell metacharacter injection while preserving identical build behavior.

high

How Command Injection happens in Node.js child_process and how to fix it

A command injection vulnerability in nix.js's Release class allowed potentially malicious input through the `arch` parameter to be executed via shell commands. The fix replaced `execSync()` with `execFileSync()`, eliminating shell interpretation and preventing command injection by passing arguments as an array instead of a concatenated string.

critical

How Sensitive Data Exposure in Error Logging happens in TypeScript/Deno and how to fix it

A critical vulnerability in Supabase Edge Functions allowed sensitive authentication errors and API credentials to leak through verbose error logging. The `cancel-subscription/index.ts` function logged full error objects to the console, potentially exposing Paddle API keys and auth tokens in deployment logs. The fix sanitizes all error messages to log only safe error text while preserving debugging capability.

critical

How HTTP Header Injection Happens in Go and How to Fix It

A critical vulnerability in the file upload handler allowed attackers to inject CRLF sequences into HTTP response headers through crafted filenames. The fix sanitizes user-supplied filenames before using them in Content-Disposition headers, preventing header injection attacks that could lead to cache poisoning, session fixation, or XSS.

high

How Path Traversal and Security Policy Bypass Happens in Node.js Dependencies and How to Fix It

A high-severity vulnerability in the fast-uri package (CVE-2026-6321) allowed attackers to bypass security policies through improper Unicode hostname canonicalization and path traversal. This issue affected the @apralabs/apra-fleet project through its dependency tree, and was resolved by upgrading fast-uri from version 3.1.0 to 4.1.2 using npm overrides.