Skip to content

Commit ca1252b

Browse files
committed
Replace whitelist with allowlist
Issue gh-8676
1 parent a907026 commit ca1252b

File tree

9 files changed

+51
-47
lines changed

9 files changed

+51
-47
lines changed

build.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ buildscript {
22
dependencies {
33
classpath 'io.spring.gradle:spring-build-conventions:0.0.32.RELEASE'
44
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
5-
classpath 'io.spring.nohttp:nohttp-gradle:0.0.2.RELEASE'
5+
classpath 'io.spring.nohttp:nohttp-gradle:0.0.5.RELEASE'
66
classpath "io.freefair.gradle:aspectj-plugin:5.0.1"
77
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
88
}
@@ -39,3 +39,7 @@ subprojects {
3939
options.encoding = "UTF-8"
4040
}
4141
}
42+
43+
nohttp {
44+
allowlistFile = project.file("etc/nohttp/allowlist.lines")
45+
}

core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public static void enableDefaultTyping(ObjectMapper mapper) {
9090
if (mapper != null) {
9191
TypeResolverBuilder<?> typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null);
9292
if (typeBuilder == null) {
93-
mapper.setDefaultTyping(createWhitelistedDefaultTyping());
93+
mapper.setDefaultTyping(createAllowlistedDefaultTyping());
9494
}
9595
}
9696
}
@@ -148,11 +148,11 @@ private static void addToModulesList(ClassLoader loader, List<Module> modules, S
148148
}
149149

