Skip to content

Commit d02786f

Browse files
Joaldmeta-codesync[bot]
authored andcommitted
Add test for submodule symlink traversal prevention
Summary: Adds test-submodule-symlink-traversal.t which validates that submodule checkout rejects paths that are symlinks. The test clones a repo with a submodule, plants a symlink at the submodule path before checkout, and verifies that `hg up` rejects the operation with "submodule path 'sub' is a symlink". This exercises the submodule path auditing added in the preceding commit. Reviewed By: quark-zju Differential Revision: D95954516 fbshipit-source-id: 2094d4aacfa9154a004b3cc4aff4f9530ae2d1ba
1 parent 6e54512 commit d02786f

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#require git symlink no-eden
2+
3+
Test that submodule checkout audits paths for symlink traversal. If a symlink
4+
exists in the working directory and a submodule shares its name, makedirs()
5+
would follow the symlink without the audit check. This validates Fix 2.
6+
7+
$ . $TESTDIR/git.sh
8+
9+
Create a payload submodule repo:
10+
11+
$ git init -q payload
12+
$ cd payload
13+
$ echo "malicious" > data
14+
$ git add data && git commit -q -m "payload"
15+
$ cd ..
16+
17+
Create a git repo with a submodule named "sub":
18+
19+
$ git init -q repo
20+
$ cd repo
21+
$ echo "readme" > README.md
22+
$ git add README.md && git commit -q -m "init"
23+
24+
$ printf "[submodule \"sub\"]\n path = sub\n url = $TESTTMP/payload\n" > "$TESTTMP/gitmodules_file"
25+
$ GITMODULES_HASH=$(git hash-object -w "$TESTTMP/gitmodules_file")
26+
$ README_HASH=$(git rev-parse HEAD:README.md)
27+
$ PAYLOAD_COMMIT=$(cd "$TESTTMP/payload" && git rev-parse HEAD)
28+
$ ROOT_TREE=$(printf "100644 blob ${GITMODULES_HASH}\t.gitmodules\n100644 blob ${README_HASH}\tREADME.md\n160000 commit ${PAYLOAD_COMMIT}\tsub" | git mktree)
29+
$ SUBMOD_COMMIT=$(echo "Add submodule" | git commit-tree "${ROOT_TREE}" -p HEAD)
30+
$ git update-ref refs/heads/master "$SUBMOD_COMMIT"
31+
$ cd ..
32+
33+
Clone the repo but don't update working copy:
34+
35+
$ hg clone --git "$TESTTMP/repo" workdir --noupdate -q
36+
37+
Plant a symlink "sub" -> ".sl" in the working directory before checkout.
38+
This simulates what happens on a case-insensitive FS when a symlink "Sub"
39+
and submodule "sub" case-fold-collide.
40+
41+
$ ln -s .sl workdir/sub
42+
43+
Now update to master which has the submodule at path "sub". The path auditor
44+
should detect that "sub" is a symlink and reject the operation.
45+
46+
$ cd workdir
47+
$ hg up remote/master
48+
abort: submodule path 'sub' is a symlink
49+
[255]
50+
51+
The working directory only has the planted symlink, no .sl/config compromise:
52+
53+
$ readlink sub
54+
.sl

0 commit comments

Comments
 (0)