Force browser to download content

For example, prevent HTML from being rendered
This commit is contained in:
Marius 2018-02-19 18:28:42 +01:00
parent 21073886e6
commit 6230c23566
2 changed files with 15 additions and 8 deletions

View File

@ -56,7 +56,8 @@ func TestGet(t *testing.T) {
URL: "yes", URL: "yes",
ResHeader: map[string]string{ ResHeader: map[string]string{
"Content-Length": "5", "Content-Length": "5",
"Content-Disposition": `inline;filename="file.jpg\"evil"`, "Content-Type": "application/octet-stream",
"Content-Disposition": `attachment;filename="file.jpg\"evil"`,
}, },
Code: http.StatusOK, Code: http.StatusOK,
ResBody: "hello", ResBody: "hello",
@ -70,9 +71,6 @@ func TestGet(t *testing.T) {
SubTest(t, "EmptyDownload", func(t *testing.T, store *MockFullDataStore) { SubTest(t, "EmptyDownload", func(t *testing.T, store *MockFullDataStore) {
store.EXPECT().GetInfo("yes").Return(FileInfo{ store.EXPECT().GetInfo("yes").Return(FileInfo{
Offset: 0, Offset: 0,
MetaData: map[string]string{
"filename": "file.jpg\"evil",
},
}, nil) }, nil)
handler, _ := NewHandler(Config{ handler, _ := NewHandler(Config{
@ -84,7 +82,7 @@ func TestGet(t *testing.T) {
URL: "yes", URL: "yes",
ResHeader: map[string]string{ ResHeader: map[string]string{
"Content-Length": "0", "Content-Length": "0",
"Content-Disposition": `inline;filename="file.jpg\"evil"`, "Content-Disposition": `attachment`,
}, },
Code: http.StatusNoContent, Code: http.StatusNoContent,
ResBody: "", ResBody: "",

View File

@ -542,17 +542,26 @@ func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request)
// Set headers before sending responses // Set headers before sending responses
w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10)) w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10))
w.Header().Set("Content-Type", "application/octet-stream")
// Force browsers to download the file instead of displaying it inline.
// Otherwise someone could upload malicious HTML which would then be
// executed if a victim visits this URL.
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
// TODO: Consider lifting this limitation and allow e.g. images to be shown
// TODO: Consider pulling Content-Type from meta data
if filename, ok := info.MetaData["filename"]; ok { if filename, ok := info.MetaData["filename"]; ok {
w.Header().Set("Content-Disposition", "inline;filename="+strconv.Quote(filename)) w.Header().Set("Content-Disposition", "attachment;filename="+strconv.Quote(filename))
} else {
w.Header().Set("Content-Disposition", "attachment")
} }
// Do not do anything if no data is stored yet. // If no data has been uploaded yet, respond with an empty "204 No Content" status.
if info.Offset == 0 { if info.Offset == 0 {
handler.sendResp(w, r, http.StatusNoContent) handler.sendResp(w, r, http.StatusNoContent)
return return
} }
// Get reader
src, err := handler.composer.GetReader.GetReader(id) src, err := handler.composer.GetReader.GetReader(id)
if err != nil { if err != nil {
handler.sendError(w, r, err) handler.sendError(w, r, err)