UNPKG

obsidian-mcp-server

Version:

MCP server for Obsidian vaults — read, write, search, and surgically edit notes, tags, and frontmatter via the Local REST API plugin. STDIO or Streamable HTTP.

21 lines (13 loc) 2.22 kB
--- summary: "Path-traversal hardening on the URL boundary + Windows-style separator parity across `PathPolicy` and `envPathList`. `obsidian_list_tags` gains an optional `nameRegex` filter with ReDoS guards." breaking: false security: true --- # 3.1.11 — 2026-05-16 ## Security - **`encodeVaultPath` rejects `.` / `..` segments** before URL construction (`validationError`, `reason: 'path_traversal'`). Closes a path-policy bypass: when `OBSIDIAN_READ_PATHS=public/` was configured, an input like `public/../private/secret.md` passed `PathPolicy.assertReadable` (prefix match) and `encodeURIComponent` preserved `..` unchanged (RFC 3986 unreserved), so the upstream Local REST API resolved the traversal. The encoder is now the single chokepoint before URL construction and treats `\` as a segment separator so Windows-style payloads (`..\..\etc`) traverse identically to `../../etc`. - **`obsidian_list_tags` `nameRegex` ReDoS guards** — user-supplied regex is bounded at 256 chars and statically rejected when it contains the canonical nested-quantifier shape (`[+*}]\)[*+{]`, e.g. `(a+)+`, `(.*)*`). JavaScript's `RegExp` engine has no execution timeout, so static rejection is the only defense short of running matches in a worker. Surfaces as typed `regex_unsafe` / `regex_invalid` errors (`ValidationError`). ## Added - **`obsidian_list_tags` `nameRegex` filter** — optional ECMAScript regex post-filters the upstream payload before returning, keeping the LLM-bound response small on vaults with long-tail tag noise. Matched against the bare tag name (no leading `#`); hierarchical tags like `work/tasks` match as the full string. No flags exposed — use character classes (`[Mm]cp`) for case-insensitivity. The result echoes `appliedFilters: { nameRegex }` so the agent can see what filtered the listing. ## Fixed - **`PathPolicy.normalize` and `envPathList` collapse `\` → `/`** before lowercase + slash trimming, so a candidate path like `Public\sub\note.md` now matches a prefix configured as `public/`. Previously the candidate stayed mixed-separator after normalization while the prefix was forward-slash-only, leaving Windows-style paths inconsistently matched against the configured allowlist.