diff --git a/README.md b/README.md index 82b012c..10b1f61 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ logs.) * `file`: an arbitrary file to attach to the report. Saved as-is to disk, and a link is added to the github issue. The filename must be in the format `name.ext`, where `name` contains only alphanumerics, `-` or `_`, and `ext` - is one of `jpg`, `png`, `txt` or `json`. + is one of `jpg`, `png`, `txt`, `json`, `txt.gz` or `json.gz`. Not supported for the JSON upload encoding. diff --git a/changelog.d/75.feature b/changelog.d/75.feature new file mode 100644 index 0000000..b13ca06 --- /dev/null +++ b/changelog.d/75.feature @@ -0,0 +1 @@ +Allow gzipped json & txt files to be uploaded as attachments to rageshakes. diff --git a/logserver.go b/logserver.go index 235fcdd..70015ef 100644 --- a/logserver.go +++ b/logserver.go @@ -104,8 +104,12 @@ func serveFile(w http.ResponseWriter, r *http.Request, path string) { // // Unlike mime.TypeByExtension, the results are limited to a set of types which // should be safe to serve to a browser without introducing XSS vulnerabilities. +// +// We handle all of the extensions we allow on files uploaded as attachments to a rageshake, +// plus 'log' which we do not allow as an attachment, but is used as the extension when serving +// the logs submitted as `logs` or `compressed-log`. func extensionToMimeType(path string) string { - if strings.HasSuffix(path, ".txt") { + if strings.HasSuffix(path, ".txt") || strings.HasSuffix(path, ".log") { // anyone uploading text in anything other than utf-8 needs to be // re-educated. return "text/plain; charset=utf-8" @@ -236,7 +240,13 @@ func addToArchive(targz *tar.Writer, dfilename string, filename string) error { } func serveGzippedFile(w http.ResponseWriter, r *http.Request, path string, size int64) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") + cType := "text/plain; charset=utf-8" + if strings.HasSuffix(path, ".gz") { + // Guess the mime type from the extension as we do in serveFile, but without + // the .gz header (in practice, either plain text or application/json). + cType = extensionToMimeType(path[:len(path)-len(".gz")]) + } + w.Header().Set("Content-Type", cType) acceptsGzip := false splitRune := func(s rune) bool { return s == ' ' || s == '\t' || s == '\n' || s == ',' } diff --git a/submit.go b/submit.go index b733cdb..6e4b8f2 100644 --- a/submit.go +++ b/submit.go @@ -405,12 +405,13 @@ func formPartToPayload(field, data string, p *payload) { // * a limited set of extensions. We are careful to limit the content-types // we will serve the files with, but somebody might accidentally point an // Apache or nginx at the upload directory, which would serve js files as -// application/javascript and open XSS vulnerabilities. +// application/javascript and open XSS vulnerabilities. We also allow gzipped +// text and json on the same basis (there's really no sense allowing gzipped images). // // * no silly characters (/, ctrl chars, etc) // // * nothing starting with '.' -var filenameRegexp = regexp.MustCompile(`^[a-zA-Z0-9_-]+\.(jpg|png|txt|json)$`) +var filenameRegexp = regexp.MustCompile(`^[a-zA-Z0-9_-]+\.(jpg|png|txt|json|txt\.gz|json\.gz)$`) // saveFormPart saves a file upload to the report directory. //