Skip to content

fix(util): reject symbolic links that alias .gitmodules - #2278

Merged
Byron merged 2 commits into
gitpython-developers:mainfrom
Keerthana-64:gitmodules-symlink-entries
Oct 9, 2026
Merged

Byron merged 2 commits into
gitpython-developers:mainfrom
Keerthana-64:gitmodules-symlink-entries

Conversation

@Keerthana-64

Copy link
Copy Markdown
Contributor

_validate_repo_path mirrors git's verify_path for tree and index entry paths but only ever saw the path, and git's rule there is mode dependent: an entry that makes .gitmodules a symbolic link is refused, since the submodule configuration would then be read through the link, from outside the repository. so IndexFile.add accepted a BaseIndexEntry of mode 120000 named .gitmodules, write_tree serialized the tree, and IndexFile.commit wrote a commit that git read-tree refuses with invalid path and git fsck --strict reports as gitmodulesSymlink, while read_cache and tree_entries_from_data accepted the same entry coming the other way, out of an untrusted repository. the entry mode is now passed down to _validate_repo_path at every boundary that has one, and for a link it rejects each spelling git recognizes: .gitmodules with trailing spaces or periods, the hfs form with ignorable code points removed, and the ntfs short names gitmod~1 through gitmod~4 and gi7eba~1 through gi7eba~9. checked against git update-index --add --cacheinfo on git 2.52.0 for modes 100644, 120000, 160000 and 40000 over the alias corpus, leaving no path that git rejects and gitpython accepts; the name is tested per component like the existing .git rule, so a link below a directory spelled like one of those aliases is refused too.

Note: this change and description were prepared by an AI agent acting for this account's owner.

`_validate_repo_path` mirrors Git's `verify_path` for tree and index entry
paths, but it only ever saw the path. Git's check there is mode dependent: an
entry that makes `.gitmodules` a symbolic link is refused, because the
submodule configuration would then be read through the link, from outside the
repository. That is why `git update-index --add --cacheinfo
120000,<sha>,.gitmodules` fails with `Invalid path`, `git read-tree` fails with
`invalid path`, and `git fsck --strict` reports `gitmodulesSymlink`.

GitPython accepted such an entry in both directions. `IndexFile.add` with a
`BaseIndexEntry` of mode `120000` and path `.gitmodules` was stored,
`write_tree` serialized the tree, and `IndexFile.commit` wrote a commit Git
refuses to read back and a server with `transfer.fsckObjects` set rejects.
Coming the other way, `read_cache` and `tree_entries_from_data` accepted the
same entry out of an untrusted repository's index or tree.

`_validate_repo_path` now takes the entry mode and, for a symbolic link,
rejects every spelling Git recognizes: `.gitmodules` with trailing spaces or
periods, the HFS form with ignorable code points removed, and the NTFS short
names `gitmod~1` through `gitmod~4` and `gi7eba~1` through `gi7eba~9`. The
mode is passed at the boundaries that have one: `write_cache`, `read_cache`,
`write_tree_from_cache`, `_tree_entry_to_baseindexentry`,
`IndexFile._preprocess_add_items`, `IndexFile.add`, `tree_to_stream`,
`tree_entries_from_data` and `TreeModifier.add`. Paths reached without a mode,
such as the directories walked by `IndexFile._iter_expand_paths`, keep their
previous behavior, and a regular file named `.gitmodules` stays valid.

Checked against `git update-index --add --cacheinfo` on git 2.52.0 for modes
`100644`, `120000`, `160000` and `40000` over the alias corpus: no path is
left that Git rejects and GitPython accepts. Like the existing `.git` rule the
name is tested per component, so a link below a directory spelled like one of
those aliases is refused as well, which Git happens to allow. Adds regression
tests in `test/test_index.py` and `test/test_tree.py`; `mypy`,
`basedpyright --warnings` and `ruff` are clean.
@Byron
Byron force-pushed the gitmodules-symlink-entries branch from 1b2615c to c99f923 Compare October 9, 2026 03:40
- speedup additional .gitmodules check
@Byron
Byron force-pushed the gitmodules-symlink-entries branch from c99f923 to 9f56080 Compare October 9, 2026 04:15
@Byron
Byron merged commit f9e74ab into gitpython-developers:main Oct 9, 2026
47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants