fix: close case-insensitive blocklist bypass and dotfile filter gap#115
Open
sadegh wants to merge 2 commits into
Open
fix: close case-insensitive blocklist bypass and dotfile filter gap#115sadegh wants to merge 2 commits into
sadegh wants to merge 2 commits into
Conversation
…n PathFilter On macOS/Windows (case-insensitive filesystems), the blocklist regex was case-sensitive, allowing paths like .Obsidian/app.json or .GIT/hooks/post-merge to bypass protection against .obsidian and .git. Combined with the fact that dotfiles and extensionless paths (where isFile() returns false) skipped the extension allowlist entirely, this enabled an RCE chain: write a git hook via .Git/hooks/post-merge and execute arbitrary code on the next git pull. Fixes: - simpleGlobMatch: add `i` flag to regex so blocklist matches case-insensitively - isAllowed: deny dotfiles (.bashrc, .zshrc, notes/.env) that don't end with an allowed extension; extensionless non-dotfile paths (directories, Makefile) are still allowed since they can't escape the vault boundary - moveFile: restore isAllowedForListing (intentional for binary file moves) with an explanatory comment; previously changed to isAllowed which broke .png moves Adds regression tests covering all three fixes.
- Reduce pathfilter.ts block comment to one line (why, not how) - Change .md test to .hidden.md — more realistic hidden markdown file - Add comment in moveFile noting that newPath uses isAllowedForListing so dotfile destinations are not blocked (by design for binary moves) - Add test documenting current move_file dotfile-destination behavior
ErycM
added a commit
to ErycM/mcpvault
that referenced
this pull request
May 15, 2026
Anyone cloning this fork (including future-self) should immediately understand (a) why it exists, (b) what's different from upstream, (c) how the cherry-picks were security-audited before pulling them in, (d) how to keep the fork in sync as upstream evolves, and (e) the plan to eventually retire the fork once PRs bitbonsai#113/bitbonsai#115 + our own --allowed-extensions all land upstream. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two security fixes to
PathFilter, both insrc/pathfilter.ts:1. Case-insensitive blocklist bypass (HIGH)
The blocklist regex was case-sensitive, so
.Obsidian/app.jsonand.GIT/hooks/post-mergebypassed the.obsidian/**and.git/**patterns on macOS/Windows (case-insensitive filesystems). Fixed by adding theiflag to the compiled regex insimpleGlobMatch.2. Dotfile filter gap (HIGH)
isFile()returnsfalsefor dotfiles (last component starts with.) because they have a dot at position 0. This caused dotfiles like.bashrcandnotes/.envto skip the extension allowlist entirely. Fixed by explicitly denying dotfiles that don't end with an allowed extension in theelsebranch ofisAllowed.Extensionless non-dotfile paths (
notes,1. Project,attachments/folder) are unaffected — they're treated as directory names and pass through as before.Chained impact: Combining both gaps enabled writing to
.Git/hooks/post-mergeon macOS (capital G bypasses.git/**, no extension bypasses the allowlist), which executes on the nextgit pullin a vault that is also a git repo.Changes
src/pathfilter.ts— two targeted changes, no new methods or helperssrc/pathfilter.test.ts— 6 new regression tests across twodescribeblockssrc/filesystem.ts— comment added tomoveFiledocumenting whyisAllowedForListingis intentional for binary file moves (no logic change)src/filesystem.test.ts— one test documenting themoveFiledotfile-destination behaviorAll 187 tests pass (180 existing + 7 new).
Test coverage
New tests cover:
.obsidian,.OBSIDIAN,.ObSiDiAnpaths.Git,.GITpathsNode_Modulesbypass.bashrc,.zshrc,notes/.envdotfile writes.hidden.md(hidden file with allowed extension — should pass)notes,Makefile,attachments/folder)moveFiledotfile-destination behavior