diff --git a/context.go b/context.go index 4d87c32683..cb360879c6 100644 --- a/context.go +++ b/context.go @@ -1052,11 +1052,17 @@ func (c *Context) FileFromFS(filepath string, fs http.FileSystem) { http.FileServer(fs).ServeHTTP(c.Writer, c.Request) } +var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") + +func escapeQuotes(s string) string { + return quoteEscaper.Replace(s) +} + // FileAttachment writes the specified file into the body stream in an efficient way // On the client side, the file will typically be downloaded with the given filename func (c *Context) FileAttachment(filepath, filename string) { if isASCII(filename) { - c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+strings.Replace(filename, "\"", "\\\"", -1)+`"`) + c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+escapeQuotes(filename)+`"`) } else { c.Writer.Header().Set("Content-Disposition", `attachment; filename*=UTF-8''`+url.QueryEscape(filename)) } diff --git a/context_test.go b/context_test.go index 54e6dacb7d..180512356d 100644 --- a/context_test.go +++ b/context_test.go @@ -1035,8 +1035,8 @@ func TestContextRenderAttachment(t *testing.T) { func TestContextRenderAndEscapeAttachment(t *testing.T) { w := httptest.NewRecorder() c, _ := CreateTestContext(w) - maliciousFilename := "tampering_field.sh\";dummy=.go" - actualEscapedResponseFilename := "tampering_field.sh\\\";dummy=.go" + maliciousFilename := "tampering_field.sh\"; \\\"; dummy=.go" + actualEscapedResponseFilename := "tampering_field.sh\\\"; \\\\\\\"; dummy=.go" c.Request, _ = http.NewRequest("GET", "/", nil) c.FileAttachment("./gin.go", maliciousFilename)