{"id":"GHSA-9h9m-rr67-9jpg","summary":"coursevault-preview has a path traversal due to improper base-directory boundary validation","details":"## Summary\n\n`coursevault-preview` versions prior to `0.1.1` contain a path traversal vulnerability in the `resolveSafe` utility. The boundary check used `String.prototype.startsWith(baseDir)` on a normalized path, which does not enforce a directory boundary. An attacker who controls the `relativePath` argument to affected `CoursevaultPreview` methods may be able to read files outside the configured `baseDir` when a sibling directory exists whose name shares the same string prefix.\n\n## Details\n\nThe vulnerable code in `src/utils/errors.ts`:\n\n```ts\nif (!full.startsWith(base)) {   // ← insufficient\n  throw new Error(\"Path escapes the base directory\");\n}\n```\n\nBecause the check is a raw string prefix test rather than a path-boundary test, the following bypass is possible:\n\n```\nbaseDir  = \"/srv/courses\"\npayload  = \"../courses-admin/config.json\"\nresolved = \"/srv/courses-admin/config.json\"\n\n\"/srv/courses-admin/config.json\".startsWith(\"/srv/courses\") // → true ✗\n```\n\nAny file whose absolute path begins with the `baseDir` string — including files in sibling directories that share a name prefix — passes the guard and can be accessed by the caller through affected file-access methods.\n\nThe fix replaces the check with a separator-aware comparison:\n\n```ts\nif (full !== base && !full.startsWith(base + sep)) {\n  throw new Error(\"Path escapes the base directory\");\n}\n```\n\n## Impact\n\nAn application that passes untrusted input as the `relativePath` argument to affected file-access methods may expose file contents outside the intended directory.\n\n1. Attacker control over the `relativePath` parameter.\n2. A sibling directory on the filesystem whose name shares a string prefix with `baseDir`.\n\nThere is no network exposure in the package itself; impact is limited to local file disclosure within the host process's file system permissions.","aliases":["CVE-2026-35613"],"modified":"2026-04-08T00:27:17.222764Z","published":"2026-04-08T00:06:03Z","database_specific":{"nvd_published_at":"2026-04-07T17:16:35Z","cwe_ids":["CWE-22"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-04-08T00:06:03Z"},"references":[{"type":"WEB","url":"https://github.com/moritzmyrz/coursevault-preview/security/advisories/GHSA-9h9m-rr67-9jpg"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-35613"},{"type":"PACKAGE","url":"https://github.com/moritzmyrz/coursevault-preview"}],"affected":[{"package":{"name":"coursevault-preview","ecosystem":"npm","purl":"pkg:npm/coursevault-preview"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.1.1"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-9h9m-rr67-9jpg/GHSA-9h9m-rr67-9jpg.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N"}]}