Skip to content

Commit 657feb3

Browse files
committed
Adding default security filters for browsers to handle anything that might come up in the future.
1 parent e9acca0 commit 657feb3

File tree

5 files changed

+207
-2
lines changed

5 files changed

+207
-2
lines changed

jetty9/src/com/thoughtworks/go/server/Jetty9Server.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import javax.management.MBeanServer;
4242
import javax.net.ssl.SSLSocketFactory;
4343
import javax.servlet.ServletException;
44+
import javax.servlet.SessionCookieConfig;
4445
import javax.servlet.UnavailableException;
4546
import javax.servlet.http.HttpServletRequest;
4647
import javax.servlet.http.HttpServletResponse;
@@ -102,7 +103,9 @@ public void addExtraJarsToClasspath(String extraClasspath) {
102103

103104
@Override
104105
public void setCookieExpirePeriod(int cookieExpirePeriod) {
105-
webAppContext.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(cookieExpirePeriod);
106+
SessionCookieConfig cookieConfig = webAppContext.getSessionHandler().getSessionManager().getSessionCookieConfig();
107+
cookieConfig.setHttpOnly(true);
108+
cookieConfig.setMaxAge(cookieExpirePeriod);
106109
}
107110

108111
@Override
@@ -141,7 +144,17 @@ public GoServerWelcomeFileHandler() {
141144

142145
private class Handler extends AbstractHandler {
143146
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
144-
if (target.equals("/")) {
147+
148+
if ("/go".equals(request.getPathInfo()) || request.getPathInfo().startsWith("/go/")) {
149+
return;
150+
}
151+
152+
response.setHeader("X-XSS-Protection", "1; mode=block");
153+
response.setHeader("X-Content-Type-Options", "nosniff");
154+
response.setHeader("X-Frame-Options", "SAMEORIGIN");
155+
response.setHeader("X-UA-Compatible", "chrome=1");
156+
157+
if ("/".equals(target)) {
145158
response.setHeader("Location", GoConstants.GO_URL_CONTEXT + "/home");
146159
response.setStatus(301);
147160
response.setHeader("Content-Type", "text/html");

jetty9/test/com/thoughtworks/go/server/Jetty9ServerTest.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@
3535
import org.mockito.ArgumentCaptor;
3636

3737
import javax.net.ssl.SSLSocketFactory;
38+
import javax.servlet.http.HttpServletRequest;
39+
import javax.servlet.http.HttpServletResponse;
3840
import java.io.File;
3941
import java.io.IOException;
42+
import java.io.PrintWriter;
4043
import java.util.Iterator;
4144
import java.util.List;
4245

@@ -146,6 +149,82 @@ public void shouldAddWelcomeRequestHandler() throws Exception {
146149
assertThat(welcomeFileHandler.getContextPath(), is("/"));
147150
}
148151

152+
@Test
153+
public void shouldAddDefaultHeadersForRootContext() throws Exception {
154+
ArgumentCaptor<HandlerCollection> captor = ArgumentCaptor.forClass(HandlerCollection.class);
155+
jetty9Server.configure();
156+
157+
verify(server, times(1)).setHandler(captor.capture());
158+
HandlerCollection handlerCollection = captor.getValue();
159+
Jetty9Server.GoServerWelcomeFileHandler handler = (Jetty9Server.GoServerWelcomeFileHandler)handlerCollection.getHandlers()[0];
160+
Handler rootPathHandler = handler.getHandler();
161+
162+
HttpServletResponse response = mock(HttpServletResponse.class);
163+
when(response.getWriter()).thenReturn(mock(PrintWriter.class));
164+
165+
HttpServletRequest request = mock(HttpServletRequest.class);
166+
when(request.getPathInfo()).thenReturn("/");
167+
168+
rootPathHandler.handle("/", mock(Request.class), request, response);
169+
170+
verify(response).setHeader("X-XSS-Protection", "1; mode=block");
171+
verify(response).setHeader("X-Content-Type-Options", "nosniff");
172+
verify(response).setHeader("X-Frame-Options", "SAMEORIGIN");
173+
verify(response).setHeader("X-UA-Compatible", "chrome=1");
174+
175+
}
176+
177+
@Test
178+
public void shouldSkipDefaultHeadersIfContextPathIsGoRootPath() throws Exception {
179+
ArgumentCaptor<HandlerCollection> captor = ArgumentCaptor.forClass(HandlerCollection.class);
180+
jetty9Server.configure();
181+
182+
verify(server, times(1)).setHandler(captor.capture());
183+
HandlerCollection handlerCollection = captor.getValue();
184+
Jetty9Server.GoServerWelcomeFileHandler handler = (Jetty9Server.GoServerWelcomeFileHandler)handlerCollection.getHandlers()[0];
185+
Handler rootPathHandler = handler.getHandler();
186+
187+
HttpServletResponse response = mock(HttpServletResponse.class);
188+
when(response.getWriter()).thenReturn(mock(PrintWriter.class));
189+
190+
HttpServletRequest request = mock(HttpServletRequest.class);
191+
when(request.getPathInfo()).thenReturn("/go");
192+
193+
rootPathHandler.handle("/go", mock(Request.class), request, response);
194+
195+
verify(response, never()).setHeader("X-XSS-Protection", "1; mode=block");
196+
verify(response, never()).setHeader("X-Content-Type-Options", "nosniff");
197+
verify(response, never()).setHeader("X-Frame-Options", "SAMEORIGIN");
198+
verify(response, never()).setHeader("X-UA-Compatible", "chrome=1");
199+
200+
}
201+
202+
203+
@Test
204+
public void shouldSkipDefaultHeadersIfContextPathIsAnyOtherUrlWithinGo() throws Exception {
205+
ArgumentCaptor<HandlerCollection> captor = ArgumentCaptor.forClass(HandlerCollection.class);
206+
jetty9Server.configure();
207+
208+
verify(server, times(1)).setHandler(captor.capture());
209+
HandlerCollection handlerCollection = captor.getValue();
210+
Jetty9Server.GoServerWelcomeFileHandler handler = (Jetty9Server.GoServerWelcomeFileHandler)handlerCollection.getHandlers()[0];
211+
Handler rootPathHandler = handler.getHandler();
212+
213+
HttpServletResponse response = mock(HttpServletResponse.class);
214+
when(response.getWriter()).thenReturn(mock(PrintWriter.class));
215+
216+
HttpServletRequest request = mock(HttpServletRequest.class);
217+
when(request.getPathInfo()).thenReturn("/go/pipelines");
218+
219+
rootPathHandler.handle("/go/pipelines", mock(Request.class), request, response);
220+
221+
verify(response, never()).setHeader("X-XSS-Protection", "1; mode=block");
222+
verify(response, never()).setHeader("X-Content-Type-Options", "nosniff");
223+
verify(response, never()).setHeader("X-Frame-Options", "SAMEORIGIN");
224+
verify(response, never()).setHeader("X-UA-Compatible", "chrome=1");
225+
226+
}
227+
149228
@Test
150229
public void shouldAddResourceHandlerForAssets() throws Exception {
151230
ArgumentCaptor<HandlerCollection> captor = ArgumentCaptor.forClass(HandlerCollection.class);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2016 ThoughtWorks, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.thoughtworks.go.server.web;
18+
19+
import javax.servlet.*;
20+
import javax.servlet.http.HttpServletResponse;
21+
import java.io.IOException;
22+
23+
public class DefaultHeadersFilter implements Filter {
24+
public void destroy() {
25+
}
26+
27+
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
28+
HttpServletResponse response = (HttpServletResponse) resp;
29+
30+
response.setHeader("X-XSS-Protection", "1; mode=block");
31+
response.setHeader("X-Content-Type-Options", "nosniff");
32+
response.setHeader("X-Frame-Options", "SAMEORIGIN");
33+
response.setHeader("X-UA-Compatible", "chrome=1");
34+
35+
chain.doFilter(req, resp);
36+
}
37+
38+
public void init(FilterConfig config) throws ServletException {
39+
// No default config
40+
}
41+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2016 ThoughtWorks, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.thoughtworks.go.server.web;
18+
19+
import org.junit.Before;
20+
import org.junit.Test;
21+
import org.mockito.Mock;
22+
23+
import javax.servlet.FilterChain;
24+
import javax.servlet.ServletRequest;
25+
import javax.servlet.http.HttpServletResponse;
26+
27+
import static org.mockito.Mockito.verify;
28+
import static org.mockito.MockitoAnnotations.initMocks;
29+
30+
public class DefaultHeadersFilterTest {
31+
32+
@Mock
33+
private HttpServletResponse response;
34+
@Mock
35+
private FilterChain chain;
36+
@Mock
37+
private ServletRequest request;
38+
39+
@Before
40+
public void setUp() throws Exception {
41+
initMocks(this);
42+
}
43+
44+
@Test
45+
public void shouldAddDefaultHeaders() throws Exception {
46+
DefaultHeadersFilter filter = new DefaultHeadersFilter();
47+
filter.doFilter(request, response, chain);
48+
49+
verify(response).setHeader("X-XSS-Protection", "1; mode=block");
50+
verify(response).setHeader("X-Content-Type-Options", "nosniff");
51+
verify(response).setHeader("X-Frame-Options", "SAMEORIGIN");
52+
verify(response).setHeader("X-UA-Compatible", "chrome=1");
53+
}
54+
55+
@Test
56+
public void shouldPropogateFilterChain() throws Exception {
57+
DefaultHeadersFilter filter = new DefaultHeadersFilter();
58+
filter.doFilter(request, response, chain);
59+
60+
verify(chain).doFilter(request, response);
61+
}
62+
}

server/webapp/WEB-INF/web.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
<filter-class>com.thoughtworks.go.server.web.BackupFilter</filter-class>
3131
</filter>
3232

33+
<filter>
34+
<filter-name>Default headers filter</filter-name>
35+
<filter-class>com.thoughtworks.go.server.web.DefaultHeadersFilter</filter-class>
36+
</filter>
37+
3338
<filter>
3439
<filter-name>Spring security Filter Chain Proxy</filter-name>
3540
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@@ -54,6 +59,11 @@
5459
<url-pattern>/*</url-pattern>
5560
</filter-mapping>
5661

62+
<filter-mapping>
63+
<filter-name>Default headers filter</filter-name>
64+
<url-pattern>/*</url-pattern>
65+
</filter-mapping>
66+
5767
<filter-mapping>
5868
<filter-name>Spring security Filter Chain Proxy</filter-name>
5969
<url-pattern>/*</url-pattern>

0 commit comments

Comments
 (0)