From 248deaecbb09af056a81692364e8b14e093361bf Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Thu, 25 Feb 2016 14:56:06 +0000
Subject: [PATCH] Console: Add X-Content-Type-Options header everywhere (ticket
 #1763)

---
 apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java   | 3 +--
 .../i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java | 1 +
 apps/i2ptunnel/jsp/edit.jsp                                    | 1 +
 apps/i2ptunnel/jsp/index.jsp                                   | 1 +
 apps/i2ptunnel/jsp/wizard.jsp                                  | 1 +
 .../src/main/java/net/i2p/imagegen/IdenticonServlet.java       | 1 +
 .../webapp/src/main/java/net/i2p/imagegen/QRServlet.java       | 1 +
 .../src/main/java/net/i2p/imagegen/RandomArtServlet.java       | 1 +
 .../java/src/net/i2p/router/web/CodedIconRendererServlet.java  | 1 +
 apps/routerconsole/jsp/css.jsi                                 | 1 +
 apps/routerconsole/jsp/flags.jsp                               | 3 ++-
 apps/routerconsole/jsp/viewhistory.jsp                         | 1 +
 apps/routerconsole/jsp/viewstat.jsp                            | 1 +
 apps/routerconsole/jsp/viewtheme.jsp                           | 1 +
 apps/routerconsole/jsp/xhr1.jsp                                | 1 +
 apps/susidns/src/jsp/addressbook.jsp                           | 1 +
 apps/susidns/src/jsp/config.jsp                                | 1 +
 apps/susidns/src/jsp/details.jsp                               | 1 +
 apps/susidns/src/jsp/export.jsp                                | 1 +
 apps/susidns/src/jsp/index.jsp                                 | 1 +
 apps/susidns/src/jsp/subscriptions.jsp                         | 1 +
 apps/susimail/src/src/i2p/susi/webmail/WebMail.java            | 1 +
 22 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java
index 95e012b49e..0c85aae962 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java
@@ -378,7 +378,7 @@ class BasicServlet extends HttpServlet
     {   
         if (content.getContentType()!=null && response.getContentType()==null)
             response.setContentType(content.getContentType());
-        
+        response.setHeader("X-Content-Type-Options", "nosniff");
         long lml = content.getLastModified();
         if (lml > 0)
             response.setDateHeader("Last-Modified",lml);
@@ -394,7 +394,6 @@ class BasicServlet extends HttpServlet
         long ct = content.getCacheTime();
         if (ct>=0)
             response.setHeader("Cache-Control", "public, max-age=" + ct);
-
     }
 
     /* ------------------------------------------------------------ */
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index 754ea81487..74688f2c72 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -379,6 +379,7 @@ public class I2PSnarkServlet extends BasicServlet {
         resp.setHeader("Pragma", "no-cache");
         resp.setHeader("X-Frame-Options", "SAMEORIGIN");
         resp.setHeader("X-XSS-Protection", "1; mode=block");
+        resp.setHeader("X-Content-Type-Options", "nosniff");
     }
 
     private void writeMessages(PrintWriter out, boolean isConfigure, String peerString) throws IOException {
diff --git a/apps/i2ptunnel/jsp/edit.jsp b/apps/i2ptunnel/jsp/edit.jsp
index 06eeee3714..21fac1fc36 100644
--- a/apps/i2ptunnel/jsp/edit.jsp
+++ b/apps/i2ptunnel/jsp/edit.jsp
@@ -5,6 +5,7 @@
     // edit pages need script for the delete button 'are you sure'
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %><%@page pageEncoding="UTF-8"
 %><%@page trimDirectiveWhitespaces="true"
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 9e2c064922..bb099231c5 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -8,6 +8,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %><%@page pageEncoding="UTF-8"
 %><%@page trimDirectiveWhitespaces="true"
diff --git a/apps/i2ptunnel/jsp/wizard.jsp b/apps/i2ptunnel/jsp/wizard.jsp
index fefd8a8772..56c6c528a1 100644
--- a/apps/i2ptunnel/jsp/wizard.jsp
+++ b/apps/i2ptunnel/jsp/wizard.jsp
@@ -8,6 +8,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %><%@page pageEncoding="UTF-8"
 %><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
diff --git a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/IdenticonServlet.java b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/IdenticonServlet.java
index 79145cb984..90cc702b9a 100644
--- a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/IdenticonServlet.java
+++ b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/IdenticonServlet.java
@@ -166,6 +166,7 @@ public class IdenticonServlet extends HttpServlet {
 
 			// return image bytes to requester
 			response.setContentType(IDENTICON_IMAGE_MIMETYPE);
+			response.setHeader("X-Content-Type-Options", "nosniff");
 			response.setContentLength(imageBytes.length);
 			response.getOutputStream().write(imageBytes);
 		}
diff --git a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/QRServlet.java b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/QRServlet.java
index bce1a12ede..e11f8d6272 100644
--- a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/QRServlet.java
+++ b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/QRServlet.java
@@ -191,6 +191,7 @@ public class QRServlet extends HttpServlet {
 
 			// return image bytes to requester
 			response.setContentType(IDENTICON_IMAGE_MIMETYPE);
+			response.setHeader("X-Content-Type-Options", "nosniff");
 			response.setContentLength(imageBytes.length);
 			response.getOutputStream().write(imageBytes);
 		}
diff --git a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/RandomArtServlet.java b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/RandomArtServlet.java
index 2ba8f460b4..83dd20b75e 100644
--- a/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/RandomArtServlet.java
+++ b/apps/imagegen/imagegen/webapp/src/main/java/net/i2p/imagegen/RandomArtServlet.java
@@ -62,6 +62,7 @@ public class RandomArtServlet extends HttpServlet {
 					response.setContentType("text/plain");
 					response.setCharacterEncoding("UTF-8");
 				}
+				response.setHeader("X-Content-Type-Options", "nosniff");
 				buf.append(RandomArt.gnutls_key_fingerprint_randomart(h.getData(), "SHA", 256, "", true, html));
 				if (html)
 					buf.append("</body></html>");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/CodedIconRendererServlet.java b/apps/routerconsole/java/src/net/i2p/router/web/CodedIconRendererServlet.java
index 1d71421bf1..c2be82a9d9 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/CodedIconRendererServlet.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/CodedIconRendererServlet.java
@@ -41,6 +41,7 @@ public class CodedIconRendererServlet extends HttpServlet {
          //set as many headers as are common to any outcome
          
          srs.setContentType("image/png");
+         srs.setHeader("X-Content-Type-Options", "nosniff");
          srs.setDateHeader("Expires", I2PAppContext.getGlobalContext().clock().now() + 86400000l);
          srs.setHeader("Cache-Control", "public, max-age=86400");
          OutputStream os = srs.getOutputStream();
diff --git a/apps/routerconsole/jsp/css.jsi b/apps/routerconsole/jsp/css.jsi
index edae862400..c49a15ea62 100644
--- a/apps/routerconsole/jsp/css.jsi
+++ b/apps/routerconsole/jsp/css.jsi
@@ -34,6 +34,7 @@
       response.setHeader("X-Frame-Options", "SAMEORIGIN");
       response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'");
       response.setHeader("X-XSS-Protection", "1; mode=block");
+      response.setHeader("X-Content-Type-Options", "nosniff");
    }
 
    String conNonceParam = request.getParameter("consoleNonce");
diff --git a/apps/routerconsole/jsp/flags.jsp b/apps/routerconsole/jsp/flags.jsp
index 7dcfa50398..b6dcf8184f 100644
--- a/apps/routerconsole/jsp/flags.jsp
+++ b/apps/routerconsole/jsp/flags.jsp
@@ -31,7 +31,8 @@ if (c != null &&
         response.setDateHeader("Last-Modified", lastmod);
         // cache for a day
         response.setDateHeader("Expires", net.i2p.I2PAppContext.getGlobalContext().clock().now() + 86400000l);
-        response.setHeader("Cache-Control", "public, max-age=86400");
+        response.setHeader("Cache-Control", "public, max-age=604800");
+        response.setHeader("X-Content-Type-Options", "nosniff");
     }
     long length = ffile.length();
     if (length > 0)
diff --git a/apps/routerconsole/jsp/viewhistory.jsp b/apps/routerconsole/jsp/viewhistory.jsp
index f4a2cbbffe..41ae6de3bd 100644
--- a/apps/routerconsole/jsp/viewhistory.jsp
+++ b/apps/routerconsole/jsp/viewhistory.jsp
@@ -7,6 +7,7 @@
  * Do not tag this file for translation.
  */
 response.setContentType("text/plain");
+response.setHeader("X-Content-Type-Options", "nosniff");
 String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath();
 try {
     net.i2p.util.FileUtil.readFile("history.txt", base, response.getOutputStream());
diff --git a/apps/routerconsole/jsp/viewstat.jsp b/apps/routerconsole/jsp/viewstat.jsp
index 6a7907ebcb..ce44c5cb79 100644
--- a/apps/routerconsole/jsp/viewstat.jsp
+++ b/apps/routerconsole/jsp/viewstat.jsp
@@ -35,6 +35,7 @@ if ( !rendered && ((rs != null) || fakeBw) ) {
     if ( (rate != null) || (fakeBw) ) {
       java.io.OutputStream cout = response.getOutputStream();
       String format = request.getParameter("format");
+      response.setHeader("X-Content-Type-Options", "nosniff");
       if ("xml".equals(format)) {
         if (!fakeBw) {
           response.setContentType("text/xml");
diff --git a/apps/routerconsole/jsp/viewtheme.jsp b/apps/routerconsole/jsp/viewtheme.jsp
index b60a6b447d..a30ec4fb63 100644
--- a/apps/routerconsole/jsp/viewtheme.jsp
+++ b/apps/routerconsole/jsp/viewtheme.jsp
@@ -21,6 +21,7 @@ if (uri.endsWith(".css")) {
 } else if (uri.endsWith(".svg")) {
   response.setContentType("image/svg+xml");
 }
+response.setHeader("X-Content-Type-Options", "nosniff");
 /*
  * User or plugin themes
  * If the request is for /themes/console/foo/bar/baz,
diff --git a/apps/routerconsole/jsp/xhr1.jsp b/apps/routerconsole/jsp/xhr1.jsp
index b48e824421..06458410b6 100644
--- a/apps/routerconsole/jsp/xhr1.jsp
+++ b/apps/routerconsole/jsp/xhr1.jsp
@@ -8,6 +8,7 @@
    if (request.getParameter("i2p.contextId") != null) {
        session.setAttribute("i2p.contextId", request.getParameter("i2p.contextId"));
    }
+   response.setHeader("X-Content-Type-Options", "nosniff");
 %>
 <jsp:useBean class="net.i2p.router.web.CSSHelper" id="intl" scope="request" />
 <jsp:setProperty name="intl" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
diff --git a/apps/susidns/src/jsp/addressbook.jsp b/apps/susidns/src/jsp/addressbook.jsp
index 14106f87d0..eb940a187b 100644
--- a/apps/susidns/src/jsp/addressbook.jsp
+++ b/apps/susidns/src/jsp/addressbook.jsp
@@ -30,6 +30,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %>
 <%@page pageEncoding="UTF-8"%>
diff --git a/apps/susidns/src/jsp/config.jsp b/apps/susidns/src/jsp/config.jsp
index 27e57a6e90..e6dcbe8dcd 100644
--- a/apps/susidns/src/jsp/config.jsp
+++ b/apps/susidns/src/jsp/config.jsp
@@ -30,6 +30,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %>
 <%@page pageEncoding="UTF-8"%>
diff --git a/apps/susidns/src/jsp/details.jsp b/apps/susidns/src/jsp/details.jsp
index b0663eb5f0..bf5a3fa436 100644
--- a/apps/susidns/src/jsp/details.jsp
+++ b/apps/susidns/src/jsp/details.jsp
@@ -27,6 +27,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %>
 <%@page pageEncoding="UTF-8"%>
diff --git a/apps/susidns/src/jsp/export.jsp b/apps/susidns/src/jsp/export.jsp
index 39440ecf42..d100cd7628 100644
--- a/apps/susidns/src/jsp/export.jsp
+++ b/apps/susidns/src/jsp/export.jsp
@@ -23,6 +23,7 @@
     // http://www.crazysquirrel.com/computing/general/form-encoding.jspx
     if (request.getCharacterEncoding() == null)
         request.setCharacterEncoding("UTF-8");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 %>
 <%@page pageEncoding="UTF-8"%>
 <%@page trimDirectiveWhitespaces="true"%>
diff --git a/apps/susidns/src/jsp/index.jsp b/apps/susidns/src/jsp/index.jsp
index f4b57eba3c..5dbc268c7a 100644
--- a/apps/susidns/src/jsp/index.jsp
+++ b/apps/susidns/src/jsp/index.jsp
@@ -30,6 +30,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %>
 <%@page pageEncoding="UTF-8"%>
diff --git a/apps/susidns/src/jsp/subscriptions.jsp b/apps/susidns/src/jsp/subscriptions.jsp
index 25ec212612..ced96834f6 100644
--- a/apps/susidns/src/jsp/subscriptions.jsp
+++ b/apps/susidns/src/jsp/subscriptions.jsp
@@ -30,6 +30,7 @@
     response.setHeader("X-Frame-Options", "SAMEORIGIN");
     response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
     response.setHeader("X-XSS-Protection", "1; mode=block");
+    response.setHeader("X-Content-Type-Options", "nosniff");
 
 %>
 <%@page pageEncoding="UTF-8"%>
diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
index bdcab5e89d..53ef8fd4f2 100644
--- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
+++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
@@ -1593,6 +1593,7 @@ public class WebMail extends HttpServlet
                 response.setHeader("X-Frame-Options", "SAMEORIGIN");
                 response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'");
                 response.setHeader("X-XSS-Protection", "1; mode=block");
+		response.setHeader("X-Content-Type-Options", "nosniff");
 		RequestWrapper request = new RequestWrapper( httpRequest );
 		
 		SessionObject sessionObject = null;
-- 
GitLab