Skip to content

fix: match sensitive file names case-insensitively - #3

Merged
rustfuture merged 1 commit into
mainfrom
fix/policy-gap
Sep 11, 2026
Merged

rustfuture merged 1 commit into
mainfrom
fix/policy-gap

Conversation

@rustfuture

Copy link
Copy Markdown
Owner

Gap (real, reproduced on macOS)

After b58b429, walk and update_file share is_sensitive_file_name, but the match stayed case-sensitive. On a case-insensitive filesystem the two paths disagree for the same on-disk file:

  • Index::build walks the real directory entry credentials.json → excluded.
  • update_file(root, "CREDENTIALS.JSON") resolves the same file through the case-insensitive FS, the name predicate misses, and the sensitive content is indexed under the alias key.

Reachable via delete+add git status handling (case-only renames use rename detection, but D+A paths exist) or any direct update_file caller.

Repro (pre-fix): full scan search("aliascanary") == [], update search == ["CREDENTIALS.JSON"].

Fix

One line: ASCII-lowercase the name inside the single shared predicate (src/lib.rs). This keeps the policy shared and makes walk/update agree on both case-sensitive and case-insensitive filesystems, and also closes uppercase variants like A.PEM/CLIENT.P12 on Linux.

Tests

  • sensitive_names_match_case_insensitively — uppercase sensitive variants, and near-misses stay indexable.
  • full_scan_and_update_agree_on_case_variant_sensitive_names — actual uppercase files, walk vs update.
  • update_file_case_alias_cannot_bypass_sensitive_policy — the case-alias bypass; verified to FAIL before the fix on this machine.

Verification

cargo fmt --check                                               OK
cargo check --locked --all-targets                              OK
cargo clippy --locked --all-targets -- -D warnings              OK
cargo test --locked                                             11 passed (was 8)
python3 evaluation/evaluate.py                                  recall_at_5=1.0 mrr=1.0
```

Also ran a temporary differential sweep over 37 paths (nested credentials/service-account, .p12/.pfx/.keystore, symlink parent and symlink leaf, hidden/build dirs, previously-indexed excluded files) comparing full walk vs sequential update_file: the case alias was the only divergence; it was removed from the worktree before commit.

walk excluded credentials.json on a case-insensitive filesystem while
update_file("CREDENTIALS.JSON") indexed the same on-disk file, so a full
scan and an incremental update could disagree. Normalize the shared
name predicate with ASCII lowercase.

Regression tests cover uppercase variants through patch and delete-plus-add
update paths, and the case-alias bypass.
@rustfuture
rustfuture merged commit 47ffef9 into main Sep 11, 2026
2 checks passed
@rustfuture
rustfuture deleted the fix/policy-gap branch September 11, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant