diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Gate html serving behind trust-scan-config
`enable-html-serving` makes the plain page send a repository file as
text/html on the site's own origin, with no nosniff and no policy, so
a scanned repository could switch it on from its git config or cgitrc
without `trust-scan-config` and run script against every visitor. The
warning for a key read from git config also named a null repository,
because `repo->path` was set only after that file had been read.
| -rw-r--r-- | MANUAL.txt | 17 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | custom/cgitrc | 6 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/scan-tree.c | 26 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0303-robustness.sh | 42 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4 files changed, 67 insertions, 24 deletions
@@ -209,7 +209,9 @@ enable-html-serving:: Flag which, when set to "1", lets the /plain handler serve mimetype headers that result in the file being treated as HTML by the browser. When set to "0", such file types are returned instead as text/plain or - application/octet-stream. Default value: "0". See also: + application/octet-stream. In a repository found by "scan-path" the + setting waits on "trust-scan-config", since a page served this way runs + with the site's own origin. Default value: "0". See also: "repo.enable-html-serving". enable-http-clone:: @@ -536,12 +538,13 @@ trust-scan-config:: Flag which, when set to "1", honours every setting in a repository's own cgitrc file and git config found by "scan-path". Those files belong to whoever can push to the repository, so without it the settings that run - a command, put raw markup on the page, place a link or read a file off - the disk are ignored with a warning. Those are the filters, - head-content, module-link, logo, logo-link, clone-url and a readme that - names a file rather than a git object. Settings in the main cgitrc, the - "repo.<option>" form included, never need this. Default value: "0". See - also: "scan-path", "enable-git-config". + a command, put raw markup on the page, serve a file as markup, place a + link or read a file off the disk are ignored with a warning. Those are + the filters, head-content, module-link, logo, logo-link, clone-url, + enable-html-serving and a readme that names a file rather than a git + object. Settings in the main cgitrc, the "repo.<option>" form included, + never need this. Default value: "0". See also: "scan-path", + "enable-git-config". virtual-root:: Url which, if specified, is used as root for all cgit links. cgit then diff --git a/custom/cgitrc b/custom/cgitrc index 5935345..06106c1 100644 --- a/custom/cgitrc +++ b/custom/cgitrc @@ -269,9 +269,9 @@ enable-http-clone=1 # Honour every setting in a repository's own cgitrc and git config found by # scan-path. Those files belong to whoever can push, so without this the -# settings that run a command, put raw markup on the page, place a link or read -# a file off the disk are ignored. The repo.* lines below never need it. Values -# are 0 or 1. Default is 0. +# settings that run a command, put raw markup on the page, serve a file as +# markup, place a link or read a file off the disk are ignored. The repo.* lines +# below never need it. Values are 0 or 1. Default is 0. trust-scan-config=0 # Filter command used to format about-page content. The bundled about-render.lua diff --git a/source/scan-tree.c b/source/scan-tree.c index 97a58e6..035e4e1 100644 --- a/source/scan-tree.c +++ b/source/scan-tree.c @@ -50,9 +50,10 @@ static int is_git_dir(const char *path) /* * A repository's own files belong to whoever can push to it, so the keys - * that run a command, put raw markup on the page, read a file off the disk - * or place a link wait on trust-scan-config. A readme naming a git object, - * the form with a colon, only reads from the repository and passes. + * that run a command, put raw markup on the page, hand a file to the browser + * as markup, read a file off the disk or place a link wait on + * trust-scan-config. A readme naming a git object, the form with a colon, + * only reads from the repository and passes. */ static int trusted_key(const char *name, const char *value) { @@ -61,13 +62,14 @@ static int trusted_key(const char *name, const char *value) if (ctx.cfg.trust_scan_config) return 1; untrusted = - ends_with(name, "-filter") || - !strcmp(name, "head-content") || - !strcmp(name, "module-link") || - starts_with(name, "module-link.") || - !strcmp(name, "logo") || - !strcmp(name, "logo-link") || - !strcmp(name, "clone-url") || + ends_with(name, "-filter") || + !strcmp(name, "head-content") || + !strcmp(name, "module-link") || + starts_with(name, "module-link.") || + !strcmp(name, "logo") || + !strcmp(name, "logo-link") || + !strcmp(name, "clone-url") || + !strcmp(name, "enable-html-serving") || (!strcmp(name, "readme") && !strchr(value, ':')); if (!untrusted) return 1; @@ -203,6 +205,9 @@ static void add_repo(const char *base, struct strbuf *path) } current_repo = cgit_add_repo(relpath.buf); + // Set before the config files are read, since a warning about a key + // found in them names the repository by this path. + current_repo->path = cgit_strdup_first_line(path->buf); if (ctx.cfg.enable_git_config) { // A pusher wrote this file, so a broken one is skipped with a // warning rather than allowed to end the request. @@ -221,7 +226,6 @@ static void add_repo(const char *base, struct strbuf *path) strip_suffix_mem(current_repo->url, &urllen, "/"); current_repo->url[urllen] = '\0'; } - current_repo->path = cgit_strdup_first_line(path->buf); while (!current_repo->owner) { if (!(pwd = getpwuid(st.st_uid))) { fprintf(stderr, "[cgit] Unable to read the owner of %s: %s (%d)\n", diff --git a/tests/t0303-robustness.sh b/tests/t0303-robustness.sh index ea50eac..cb16957 100755 --- a/tests/t0303-robustness.sh +++ b/tests/t0303-robustness.sh @@ -1,8 +1,8 @@ #!/bin/sh -# Regression tests from the September 2026 audit. Each case is a config, -# repository or request that used to crash cgit, end it inside git, or hand -# a visitor something other than what was asked for. +# Regression tests from the audits of September and October 2026. Each case +# is a config, repository or request that used to crash cgit, end it inside +# git, or hand a visitor something other than what was asked for. test_description='Check the audit regressions' . ./setup.sh @@ -112,6 +112,42 @@ test_expect_success 'a filesystem readme from a scanned repository is refused' ' grep "Ignoring readme in " err ' +# A repository served as html runs its pages on the site's own origin, so +# the switch waits on trust like the keys that place markup. The warning has +# to name the repository, which it did not for a key read from git config. +test_expect_success 'html serving from a scanned repository waits on trust' ' + ( + cd repos/rob && + printf "<p>page</p>\n" >page.html && + git add page.html && + git commit -m html + ) && + mkdir -p scan2 && + git clone -q --bare repos/rob/.git scan2/c.git && + git -C scan2/c.git config cgit.enable-html-serving 1 && + { + echo "virtual-root=/" && + echo "cache-size=0" && + echo "enable-git-config=1" && + echo "mimetype.html=text/html" && + echo "scan-path=$PWD/scan2" + } >htmlrc && + CGIT_CONFIG="$PWD/htmlrc" QUERY_STRING="url=c.git/plain/page.html" cgit >tmp 2>err && + grep "^Content-Type: text/plain" tmp && + grep "^X-Content-Type-Options: nosniff" tmp && + grep "Ignoring enable-html-serving in $PWD/scan2/c.git/: trust-scan-config is not set" err +' + +test_expect_success 'with trust-scan-config the same repository serves html' ' + { + echo "trust-scan-config=1" && + cat htmlrc + } >htmltrustrc && + CGIT_CONFIG="$PWD/htmltrustrc" QUERY_STRING="url=c.git/plain/page.html" cgit >tmp && + grep "^Content-Type: text/html" tmp && + ! grep "^X-Content-Type-Options" tmp +' + test_expect_success SYMLINKS 'a symlink cycle under the scan path is entered once' ' ln -s . scan/loop && CGIT_CONFIG="$PWD/gitcfgrc" QUERY_STRING="url=" cgit >tmp && |