150150
/**
151-
* Creates a TypeResolverBuilder that performs whitelisting.
152-
* @return a TypeResolverBuilder that performs whitelisting.
151+
* Creates a TypeResolverBuilder that restricts allowed types.
152+
* @return a TypeResolverBuilder that restricts allowed types.
153153
*/
154-
private static TypeResolverBuilder<? extends TypeResolverBuilder> createWhitelistedDefaultTyping() {
155-
TypeResolverBuilder<? extends TypeResolverBuilder> result = new WhitelistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
154+
private static TypeResolverBuilder<? extends TypeResolverBuilder> createAllowlistedDefaultTyping() {
155+
TypeResolverBuilder<? extends TypeResolverBuilder> result = new AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
156156
result = result.init(JsonTypeInfo.Id.CLASS, null);
157157
result = result.inclusion(JsonTypeInfo.As.PROPERTY);
158158
return result;
@@ -164,9 +164,9 @@ private static TypeResolverBuilder<? extends TypeResolverBuilder> createWhitelis
164164
* and overrides the {@code TypeIdResolver}
165165
* @author Rob Winch
166166
*/
167-
static class WhitelistTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
167+
static class AllowlistTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
168168

169-
WhitelistTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping) {
169+
AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping) {
170170
super(
171171
defaultTyping,
172172
//we do explicit validation in the TypeIdResolver
@@ -182,17 +182,17 @@ protected TypeIdResolver idResolver(MapperConfig<?> config,
182182
PolymorphicTypeValidator subtypeValidator,
183183
Collection<NamedType> subtypes, boolean forSer, boolean forDeser) {
184184
TypeIdResolver result = super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
185-
return new WhitelistTypeIdResolver(result);
185+
return new AllowlistTypeIdResolver(result);
186186
}
187187
}
188188

189189
/**
190190
* A {@link TypeIdResolver} that delegates to an existing implementation and throws an IllegalStateException if the
191-
* class being looked up is not whitelisted, does not provide an explicit mixin, and is not annotated with Jackson
191+
* class being looked up is not in the allowlist, does not provide an explicit mixin, and is not annotated with Jackson
192192
* mappings. See https://github.com/spring-projects/spring-security/issues/4370
193193
*/
194-
static class WhitelistTypeIdResolver implements TypeIdResolver {
195-
private static final Set<String> WHITELIST_CLASS_NAMES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
194+
static class AllowlistTypeIdResolver implements TypeIdResolver {
195+
private static final Set<String> ALLOWLIST_CLASS_NAMES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
196196
"java.util.ArrayList",
197197
"java.util.Collections$EmptyList",
198198
"java.util.Collections$EmptyMap",
@@ -209,7 +209,7 @@ static class WhitelistTypeIdResolver implements TypeIdResolver {
209209

210210
private final TypeIdResolver delegate;
211211

212-
WhitelistTypeIdResolver(TypeIdResolver delegate) {
212+
AllowlistTypeIdResolver(TypeIdResolver delegate) {
213213
this.delegate = delegate;
214214
}
215215

@@ -238,7 +238,7 @@ public JavaType typeFromId(DatabindContext context, String id) throws IOExceptio
238238
DeserializationConfig config = (DeserializationConfig) context.getConfig();
239239
JavaType result = delegate.typeFromId(context, id);
240240
String className = result.getRawClass().getName();
241-
if (isWhitelisted(className)) {
241+
if (isInAllowlist(className)) {
242242
return result;
243243
}
244244
boolean isExplicitMixin = config.findMixInClassFor(result.getRawClass()) != null;
@@ -249,14 +249,14 @@ public JavaType typeFromId(DatabindContext context, String id) throws IOExceptio
249249
if (jacksonAnnotation != null) {
250250
return result;
251251
}
252-
throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not whitelisted. " +
252+
throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not in the allowlist. " +
253253
"If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. " +
254254
"If the serialization is only done by a trusted source, you can also enable default typing. " +
255255
"See https://github.com/spring-projects/spring-security/issues/4370 for details");
256256
}
257257

258-
private boolean isWhitelisted(String id) {
259-
return WHITELIST_CLASS_NAMES.contains(id);
258+
private boolean isInAllowlist(String id) {
259+
return ALLOWLIST_CLASS_NAMES.contains(id);
260260
}
261261

262262
@Override

core/src/test/java/org/springframework/security/jackson2/SecurityJackson2ModulesTests.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,50 +44,50 @@ public void setup() {
4444
}
4545

4646
@Test
47-
public void readValueWhenNotWhitelistedOrMappedThenThrowsException() {
48-
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
47+
public void readValueWhenNotAllowedOrMappedThenThrowsException() {
48+
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
4949
assertThatThrownBy(() -> {
5050
mapper.readValue(content, Object.class);
5151
}
52-
).hasStackTraceContaining("whitelisted");
52+
).hasStackTraceContaining("allowlist");
5353
}
5454

5555
@Test
5656
public void readValueWhenExplicitDefaultTypingAfterSecuritySetupThenReadsAsSpecificType() throws Exception {
5757
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
58-
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
58+
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
5959

60-
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
60+
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
6161
}
6262

6363
@Test
6464
public void readValueWhenExplicitDefaultTypingBeforeSecuritySetupThenReadsAsSpecificType() throws Exception {
6565
mapper = new ObjectMapper();
6666
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
6767
SecurityJackson2Modules.enableDefaultTyping(mapper);
68-
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
68+
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
6969

70-
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
70+
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
7171
}
7272

7373
@Test
7474
public void readValueWhenAnnotatedThenReadsAsSpecificType() throws Exception {
75-
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelistedButAnnotated\",\"property\":\"bar\"}";
75+
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlistedButAnnotated\",\"property\":\"bar\"}";
7676

77-
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelistedButAnnotated.class);
77+
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlistedButAnnotated.class);
7878
}
7979

8080
@Test
8181
public void readValueWhenMixinProvidedThenReadsAsSpecificType() throws Exception {
82-
mapper.addMixIn(NotWhitelisted.class, NotWhitelistedMixin.class);
83-
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
82+
mapper.addMixIn(NotAllowlisted.class, NotAllowlistedMixin.class);
83+
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
8484

85-
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
85+
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
8686
}
8787

8888
@Test
8989
public void readValueWhenHashMapThenReadsAsSpecificType() throws Exception {
90-
mapper.addMixIn(NotWhitelisted.class, NotWhitelistedMixin.class);
90+
mapper.addMixIn(NotAllowlisted.class, NotAllowlistedMixin.class);
9191
String content = "{\"@class\":\"java.util.HashMap\"}";
9292

9393
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(HashMap.class);
@@ -99,7 +99,7 @@ public void readValueWhenHashMapThenReadsAsSpecificType() throws Exception {
9999
public @interface NotJacksonAnnotation {}
100100

101101
@NotJacksonAnnotation
102-
static class NotWhitelisted {
102+
static class NotAllowlisted {
103103
private String property = "bar";
104104

105105
public String getProperty() {
@@ -111,7 +111,7 @@ public void setProperty(String property) {
111111
}
112112

113113
@JsonIgnoreType(false)
114-
static class NotWhitelistedButAnnotated {
114+
static class NotAllowlistedButAnnotated {
115115
private String property = "bar";
116116

117117
public String getProperty() {
@@ -126,7 +126,7 @@ public void setProperty(String property) {
126126
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
127127
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
128128
@JsonIgnoreProperties(ignoreUnknown = true)
129-
abstract class NotWhitelistedMixin {
129+
abstract class NotAllowlistedMixin {
130130

131131
}
132132
}

docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ In this case, you construct `JwtIssuerReactiveAuthenticationManagerResolver` wit
10821082
This approach allows us to add and remove elements from the repository (shown as a `Map` in the snippet) at runtime.
10831083

10841084
NOTE: It would be unsafe to simply take any issuer and construct an `ReactiveAuthenticationManager` from it.
1085-
The issuer should be one that the code can verify from a trusted source like a whitelist.
1085+
The issuer should be one that the code can verify from a trusted source like an allowed list of issuers.
10861086

10871087
[[webflux-oauth2resourceserver-bearertoken-resolver]]
10881088
== Bearer Token Resolution

docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,7 @@ In this case, you construct `JwtIssuerAuthenticationManagerResolver` with a stra
18571857
This approach allows us to add and remove elements from the repository (shown as a `Map` in the snippet) at runtime.
18581858

18591859
NOTE: It would be unsafe to simply take any issuer and construct an `AuthenticationManager` from it.
1860-
The issuer should be one that the code can verify from a trusted source like a whitelist.
1860+
The issuer should be one that the code can verify from a trusted source like a list of allowed issuers.
18611861

18621862
===== Parsing the Claim Only Once
18631863

@@ -1907,7 +1907,7 @@ public class TenantJWSKeySelector
19071907
----
19081908
<1> A hypothetical source for tenant information
19091909
<2> A cache for `JWKKeySelector`s, keyed by tenant identifier
1910-
<3> Looking up the tenant is more secure than simply calculating the JWK Set endpoint on the fly - the lookup acts as a tenant whitelist
1910+
<3> Looking up the tenant is more secure than simply calculating the JWK Set endpoint on the fly - the lookup acts as a list of allowed tenants
19111911
<4> Create a `JWSKeySelector` via the types of keys that come back from the JWK Set endpoint - the lazy lookup here means that you don't need to configure all tenants at startup
19121912

19131913
The above key selector is a composition of many key selectors.
File renamed without changes.

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
*
4646
* To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that
4747
* anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way
48-
* to achieve this is to supply a whitelist of trusted issuers in the constructor.
48+
* to achieve this is to supply a list of trusted issuers in the constructor.
4949
*
5050
* This class derives the Issuer from the `iss` claim found in the {@link HttpServletRequest}'s
5151
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>.
@@ -60,7 +60,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
6060
/**
6161
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
6262
*
63-
* @param trustedIssuers a whitelist of trusted issuers
63+
* @param trustedIssuers a list of trusted issuers
6464
*/
6565
public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) {
6666
this(Arrays.asList(trustedIssuers));
@@ -69,7 +69,7 @@ public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) {
6969
/**
7070
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
7171
*
72-
* @param trustedIssuers a whitelist of trusted issuers
72+
* @param trustedIssuers a list of trusted issuers
7373
*/
7474
public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers) {
7575
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty");
@@ -82,7 +82,7 @@ public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers)
8282
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
8383
*
8484
* Note that the {@link AuthenticationManagerResolver} provided in this constructor will need to
85-
* verify that the issuer is trusted. This should be done via a whitelist.
85+
* verify that the issuer is trusted. This should be done via an allowlist.
8686
*
8787
* One way to achieve this is with a {@link Map} where the keys are the known issuers:
8888
* <pre>
@@ -93,7 +93,7 @@ public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers)
9393
* (authenticationManagers::get);
9494
* </pre>
9595
*
96-
* The keys in the {@link Map} are the whitelist.
96+
* The keys in the {@link Map} are the allowed issuers.
9797
*
9898
* @param issuerAuthenticationManagerResolver a strategy for resolving the {@link AuthenticationManager} by the issuer
9999
*/

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
*
4949
* To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that
5050
* anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way
51-
* to achieve this is to supply a whitelist of trusted issuers in the constructor.
51+
* to achieve this is to supply a list of trusted issuers in the constructor.
5252
*
5353
* This class derives the Issuer from the `iss` claim found in the {@link ServerWebExchange}'s
5454
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>.
@@ -66,7 +66,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
6666
/**
6767
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
6868
*
69-
* @param trustedIssuers a whitelist of trusted issuers
69+
* @param trustedIssuers a list of trusted issuers
7070
*/
7171
public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers) {
7272
this(Arrays.asList(trustedIssuers));
@@ -75,7 +75,7 @@ public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers)
7575
/**
7676
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
7777
*
78-
* @param trustedIssuers a whitelist of trusted issuers
78+
* @param trustedIssuers a collection of trusted issuers
7979
*/
8080
public JwtIssuerReactiveAuthenticationManagerResolver(Collection<String> trustedIssuers) {
8181
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty");
@@ -87,7 +87,7 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection<String> trusted
8787
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
8888
*
8989
* Note that the {@link ReactiveAuthenticationManagerResolver} provided in this constructor will need to
90-
* verify that the issuer is trusted. This should be done via a whitelist.
90+
* verify that the issuer is trusted. This should be done via an allowed list of issuers.
9191
*
9292
* One way to achieve this is with a {@link Map} where the keys are the known issuers:
9393
* <pre>
@@ -98,7 +98,7 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection<String> trusted
9898
* (issuer -> Mono.justOrEmpty(authenticationManagers.get(issuer));
9999
* </pre>
100100
*
101-
* The keys in the {@link Map} are the whitelist.
101+
* The keys in the {@link Map} are the trusted issuers.
102102
*
103103
* @param issuerAuthenticationManagerResolver a strategy for resolving the {@link ReactiveAuthenticationManager}
104104
* by the issuer

web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ private void rejectForbiddenHttpMethod(HttpServletRequest request) {
358358
if (!this.allowedHttpMethods.contains(request.getMethod())) {
359359
throw new RequestRejectedException("The request was rejected because the HTTP method \"" +
360360
request.getMethod() +
361-
"\" was not included within the whitelist " +
361+
"\" was not included within the list of allowed HTTP methods " +
362362
this.allowedHttpMethods);
363363
}
364364
}

0 commit comments

Comments
 (0)