This is an automated email from the ASF dual-hosted git repository. prabhjyotsingh pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push: new 106f127 [ZEPPELIN-4471] Add HTTP security header X-Content-Type-Options 106f127 is described below commit 106f12796a6b54a1dbac426b4d3754084ce816ef Author: Vipin Rathor <v.rat...@gmail.com> AuthorDate: Mon Dec 9 11:14:01 2019 -0800 [ZEPPELIN-4471] Add HTTP security header X-Content-Type-Options ### What is this PR for? This PR adds support for X-Content-Type-Options response header. As per Security best practices, Zeppelin server should have an option to include "X-Content-Type-Options: nosniff" header in HTTP response. This header prevents MIME type sniffing attack on web server. ### What type of PR is it? [Improvement] ### Todos * [x] - Document the new option ### What is the Jira issue? https://issues.apache.org/jira/browse/ZEPPELIN-4471 ### How should this be tested? * Travis CI should pass * Manual verification HTTP response header before patch (missing X-Content-Type-Options header): ``` $ curl -i `hostname -f`:8080 HTTP/1.1 200 OK Date: Sat, 07 Dec 2019 00:43:34 GMT Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE X-FRAME-OPTIONS: SAMEORIGIN X-XSS-Protection: 1 Last-Modified: Sat, 07 Dec 2019 00:35:42 GMT Content-Type: text/html Accept-Ranges: bytes Content-Length: 4660 Server: Jetty(9.4.18.v20190429) ``` HTTP response header after patch (notice the X-Content-Type-Options header): ``` $ curl -i `hostname -f`:8080 HTTP/1.1 200 OK Date: Sat, 07 Dec 2019 01:30:37 GMT Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE X-FRAME-OPTIONS: SAMEORIGIN X-XSS-Protection: 1 X-Content-Type-Options: nosniff Last-Modified: Sat, 07 Dec 2019 01:28:44 GMT Content-Type: text/html Accept-Ranges: bytes Content-Length: 4660 Server: Jetty(9.4.18.v20190429) ``` ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? Yes Author: Vipin Rathor <v.rat...@gmail.com> Closes #3544 from VipinRathor/ZEPPELIN-4471 and squashes the following commits: 96319519b [Vipin Rathor] Add documentation for X-Content-Type-Options Header support fe353e9d5 [Vipin Rathor] Incorporating review comments 89d6fb2a5 [Vipin Rathor] ZEPPELIN-4471 - Add HTTP security header X-Content-Type-Options Change-Id: Ib8b14052ae08a3caa9039059fc8aa8d48e66fbe7 --- conf/zeppelin-site.xml.template | 8 ++++++++ docs/setup/security/http_security_headers.md | 14 ++++++++++++++ .../org/apache/zeppelin/conf/ZeppelinConfiguration.java | 5 +++++ .../main/java/org/apache/zeppelin/server/CorsFilter.java | 1 + 4 files changed, 28 insertions(+) diff --git a/conf/zeppelin-site.xml.template b/conf/zeppelin-site.xml.template index e02722b..6a45b0b 100755 --- a/conf/zeppelin-site.xml.template +++ b/conf/zeppelin-site.xml.template @@ -555,6 +555,14 @@ <!-- <property> + <name>zeppelin.server.xcontent.type.options</name> + <value>nosniff</value> + <description>The HTTP X-Content-Type-Options response header helps to prevent MIME type sniffing attacks. It directs the browser to honor the type specified in the Content-Type header, rather than trying to determine the type from the content itself. The default value "nosniff" is really the only meaningful value. This header is supported on all browsers except Safari and Safari on iOS.</description> +</property> +--> + +<!-- +<property> <name>zeppelin.interpreter.callback.portRange</name> <value>10000:10010</value> </property> diff --git a/docs/setup/security/http_security_headers.md b/docs/setup/security/http_security_headers.md index ad4aeef..9fcb9f4 100644 --- a/docs/setup/security/http_security_headers.md +++ b/docs/setup/security/http_security_headers.md @@ -93,6 +93,20 @@ You can choose appropriate value from below. * `SAMEORIGIN` * `ALLOW-FROM uri` +## Setting up X-Content-Type-Options Header + +The HTTP X-Content-Type-Options response header helps to prevent MIME type sniffing attacks. It directs the browser to honor the type specified in the Content-Type header, rather than trying to determine the type from the content itself. The default value `nosniff` is really the only meaningful value. This header is supported on all browsers except Safari and Safari on iOS. + +Zeppelin server will add this header to HTTP response by default. The following property needs to be updated in the zeppelin-site.xml in order to change X-Content-Type-Options header value. + +```xml +<property> + <name>zeppelin.server.xcontent.type.options</name> + <value>nosniff</value> + <description>The HTTP X-Content-Type-Options response header helps to prevent MIME type sniffing attacks.</description> +</property> +``` + ## Setting up Server Header Security conscious organisations does not want to reveal the Application Server name and version to prevent finding this information easily by Attacker while fingerprinting the Application. The exact version number can tell an Attacker if the current Application Server is patched for or vulnerable to certain publicly known CVE associated to it. diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java index db6f09d..ad1e0a3 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java @@ -631,6 +631,10 @@ public class ZeppelinConfiguration extends XMLConfiguration { return getString(ConfVars.ZEPPELIN_SERVER_X_XSS_PROTECTION); } + public String getXContentTypeOptions() { + return getString(ConfVars.ZEPPELIN_SERVER_X_CONTENT_TYPE_OPTIONS); + } + public String getStrictTransport() { return getString(ConfVars.ZEPPELIN_SERVER_STRICT_TRANSPORT); } @@ -885,6 +889,7 @@ public class ZeppelinConfiguration extends XMLConfiguration { ZEPPELIN_SERVER_AUTHORIZATION_HEADER_CLEAR("zeppelin.server.authorization.header.clear", true), ZEPPELIN_SERVER_STRICT_TRANSPORT("zeppelin.server.strict.transport", "max-age=631138519"), ZEPPELIN_SERVER_X_XSS_PROTECTION("zeppelin.server.xxss.protection", "1"), + ZEPPELIN_SERVER_X_CONTENT_TYPE_OPTIONS("zeppelin.server.xcontent.type.options", "nosniff"), ZEPPELIN_SERVER_KERBEROS_KEYTAB("zeppelin.server.kerberos.keytab", ""), ZEPPELIN_SERVER_KERBEROS_PRINCIPAL("zeppelin.server.kerberos.principal", ""), diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/CorsFilter.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/CorsFilter.java index 67ada6a..8688716 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/server/CorsFilter.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/CorsFilter.java @@ -76,6 +76,7 @@ public class CorsFilter implements Filter { response.setHeader("Strict-Transport-Security", zeppelinConfiguration.getStrictTransport()); } response.setHeader("X-XSS-Protection", zeppelinConfiguration.getXxssProtection()); + response.setHeader("X-Content-Type-Options", zeppelinConfiguration.getXContentTypeOptions()); } @Override