changeset 5469:514fd39f87a8

improved handling of X-Content-Type-Options
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 18 Dec 2023 21:06:41 +0100
parents 47334eeaaa1a
children 1dc6e4b7f5d8
files OrthancFramework/Sources/HttpServer/HttpOutput.cpp OrthancFramework/Sources/HttpServer/HttpOutput.h OrthancServer/Resources/Samples/ImportDicomFiles/ImportDicomFiles.py OrthancServer/Resources/Samples/ImportDicomFiles/OrthancImport.py
diffstat 4 files changed, 21 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Mon Dec 18 10:44:11 2023 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Mon Dec 18 21:06:41 2023 +0100
@@ -44,6 +44,8 @@
 #  endif
 #endif
 
+static const std::string X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
+
 
 namespace Orthanc
 {
@@ -58,7 +60,8 @@
     contentLength_(0),
     contentPosition_(0),
     keepAlive_(isKeepAlive),
-    keepAliveTimeout_(keepAliveTimeout)
+    keepAliveTimeout_(keepAliveTimeout),
+    hasXContentTypeOptions_(false)
   {
   }
 
@@ -142,6 +145,11 @@
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
     }
 
+    if (header == X_CONTENT_TYPE_OPTIONS)
+    {
+      hasXContentTypeOptions_ = true;
+    }
+
     headers_.push_back(header + ": " + value + "\r\n");
   }
 
@@ -178,9 +186,6 @@
 
     if (state_ == State_WritingHeader)
     {
-      // always include this header to prevent MIME Confusion attacks: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-content-type-options
-      AddHeader("X-Content-Type-Options", "nosniff");
-
       // Send the HTTP header before writing the body
 
       stream_.OnHttpStatusReceived(status_);
@@ -220,6 +225,13 @@
         s += *it;
       }
 
+      if (!hasXContentTypeOptions_)
+      {
+        // Always include this header to prevent MIME Confusion attacks:
+        // https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-content-type-options
+        s += X_CONTENT_TYPE_OPTIONS + ": nosniff\r\n";
+      }
+
       if (status_ != HttpStatus_200_Ok)
       {
         hasContentLength_ = false;
@@ -369,8 +381,8 @@
 
     if (messageSize > 0)
     {
-      // we assume that the body always contains a json description of the error
-      stateMachine_.SetContentType("application/json");
+      // Assume that the body always contains a textual description of the error
+      stateMachine_.SetContentType("text/plain");
     }
 
     stateMachine_.SendBody(message, messageSize);
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.h	Mon Dec 18 10:44:11 2023 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.h	Mon Dec 18 21:06:41 2023 +0100
@@ -64,6 +64,7 @@
       bool keepAlive_;
       unsigned int keepAliveTimeout_;
       std::list<std::string> headers_;
+      bool hasXContentTypeOptions_;
 
       std::string multipartBoundary_;
       std::string multipartContentType_;
--- a/OrthancServer/Resources/Samples/ImportDicomFiles/ImportDicomFiles.py	Mon Dec 18 10:44:11 2023 +0100
+++ b/OrthancServer/Resources/Samples/ImportDicomFiles/ImportDicomFiles.py	Mon Dec 18 21:06:41 2023 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Orthanc - A Lightweight, RESTful DICOM Store
 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
--- a/OrthancServer/Resources/Samples/ImportDicomFiles/OrthancImport.py	Mon Dec 18 10:44:11 2023 +0100
+++ b/OrthancServer/Resources/Samples/ImportDicomFiles/OrthancImport.py	Mon Dec 18 21:06:41 2023 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Orthanc - A Lightweight, RESTful DICOM Store
 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics