Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Test every scanned key that waits on trust
Only head-content and logo-link were tried, so logo, clone-url and
both module-link forms could have been taken from a repository's own
cgitrc unnoticed. A trusted control shows each value would reach the
page, and the refused disk readmes are now checked against a file that
would show if read.
| -rwxr-xr-x | tests/t0303-robustness.sh | 102 |
1 file changed, 79 insertions, 23 deletions
diff --git a/tests/t0303-robustness.sh b/tests/t0303-robustness.sh index c0e7c96..bb405f1 100755 --- a/tests/t0303-robustness.sh +++ b/tests/t0303-robustness.sh @@ -97,36 +97,92 @@ test_expect_success 'a valueless or broken git config in a scanned repository is grep "Ignoring unreadable config in $PWD/scan/a.git/config" err ' -test_expect_success 'only descriptive keys are taken from a scanned repository' ' +# A repository's own cgitrc belongs to whoever can push to it, and each value +# below would reach the page once trusted. clone-url is even expanded from +# the request's environment, a visitor's cookie among it, into a page the +# cache then serves to others. +test_expect_success 'set up a scanned repository setting every key that waits on trust' ' git clone -q --bare repos/rob/.git scan/b.git && + mkrepo scankeys/k 1 && + sub=$(git -C scankeys/k rev-parse HEAD) && + git -C scankeys/k update-index --add --cacheinfo 160000,$sub,sub && + git -C scankeys/k update-index --add --cacheinfo 160000,$sub,other && + git -C scankeys/k commit -q -m gitlinks && + write_script evil-filter.sh <<-\EOF && + echo "evil filter" + cat + EOF + cat >scankeys/k/.git/cgitrc <<-EOF && + desc=from the repo + readme=master:file-1 + about-filter=exec:$PWD/evil-filter.sh + head-content=<script>alert(1)</script> + logo=/evil/logo.png + logo-link=https://evil.example/logo-link + clone-url=https://evil.example/clone + module-link=https://evil.example/module/%s + module-link.sub=https://evil.example/path/%s + EOF + { + echo "virtual-root=/" && + echo "cache-size=0" && + echo "scan-path=$PWD/scankeys" + } >scankeysrc && { - echo "desc=from the repo" && - echo "readme=master:file-1" && - echo "head-content=<script>alert(1)</script>" && - echo "logo-link=javascript:alert(2)" - } >scan/b.git/cgitrc && - cgit_rc gitcfgrc "url=b.git/about/" >tmp 2>err && - grep "from the repo" tmp && - grep "pre class=.plaintext." tmp && - ! grep "alert(" tmp && - grep "Ignoring head-content in $PWD/scan/b.git/: trust-scan-config is not set" err && - grep "Ignoring logo-link in " err + echo "trust-scan-config=1" && + cat scankeysrc + } >scankeystrustrc ' -test_expect_success 'a filesystem readme from a scanned repository is refused' ' - echo "readme=/etc/hosts" >scan/b.git/cgitrc && - cgit_rc gitcfgrc "url=b.git/about/" >tmp 2>err && - grep "Ignoring readme in " err +test_expect_success 'only descriptive keys are taken from a scanned repository' ' + for page in about/ "" tree/ + do + cgit_rc scankeysrc "url=k/$page" >tmp 2>err && + test_grep "^Status: 200" tmp && + test_grep "<p class=.sub desc.>from the repo</p>" tmp && + test_grep ! "evil" tmp && + test_grep ! "alert(" tmp || return 1 + done && + for key in about-filter head-content logo logo-link clone-url module-link module-link.sub + do + test_grep "Ignoring $key in $PWD/scankeys/k/.git/: trust-scan-config is not set" err || return 1 + done && + cgit_rc scankeysrc "url=k/about/" >tmp && + test_grep "<pre class=.plaintext.>1$" tmp +' + +test_expect_success 'with trust-scan-config the same keys apply' ' + sub=$(git -C scankeys/k rev-parse HEAD~1) && + cgit_ok scankeystrustrc "url=k/about/" >tmp && + test_grep "^<script>alert(1)</script></head>$" tmp && + test_grep "<a class=.logo. href=.https://evil.example/logo-link.><img src=./evil/logo.png." tmp && + test_grep "<div id=.about.>evil filter$" tmp && + cgit_ok scankeystrustrc "url=k/" >tmp && + test_grep "https://evil.example/clone" tmp && + cgit_ok scankeystrustrc "url=k/tree/" >tmp && + test_grep "href=.https://evil.example/path/$sub.>sub</a>" tmp && + test_grep "href=.https://evil.example/module/other.>other</a>" tmp ' -# A colon with nothing after it names no ref, so the setting is a path on -# disk and has to wait on trust like any other. -test_expect_success 'a readme ending in a colon is refused like a path on disk' ' +# A path on the server waits on trust, and so does a readme ending in a +# colon, which names no ref and is read as a path too. +test_expect_success 'a filesystem readme from a scanned repository is refused' ' + echo "outside the repository" >outside && echo "outside the repository" >"scan/outside:" && - echo "readme=../outside:" >scan/b.git/cgitrc && - cgit_rc gitcfgrc "url=b.git/about/" >tmp 2>err && - grep "Ignoring readme in " err && - ! grep "outside the repository" tmp + { + echo "trust-scan-config=1" && + cat gitcfgrc + } >gitcfgtrustrc && + for readme in "$PWD/outside" ../outside: + do + echo "readme=$readme" >scan/b.git/cgitrc && + cgit_rc gitcfgrc "url=b.git/about/" >tmp 2>err && + test_grep "^Status: 302" tmp && + test_grep "Ignoring readme in $PWD/scan/b.git/: trust-scan-config is not set" err && + cgit_rc gitcfgtrustrc "url=b.git/about/" >tmp && + test_grep "^Status: 200" tmp && + test_grep "outside the repository" tmp || return 1 + done ' # The readme list is read as a page is served rather than copied at the |
