feat: enforce gitignore protection across bash tool and indexer#39
Merged
feat: enforce gitignore protection across bash tool and indexer#39
Conversation
- Expand bash.ts path-resolution loop to cover all FILE_READ_CMDS (head, tail, grep, sed, awk, less, more, etc.) so gitignored files are blocked across the board, not just for cat - Add FILE_FLAG_CMDS + skipNext pattern to catch grep/awk/sed -f <file> flag-value args that previously bypassed the gitignore check - Remove tee from FILE_READ_CMDS (write command, not a read command) - Fix let → const for commandText (style) - Indexer: skip gitignored files entirely instead of faking content; remove Faker import, is_gitignored payload field, and related code - Tests: add head/tail/grep/sed gitignore-blocking tests; extract setupGitignore helper; add git identity to prevent CI failures
Contributor
There was a problem hiding this comment.
Pull request overview
This PR enforces gitignore protection by expanding the bash tool's file-read command list and gitignore check, and simplifies the indexer to skip gitignored files entirely instead of faking their content. It also renames the index CLI command to indexer.
Changes:
- Expanded bash tool gitignore checks to cover ~20 file-reading commands and added
FILE_FLAG_CMDShandling for-fflag arguments - Simplified indexer to return
nullfor gitignored files instead of usingFaker.fakeContent() - Renamed CLI command from
indextoindexerand added corresponding tests
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/opencode/src/tool/bash.ts | Added FILE_READ_CMDS/FILE_FLAG_CMDS sets and gitignore check for file-reading commands |
| packages/opencode/src/indexer/index.ts | Skip gitignored files entirely instead of faking content; removed Faker import and is_gitignored field |
| packages/opencode/test/tool/bash.test.ts | Added gitignore-blocking tests for head/tail/grep/sed with shared setupGitignore helper |
| packages/opencode/src/cli/cmd/indexer.ts | Renamed IndexCommand to IndexerCommand, command index to indexer |
| packages/opencode/src/index.ts | Updated import/usage to IndexerCommand |
| Makefile | Added indexer to CLI command list |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
packages/opencode/src/tool/bash.ts
Outdated
Comment on lines
+146
to
+151
| let skipNext = false | ||
| for (const arg of command.slice(1)) { | ||
| if (arg.startsWith("-") || (command[0] === "chmod" && arg.startsWith("+"))) continue | ||
| if (skipNext) { | ||
| skipNext = false | ||
| } else if (arg.startsWith("-") || (command[0] === "chmod" && arg.startsWith("+"))) { | ||
| if (FILE_FLAG_CMDS.has(command[0]) && /^-[a-zA-Z]*f/.test(arg)) skipNext = true |
| @@ -740,19 +737,14 @@ export namespace Indexer { | |||
| if (!stat.isFile()) return null | |||
| if (stat.size > maxFileSizeBytes()) return null | |||
|
|
|||
- bash.ts: remove no-op skipNext/FILE_FLAG_CMDS — file args after -f already fall through to gitignore check as regular positional args - indexer/index.ts: restore mtime-based early return so incremental indexing still skips unchanged files (was accidentally removed with the Faker cleanup)
A-Souhei
added a commit
that referenced
this pull request
Mar 13, 2026
Gitignored files now return -stat.mtimeMs instead of null so callers store a sentinel in the mtime cache. This prevents re-running the gitignore check on every startup for every gitignored file (fixing the re-index-from-zero regression introduced in PR #39), while ensuring the mtime early-return never fires for gitignored files — so un-gitignoring a file without touching its mtime still triggers a proper re-index on the next run. No file content is read and no vectors are stored for gitignored files; the gitignore safety property from PR #39 is fully preserved.
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
Closes the known gap where gitignored files could still be read by bash commands other than
cat, and removes the Faker-based content substitution from the indexer in favour of simply skipping gitignored files.Changes
bash.tsFILE_READ_CMDS(head,tail,grep,sed,awk,less,more,sort,uniq,wc,strings,xxd,od,base64,python,python3,node,perl,ruby) — these now all trigger the gitignore checkFILE_FLAG_CMDS(grep,awk,sed) +skipNextpattern so that-f <file>flag-value arguments (e.g.grep -f .env pattern) are also resolved and gitignore-checked; compound flags like-fnhandled via regex/^-[a-zA-Z]*f/teefromFILE_READ_CMDS—teeis a write command (reads stdin, not files by path); its gitignore check was a no-oplet commandText→const commandText(style guide)indexer/index.tsindexFile()now returnsnullimmediately for gitignored files instead of callingFaker.fakeContent()and embedding fake dataimport { Faker },indexedPath,is_gitignoredpayload field, andRETURN 4 → RETURN 3in Redis backendIndexer.search()simplified — no longer needs a ternary to redact real paths for gitignored resultstest/tool/bash.test.tshead,tail,grep,sedsetupGitignore(dir)helper to eliminate 5× duplicated boilerplate-c user.email=test@test.com -c user.name=Testto git setup calls (prevents silent CI failures without a global git config).quiet()from git setup commands so failures surfaceKnown limitations (documented, not fixed — architectural)
cat $SECRET) bypasses static analysis — tree-sitter filters expansion nodesisGitignoredrm .env,mv .env /tmp) are not gitignore-checkedpython -c "...",node -e "...") bypasses the check