path: root/apply.c
diff options
authorJeff King <>2018-05-05 00:03:35 (GMT)
committerJeff King <>2018-05-22 03:50:11 (GMT)
commit10ecfa76491e4923988337b2e2243b05376b40de (patch)
tree47fd3ecfa1590f62eaa65dced6aef152a85b33e6 /apply.c
parenteb12dd0c764d2b71bebd5ffffb7379a3835253ae (diff)
verify_path: disallow symlinks in .gitmodules
There are a few reasons it's not a good idea to make .gitmodules a symlink, including: 1. It won't be portable to systems without symlinks. 2. It may behave inconsistently, since Git may look at this file in the index or a tree without bothering to resolve any symbolic links. We don't do this _yet_, but the config infrastructure is there and it's planned for the future. With some clever code, we could make (2) work. And some people may not care about (1) if they only work on one platform. But there are a few security reasons to simply disallow it: a. A symlinked .gitmodules file may circumvent any fsck checks of the content. b. Git may read and write from the on-disk file without sanity checking the symlink target. So for example, if you link ".gitmodules" to "../oops" and run "git submodule add", we'll write to the file "oops" outside the repository. Again, both of those are problems that _could_ be solved with sufficient code, but given the complications in (1) and (2), we're better off just outlawing it explicitly. Note the slightly tricky call to verify_path() in update-index's update_one(). There we may not have a mode if we're not updating from the filesystem (e.g., we might just be removing the file). Passing "0" as the mode there works fine; since it's not a symlink, we'll just skip the extra checks. Signed-off-by: Jeff King <>
Diffstat (limited to 'apply.c')
1 files changed, 2 insertions, 2 deletions
diff --git a/apply.c b/apply.c
index f8bf0bd..b96d375 100644
--- a/apply.c
+++ b/apply.c
@@ -3867,9 +3867,9 @@ static int check_unsafe_path(struct patch *patch)
if (!patch->is_delete)
new_name = patch->new_name;
- if (old_name && !verify_path(old_name))
+ if (old_name && !verify_path(old_name, patch->old_mode))
return error(_("invalid path '%s'"), old_name);
- if (new_name && !verify_path(new_name))
+ if (new_name && !verify_path(new_name, patch->new_mode))
return error(_("invalid path '%s'"), new_name);
return 0;