XSS in cgit
Jason A. Donenfeld
Jason at zx2c4.com
Wed Jan 13 17:07:12 CET 2016
Krzysztof Katowicz-Kowalewsk has contacted me about two XSS security
vulnerabilities he's found in cgit. Upon investigation the problem
looks a bit deeper than he initially reported, and I found a few more
related vulnerabilities, and I think it generally deserves a bit of
discussion for the best way of patching it.
First (1), the big bad one. In ui-blob.c, we have:
ctx.page.mimetype = ctx.qry.mimetype;
This invokes, from ui-shared.c:
htmlf("Content-Type: %s\n", ctx.page.mimetype);
htmlf("Content-Type: %s; charset=%s\n", ctx.page.mimetype, ctx.page.charset);
A malicious user can pass a mime type such as text/html followed by a
launch an XSS attack. The obvious solution here is to ensure
ctx.page.mimetype doesn't contain new lines, null characters, and
other naughty fields according to the HTTP spec.
Second (2), there's another place where something similar happens:
htmlf("Content-Disposition: inline; filename=\"%s\"\n", ctx.page.filename);
In this case, ctx.page.filename is related to what the user has put in
the git archive. Filenames could contain new lines, resulting in a
Thus, for (1) and (2), I will gladly accept patches that run
parameters to header functions through a sanitation function.
Third (3), a user may upload an HTML page to a git repository. Upon
fetching it via /blob, it will use the inferred mime-type of
text/html. Though I have in the past enjoyed this as a means of
serving HTML from my personal cgit, this is probably not a desired
state of affairs for folks hosting cgit in shared environments, or
using cgit to mirror third party repositories. I therefore believe we
should use either a whitelist or a blacklist for allowed mime-types.
Furthermore, before dumping these blobs, we should add these two
html("Content-Security-Policy: default-src 'none'\n");
I will thus accept patches for (3) that somehow safely limit the
mime-types served for /blob and /plain. If a whitelist,
ctx.qry.mimetype can then be removed entirely. If a blacklist, we can
keep ctx.qry.mimetype, but we'll need to be ensure that there's a
future proof way of preventing XSS via a mimetype blacklist; I'm not
yet convinced such a list can be compiled securely.
Given all this, could somebody remind me why we have both /plain and
/blob handlers? And if it's still necessary to maintain a distinction?
If not, I will gladly accept patches to unify these.
More information about the CGit