8000 Append SecureHeaders CSP value when upstream already provides CSP by lly835 · Pull Request #4079 · spring-cloud/spring-cloud-gateway · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The `SecureHeaders` `GatewayFilter` factory adds a number of headers to the resp

The following headers (shown with their default values) are added:

NOTE: If a `Content-Security-Policy` header is already present (for example, from an upstream service), the value configured by `SecureHeaders` is appended as an additional `Content-Security-Policy` header value.
Other secure headers are only added when absent.

* `X-Xss-Protection:1 (mode=block`)
* `Strict-Transport-Security (max-age=631138519`)
* `X-Frame-Options (DENY)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ private void applySecurityHeaders(HttpHeaders responseHeaders, Set<String> heade
addHeaderIfEnabled(responseHeaders, headersToAddToResponse, SecureHeadersProperties.REFERRER_POLICY_HEADER,
config.getReferrerPolicyHeaderValue());

addHeaderIfEnabled(responseHeaders, headersToAddToResponse,
SecureHeadersProperties.CONTENT_SECURITY_POLICY_HEADER, config.getContentSecurityPolicyHeaderValue());
addContentSecurityPolicyHeaderIfEnabled(responseHeaders, headersToAddToResponse,
config.getContentSecurityPolicyHeaderValue());

addHeaderIfEnabled(responseHeaders, headersToAddToResponse, SecureHeadersProperties.X_DOWNLOAD_OPTIONS_HEADER,
config.getDownloadOptionsHeaderValue());
Expand Down Expand Up @@ -195,6 +195,18 @@ private void addHeaderIfEnabled(HttpHeaders headers, Set<String> headersToAdd, S
}
}

private void addContentSecurityPolicyHeaderIfEnabled(HttpHeaders headers, Set<String> headersToAdd,
@Nullable String headerValue) {
if (headerValue != null && headersToAdd
.contains(SecureHeadersProperties.CONTENT_SECURITY_POLICY_HEADER.toLowerCase(Locale.ROOT))) {
if (!headers.containsHeader(SecureHeadersProperties.CONTENT_SECURITY_POLICY_HEADER)
|| !headers.getOrEmpty(SecureHeadersProperties.CONTENT_SECURITY_POLICY_HEADER)
.contains(headerValue)) {
headers.add(SecureHeadersProperties.CONTENT_SECURITY_POLICY_HEADER, headerValue);
}
}
}

/**
* POJO for {@link SecureHeadersGatewayFilterFactory} filter configuration.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ public void doesNotDuplicateHeaders() {
Config config = new Config();

String[] headers = { X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER,
X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER,
X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, PERMISSIONS_POLICY_HEADER };
X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER,
X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, PERMISSIONS_POLICY_HEADER };

for (String header : headers) {
filter = filterFactory.apply(config);
Expand All @@ -171,6 +171,25 @@ public void doesNotDuplicateHeaders() {
}
}

@Test
public void appendsContentSecurityPolicyHeaderWhenAlreadyPresent() {
String originalHeaderValue = "default-src 'self'";

SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory(
new SecureHeadersProperties());
filter = filterFactory.apply(new Config());

MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost").build();
exchange = MockServerWebExchange.from(request);
exchange.getResponse().getHeaders().set(CONTENT_SECURITY_POLICY_HEADER, originalHeaderValue);

filter.filter(exchange, filterChain).block();

ServerHttpResponse response = captor.getValue().getResponse();
assertThat(response.getHeaders().get(CONTENT_SECURITY_POLICY_HEADER)).containsExactly(originalHeaderValue,
new SecureHeadersProperties().getContentSecurityPolicy());
}

@Test
public void toStringFormat() {
GatewayFilter filter = new SecureHeadersGatewayFilterFactory(new SecureHeadersProperties()).apply(new Config());
Expand Down
0