# HG changeset patch # User Alain Mazy # Date 1768240010 -3600 # Node ID da36804105e3a1fea409fdac0c17bfc2cd1ce024 # Parent c3bc970cf1691a1425f70ef7e95820b166df9566 fix filename argument security issue diff -r c3bc970cf169 -r da36804105e3 NEWS --- a/NEWS Fri Jan 09 12:11:35 2026 +0100 +++ b/NEWS Mon Jan 12 18:46:50 2026 +0100 @@ -11,6 +11,9 @@ * Added new metrics in "/tools/metrics-prometheus": - "orthanc_logged_errors_count" - "orthanc_logged_warnings_count" +* Fixed a security issue where one could hijack HTTP headers in the response + through the `filename` argument of "/.../file" or "/.../archive" routes. + Maintenance ----------- diff -r c3bc970cf169 -r da36804105e3 OrthancFramework/Sources/HttpServer/HttpOutput.cpp --- a/OrthancFramework/Sources/HttpServer/HttpOutput.cpp Fri Jan 09 12:11:35 2026 +0100 +++ b/OrthancFramework/Sources/HttpServer/HttpOutput.cpp Mon Jan 12 18:46:50 2026 +0100 @@ -37,7 +37,7 @@ #include #include #include - +#include #if ORTHANC_ENABLE_CIVETWEB == 1 # if !defined(CIVETWEB_HAS_DISABLE_KEEP_ALIVE) @@ -121,10 +121,18 @@ return isContentCompressible_; } + static std::string SanitizeFileName(const char* filename) + { + const boost::regex pattern("[\r\n\"]"); + + return boost::regex_replace(std::string(filename), pattern, ""); + } + void HttpOutput::StateMachine::SetContentFilename(const char* filename) { - // TODO Escape double quotes - AddHeader("Content-Disposition", "filename=\"" + std::string(filename) + "\""); + std::string sanitized = SanitizeFileName(filename); // since the filename might come from the API, we need to sanitize it to make + // sure it does not add extra headers in the response with e.g: 'filename=toto.dcm"\r\nSet-Cookie:evil=1" + AddHeader("Content-Disposition", "filename=\"" + sanitized + "\""); } void HttpOutput::StateMachine::SetCookie(const std::string& cookie,