Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.zx2c4.com/cgit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2026-05-04 19:13:13 +0300
committerJason A. Donenfeld <Jason@zx2c4.com>2026-05-04 19:28:27 +0300
commited05b1054df10a2fbc68000cfdd429daec03a456 (patch)
tree21563e3f6537e7db4b26c446edc4d9b1f8cfbccc /shared.c
parente7e8cf1801b06a9f7f5092671b0413689a765fe7 (diff)
cgit: truncate all config values at the newline
These would be largely invalid anyway (save, I suppose, for Linux file paths that technically can contain new lines). The actual problem is that these get printed back out into cached -- and trusted -- cgitrc files, and if the fields have newlines, the git-config way of less trusted users configuring repos on a shared system can be abused to inject newlines, which then can be used to smuggle global options (including filters, which execute code) into the cached cgitrc. So now, only ever duplicate up to the newline, when dealing with these inputs. Reported-by: Adrian Denkiewicz <adrian@doyensec.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'shared.c')
-rw-r--r--shared.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/shared.c b/shared.c
index cec2c81..8173eb8 100644
--- a/shared.c
+++ b/shared.c
@@ -52,6 +52,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
ret = &cgit_repolist.repos[cgit_repolist.count-1];
memset(ret, 0, sizeof(struct cgit_repo));
ret->url = trim_end(url, '/');
+ *strchrnul(ret->url, '\n') = '\0';
ret->name = ret->url;
ret->path = NULL;
ret->desc = cgit_default_repo_desc;
@@ -440,9 +441,10 @@ void cgit_prepare_repo_env(struct cgit_repo * repo)
}
/* Read the content of the specified file into a newly allocated buffer,
- * zeroterminate the buffer and return 0 on success, errno otherwise.
+ * zeroterminate the buffer, truncate at a new line, and return 0 on success,
+ * errno otherwise.
*/
-int readfile(const char *path, char **buf, size_t *size)
+int read_first_line(const char *path, char **buf, size_t *size)
{
int fd, e;
struct stat st;
@@ -463,10 +465,18 @@ int readfile(const char *path, char **buf, size_t *size)
*size = read_in_full(fd, *buf, st.st_size);
e = errno;
(*buf)[*size] = '\0';
+ *strchrnul(*buf, '\n') = '\0';
close(fd);
return (*size == st.st_size ? 0 : e);
}
+char *strdup_first_line(const char *txt)
+{
+ char *t = xstrdup(txt);
+ *strchrnul(t, '\n') = '\0';
+ return t;
+}
+
static int is_token_char(char c)
{
return isalnum(c) || c == '_';