diff options
context:
space:
mode:
-rw-r--r--MANUAL.txt17
-rw-r--r--custom/cgitrc6
-rw-r--r--source/scan-tree.c26
-rwxr-xr-xtests/t0303-robustness.sh42
4 files changed, 67 insertions, 24 deletions
diff --git a/MANUAL.txt b/MANUAL.txt
index 053bb5f..d1150ef 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -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 &&