From 1456483a0b2b835d326f1a92571166c2c8ee41f6 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Thu, 1 Oct 2026 14:30:23 -1000 Subject: 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. --- source/scan-tree.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'source/scan-tree.c') 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", -- cgit v2.8.0