{"id":"CVE-2026-49342","aliases":["DEBIAN-CVE-2026-49342","EUVD-2026-38069","GHSA-pxcc-8665-phx8","OESA-2026-2851","OESA-2026-2852","UBUNTU-CVE-2026-49342"],"status":"published","title":"YARD static cache reads raw traversal paths before router sanitization","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","severity":{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00332,"percentile":0.26554,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2026-06-19T19:13:59Z","modified":"2026-10-28T02:30:20Z","fixes":[{"ecosystem":"RubyGems","package":"yard","fixed_in":["0.9.44"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"yard","fixed_in":["0.9.44-1"],"sources":["osv"]},{"ecosystem":"openEuler:24.03-LTS-SP1","package":"rubygem-yard","fixed_in":["0.9.34-4.oe2403sp1"],"sources":["osv"]},{"ecosystem":"openEuler:24.03-LTS-SP3","package":"rubygem-yard","fixed_in":["0.9.34-4.oe2403sp3"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"RubyGems","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.9.44"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.28-2","0.9.28-2+deb12u1","0.9.28-2+deb12u2","0.9.34-1","0.9.35-1","0.9.36-1","0.9.37-1","0.9.38-1","0.9.39-1","0.9.44-1","0.9.45-1","1.17.patch1-5","2.2-3","2.2-4","2.2-5"]},{"source":"osv","ecosystem":"Debian:13","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.37-1","0.9.38-1","0.9.39-1","0.9.44-1","0.9.45-1","1.17.patch1-5","2.2-3","2.2-4","2.2-5"]},{"source":"osv","ecosystem":"Debian:14","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.9.44-1"}]}],"versions":["0.9.37-1","0.9.38-1","0.9.39-1"]},{"source":"osv","ecosystem":"RubyGems","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.9.44"}]}],"versions":["0.2.0","0.2.1","0.2.2","0.2.3","0.2.3.2","0.2.3.3","0.2.3.4","0.2.3.5","0.4.0","0.5.0","0.5.1","0.5.1p1","0.5.2","0.5.3","0.5.4","0.5.5","0.5.6","0.5.7","0.5.8","0.6.0","0.6.1","0.6.2","0.6.3","0.6.4","0.6.5","0.6.6","0.6.7","0.6.8","0.7.0","0.7.1","0.7.2","0.7.3","0.7.4","0.7.5","0.8.0","0.8.1","0.8.2","0.8.2.1","0.8.3","0.8.4","0.8.4.1","0.8.5","0.8.5.1","0.8.5.2","0.8.6","0.8.6.1","0.8.6.2","0.8.7","0.8.7.1","0.8.7.2","0.8.7.3","0.8.7.4","0.8.7.5","0.8.7.6","0.9.0","0.9.1","0.9.10","0.9.11","0.9.12","0.9.13","0.9.14","0.9.15","0.9.16","0.9.17","0.9.18","0.9.19","0.9.2","0.9.20","0.9.21","0.9.22","0.9.23","0.9.24","0.9.25","0.9.26","0.9.27","0.9.28","0.9.29","0.9.3","0.9.30","0.9.31","0.9.32","0.9.33","0.9.34","0.9.35","0.9.36","0.9.37","0.9.38","0.9.39","0.9.4","0.9.40","0.9.41","0.9.42","0.9.43","0.9.5","0.9.6","0.9.7","0.9.8","0.9.9"]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP1","package":"rubygem-yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.9.34-4.oe2403sp1"}]}]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP3","package":"rubygem-yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.9.34-4.oe2403sp3"}]}]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.8.7.6-1","0.8.7.6+git20160220-3","0.8.7.6+git20160220-3ubuntu0.1~esm1","0.8.7.6+git20160220-3ubuntu0.1~esm2"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.9-1","0.9.12-1","0.9.12-1ubuntu3","0.9.12-2","0.9.12-2ubuntu0.1~esm1","0.9.12-2ubuntu0.1~esm2"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.16-1","0.9.20-1","0.9.24-1","0.9.24-1+deb11u1build0.20.04.1","0.9.24-1+deb11u1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.24-1","0.9.26-1","0.9.26-1ubuntu0.1","0.9.26-1ubuntu0.1+esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:24.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.28-2","0.9.34-1","0.9.35-1","0.9.36-1","0.9.36-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.37-1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.38-1","0.9.39-1","0.9.45-1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:26.04:LTS","package":"yard","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.9.37-1","0.9.37-1build1","0.9.38-1","0.9.38-1ubuntu0.1~esm1"]}],"products":[{"vendor":"lsegal","product":"yard"}],"references":[{"url":"https://github.com/lsegal/yard/security/advisories/GHSA-pxcc-8665-phx8","tags":["x_refsource_CONFIRM","exploit","advisory","web","report"]},{"url":"https://github.com/lsegal/yard/commit/f78c19f0dd33a407085b4ed181bb60c0aa0078b4","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-49342","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pxcc-8665-phx8"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/49xxx/CVE-2026-49342.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-49342","tags":["advisory"]},{"url":"https://github.com/lsegal/yard","tags":["package"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-2851","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-2852","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-49342","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-49342","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-49342","title":"YARD static cache reads raw traversal paths before router sanitization","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T19:13:59.598Z","modified":"2026-06-22T17:14:14.512Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T13:35:10.963527Z"}],"euvd":[{"id":"EUVD-2026-38069","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T19:13:59Z","modified":"2026-06-22T17:14:14Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T18:20:34.238696Z"}],"ghsa":[{"id":"GHSA-pxcc-8665-phx8","title":"YARD static cache reads raw traversal paths before router sanitization","description":"### Summary\nYARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. \n\nThe potential security risk seems low, as only html-ending files can be read, but still the risk of reading arbitrary html files is a confiendtiality issue in itself, which is why we decided to report. Please let us know if this is out of your project's scope.\n\n### Details\nThe `--docroot` CLI option stores the configured directory in `server_options[:DocumentRoot]` at `lib/yard/cli/server.rb:198`, and adapter initialization copies that value into `adapter.document_root` at `lib/yard/server/adapter.rb:76`. For Rack requests, `RackAdapter#call` builds a request object from the Rack environment at `lib/yard/server/rack_adapter.rb:58` and passes it to `router.call(request)` at `lib/yard/server/rack_adapter.rb:60`. `Router#call` then stores the incoming request at `lib/yard/server/router.rb:55` and invokes `check_static_cache` before normal routing at `lib/yard/server/router.rb:56`. Inside `check_static_cache`, the only initial guard is that `adapter.document_root` is present at `lib/yard/server/static_caching.rb:35`; the cache path is built from `File.join(adapter.document_root, request.path.sub(/\\.html$/, '') + '.html')` at `lib/yard/server/static_caching.rb:36`, without cleaning `..` components first. If that resolved path is a regular file, `File.file?` accepts it at `lib/yard/server/static_caching.rb:38` and the file bytes are returned as a `200` HTML response at `lib/yard/server/static_caching.rb:40`. The later route sanitizer in `final_options` uses `File.cleanpath(...).gsub(...)` at `lib/yard/server/router.rb:181` and `lib/yard/server/router.rb:182`, but a static-cache hit returns before that code is reached.\n\n### PoC\n[poc.zip](https://github.com/user-attachments/files/28185421/poc.zip)\n\n```bash\nbash ./poc/run.sh\n```\nexpected output:\n```text\nrun 1: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\nrun 2: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\nrun 3: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\n```\n\nThe `YARD_STATIC_CACHE_PATH_TRAVERSAL` fingerprint is emitted only after the PoC observes a `200` static-cache response whose body contains the sibling file outside the configured document root. A setup failure, syntax failure, or cache miss would not print this oracle and would not demonstrate this traversal read.\n\n### Impact\nA remote unauthenticated HTTP client who can reach a YARD documentation server with `DocumentRoot`/`--docroot` enabled can request `.html` paths containing parent-directory components and receive readable matching files outside the configured document root. The required guards are narrow: `adapter.document_root` must be set, the traversed target must exist as a regular readable file, and the target must be reachable through the implementation's forced `.html` suffix. Those requests bypass the later `final_options` path cleanup because the cache check runs first. The resulting severity class is information disclosure: response bodies can contain off-root `.html` file contents, but this path does not show write access, code execution, or arbitrary files without the `.html` constraint.","status":"published","published":"2026-06-26T22:29:29Z","modified":"2026-06-26T22:29:31Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:40:34.713036Z"}],"nvd":[{"id":"CVE-2026-49342","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T20:16:18.377Z","modified":"2026-10-25T23:10:00.167Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:24.912854Z"}],"osv":[{"id":"CVE-2026-49342","title":"YARD static cache reads raw traversal paths before router sanitization","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T19:13:59.598Z","modified":"2026-10-28T02:30:20.598475494Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:45:07.060148Z"},{"id":"DEBIAN-CVE-2026-49342","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T20:16:18.377Z","modified":"2026-10-26T11:47:34.648583316Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T15:45:56.444225Z"},{"id":"GHSA-pxcc-8665-phx8","title":"YARD static cache reads raw traversal paths before router sanitization","description":"### Summary\nYARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. \n\nThe potential security risk seems low, as only html-ending files can be read, but still the risk of reading arbitrary html files is a confiendtiality issue in itself, which is why we decided to report. Please let us know if this is out of your project's scope.\n\n### Details\nThe `--docroot` CLI option stores the configured directory in `server_options[:DocumentRoot]` at `lib/yard/cli/server.rb:198`, and adapter initialization copies that value into `adapter.document_root` at `lib/yard/server/adapter.rb:76`. For Rack requests, `RackAdapter#call` builds a request object from the Rack environment at `lib/yard/server/rack_adapter.rb:58` and passes it to `router.call(request)` at `lib/yard/server/rack_adapter.rb:60`. `Router#call` then stores the incoming request at `lib/yard/server/router.rb:55` and invokes `check_static_cache` before normal routing at `lib/yard/server/router.rb:56`. Inside `check_static_cache`, the only initial guard is that `adapter.document_root` is present at `lib/yard/server/static_caching.rb:35`; the cache path is built from `File.join(adapter.document_root, request.path.sub(/\\.html$/, '') + '.html')` at `lib/yard/server/static_caching.rb:36`, without cleaning `..` components first. If that resolved path is a regular file, `File.file?` accepts it at `lib/yard/server/static_caching.rb:38` and the file bytes are returned as a `200` HTML response at `lib/yard/server/static_caching.rb:40`. The later route sanitizer in `final_options` uses `File.cleanpath(...).gsub(...)` at `lib/yard/server/router.rb:181` and `lib/yard/server/router.rb:182`, but a static-cache hit returns before that code is reached.\n\n### PoC\n[poc.zip](https://github.com/user-attachments/files/28185421/poc.zip)\n\n```bash\nbash ./poc/run.sh\n```\nexpected output:\n```text\nrun 1: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\nrun 2: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\nrun 3: exit=0 timed_out=False duration=0.08s matched=True phase=oracle fingerprint='YARD_STATIC_CACHE_PATH_TRAVERSAL'\n```\n\nThe `YARD_STATIC_CACHE_PATH_TRAVERSAL` fingerprint is emitted only after the PoC observes a `200` static-cache response whose body contains the sibling file outside the configured document root. A setup failure, syntax failure, or cache miss would not print this oracle and would not demonstrate this traversal read.\n\n### Impact\nA remote unauthenticated HTTP client who can reach a YARD documentation server with `DocumentRoot`/`--docroot` enabled can request `.html` paths containing parent-directory components and receive readable matching files outside the configured document root. The required guards are narrow: `adapter.document_root` must be set, the traversed target must exist as a regular readable file, and the target must be reachable through the implementation's forced `.html` suffix. Those requests bypass the later `final_options` path cleanup because the cache check runs first. The resulting severity class is information disclosure: response bodies can contain off-root `.html` file contents, but this path does not show write access, code execution, or arbitrary files without the `.html` constraint.","status":"published","published":"2026-06-26T22:29:29Z","modified":"2026-06-26T22:56:27.767407Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:53.700556Z"},{"id":"OESA-2026-2851","title":"rubygem-yard security update","description":"YARD is a documentation generation tool for the Ruby programming language. It enables the user to generate consistent, usable documentation that can be exported to a number of formats very easily, and also supports extending for custom Ruby constructs such as custom class level definitions.\r\n\r\nSecurity Fix(es):\n\nYARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD\u0026apos;s static cache lookup reads a request path before the router\u0026apos;s path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.(CVE-2026-49342)","status":"published","published":"2026-07-06T11:11:45Z","modified":"2026-08-18T01:21:14.041804562Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:46.823443Z"},{"id":"OESA-2026-2852","title":"rubygem-yard security update","description":"YARD is a documentation generation tool for the Ruby programming language. It enables the user to generate consistent, usable documentation that can be exported to a number of formats very easily, and also supports extending for custom Ruby constructs such as custom class level definitions.\r\n\r\nSecurity Fix(es):\n\nYARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD\u0026apos;s static cache lookup reads a request path before the router\u0026apos;s path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.(CVE-2026-49342)","status":"published","published":"2026-07-06T11:11:45Z","modified":"2026-08-18T01:21:14.076705657Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:46.823443Z"},{"id":"UBUNTU-CVE-2026-49342","description":"YARD is a documentation generation tool for the Ruby programming language. Prior to version 0.9.44, YARD's static cache lookup reads a request path before the router's path cleanup runs. When a server is configured with a document root, a traversal path such as `/../yard-cache-secret.html` is joined against that root and can return a readable sibling `.html` file outside the intended static tree. Version 0.9.44 patches the issue.","status":"published","published":"2026-06-19T20:16:00Z","modified":"2026-10-17T12:58:32.238467466Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T16:56:33.391918Z"}]}}
