microsoft / microsoft/vscode

Ignore parser treats literal exclamation marks as negation

Open
#334,711 1 comment 0 reactions 2 assignees Claimed by @dmitrivMS View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Does this issue occur when all extensions are disabled?: Reproduced in the core parser without loading extensions. Browser and Explorer UI verification has not been performed for this report.

- VS Code Version: source `main` at `fc0a9e94576224c89cc08d390b38ab760a261f1f` (`1.138.0` development version)
- OS Version: macOS 27.0 (26A5425a), arm64; Node 24.18.0

The shared `IgnoreFile` parser treats an exclamation mark anywhere in a `.gitignore` pattern as negation, then removes every exclamation mark. This can exclude the intended exception and include a different filename instead.

For example:

```gitignore
*.txt
!important!.txt
```

The first `!` negates the rule; the second belongs to the filename. The parser currently re-includes `important.txt` instead of `important!.txt`.

### Steps to reproduce in the core parser

1. Check out the source revision above and install the repository dependencies.
2. Run `npm run transpile-client`.
3. From the repository root, run:

```sh
node --input-type=module <<'JS'
import { IgnoreFile } from './out/vs/workbench/services/search/common/ignoreFile.js';

const ignore = new IgnoreFile('*.txt\n!important!.txt', '/');
for (const file of ['/important!.txt', '/important.txt']) {
console.log(file, ignore.isArbitraryPathIgnored(file, false));
}
JS
```

| File | Expected `isArbitraryPathIgnored` | Actual |
| --- | --- | --- |
| `/important!.txt` | `false` | `true` |
| `/important.txt` | `true` | `false` |

Other inputs exposing the same classification problem are `important!.txt` (a literal filename to exclude), `\!important.txt` (an escaped leading exclamation mark), and `[!a].txt` (a negated character class).

### Affected code paths

- Browser local-folder file and text search reads `.gitignore` and `.ignore` through this parser in `localFileSearch.ts`.
- Explorer filtering uses the same parser when `explorer.excludeGitIgnore` is enabled, including on desktop (`explorerViewer.ts`).

Native ripgrep search uses a separate implementation. The behavior above was reproduced directly in the shared parser, rather than inferred from a desktop search result.

The [Git pattern documentation](https://git-scm.com/docs/gitignore#_pattern_format) describes negation as a prefix and permits escaping a literal leading exclamation mark. Comparing 27 file, directory, and nested-path cases with `git check-ignore` found 17 mismatches before the proposed fix and none afterward.

Related: #156077 concerns re-including directories. This report reproduces with files at the root and literal exclamation marks, independently of that directory-traversal behavior.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.