Skip to content

Commit 1cc53b5

Browse files
authored
Bad regex in CORS settings should throw a nicer error (#34035)
Currently a bad regex in CORS settings throws a PatternSyntaxException, which then bubbles up through the bootstrap code, meaning users have to parse a stack trace to work out where the problem is. We should instead catch this exception and rethrow with a more useful error message.
1 parent 53d10bb commit 1cc53b5

File tree

4 files changed

+48
-10
lines changed

4 files changed

+48
-10
lines changed

modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.elasticsearch.common.settings.Setting;
4949
import org.elasticsearch.common.settings.Setting.Property;
5050
import org.elasticsearch.common.settings.Settings;
51+
import org.elasticsearch.common.settings.SettingsException;
5152
import org.elasticsearch.common.unit.ByteSizeUnit;
5253
import org.elasticsearch.common.unit.ByteSizeValue;
5354
import org.elasticsearch.common.util.BigArrays;
@@ -68,6 +69,7 @@
6869
import java.util.Arrays;
6970
import java.util.concurrent.TimeUnit;
7071
import java.util.regex.Pattern;
72+
import java.util.regex.PatternSyntaxException;
7173

7274
import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadFactory;
7375
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_CREDENTIALS;
@@ -241,11 +243,15 @@ static Netty4CorsConfig buildCorsConfig(Settings settings) {
241243
} else if (origin.equals(ANY_ORIGIN)) {
242244
builder = Netty4CorsConfigBuilder.forAnyOrigin();
243245
} else {
244-
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
245-
if (p == null) {
246-
builder = Netty4CorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
247-
} else {
248-
builder = Netty4CorsConfigBuilder.forPattern(p);
246+
try {
247+
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
248+
if (p == null) {
249+
builder = Netty4CorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
250+
} else {
251+
builder = Netty4CorsConfigBuilder.forPattern(p);
252+
}
253+
} catch (PatternSyntaxException e) {
254+
throw new SettingsException("Bad regex in [" + SETTING_CORS_ALLOW_ORIGIN.getKey() + "]: [" + origin + "]", e);
249255
}
250256
}
251257
if (SETTING_CORS_ALLOW_CREDENTIALS.get(settings)) {

modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.elasticsearch.common.network.NetworkService;
4545
import org.elasticsearch.common.settings.Setting;
4646
import org.elasticsearch.common.settings.Settings;
47+
import org.elasticsearch.common.settings.SettingsException;
4748
import org.elasticsearch.common.transport.TransportAddress;
4849
import org.elasticsearch.common.unit.ByteSizeValue;
4950
import org.elasticsearch.common.unit.TimeValue;
@@ -75,6 +76,7 @@
7576
import java.util.concurrent.TimeUnit;
7677
import java.util.concurrent.atomic.AtomicBoolean;
7778
import java.util.concurrent.atomic.AtomicReference;
79+
import java.util.regex.PatternSyntaxException;
7880
import java.util.stream.Collectors;
7981

8082
import static org.elasticsearch.common.Strings.collectionToDelimitedString;
@@ -148,6 +150,17 @@ public void testCorsConfigWithDefaults() {
148150
assertFalse(corsConfig.isCredentialsAllowed());
149151
}
150152

153+
public void testCorsConfigWithBadRegex() {
154+
final Settings settings = Settings.builder()
155+
.put(SETTING_CORS_ENABLED.getKey(), true)
156+
.put(SETTING_CORS_ALLOW_ORIGIN.getKey(), "/[*/")
157+
.put(SETTING_CORS_ALLOW_CREDENTIALS.getKey(), true)
158+
.build();
159+
SettingsException e = expectThrows(SettingsException.class, () -> Netty4HttpServerTransport.buildCorsConfig(settings));
160+
assertThat(e.getMessage(), containsString("Bad regex in [http.cors.allow-origin]: [/[*/]"));
161+
assertThat(e.getCause(), instanceOf(PatternSyntaxException.class));
162+
}
163+
151164
/**
152165
* Test that {@link Netty4HttpServerTransport} supports the "Expect: 100-continue" HTTP header
153166
* @throws InterruptedException if the client communication with the server is interrupted

plugins/transport-nio/src/main/java/org/elasticsearch/http/nio/NioHttpServerTransport.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.elasticsearch.common.recycler.Recycler;
2828
import org.elasticsearch.common.settings.Setting;
2929
import org.elasticsearch.common.settings.Settings;
30+
import org.elasticsearch.common.settings.SettingsException;
3031
import org.elasticsearch.common.unit.ByteSizeValue;
3132
import org.elasticsearch.common.util.BigArrays;
3233
import org.elasticsearch.common.util.PageCacheRecycler;
@@ -57,6 +58,7 @@
5758
import java.util.Arrays;
5859
import java.util.function.Consumer;
5960
import java.util.regex.Pattern;
61+
import java.util.regex.PatternSyntaxException;
6062

6163
import static org.elasticsearch.common.settings.Setting.intSetting;
6264
import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadFactory;
@@ -176,11 +178,15 @@ static NioCorsConfig buildCorsConfig(Settings settings) {
176178
} else if (origin.equals(ANY_ORIGIN)) {
177179
builder = NioCorsConfigBuilder.forAnyOrigin();
178180
} else {
179-
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
180-
if (p == null) {
181-
builder = NioCorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
182-
} else {
183-
builder = NioCorsConfigBuilder.forPattern(p);
181+
try {
182+
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
183+
if (p == null) {
184+
builder = NioCorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
185+
} else {
186+
builder = NioCorsConfigBuilder.forPattern(p);
187+
}
188+
} catch (PatternSyntaxException e) {
189+
throw new SettingsException("Bad regex in [" + SETTING_CORS_ALLOW_ORIGIN.getKey() + "]: [" + origin + "]", e);
184190
}
185191
}
186192
if (SETTING_CORS_ALLOW_CREDENTIALS.get(settings)) {

plugins/transport-nio/src/test/java/org/elasticsearch/http/nio/NioHttpServerTransportTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.elasticsearch.common.network.NetworkService;
3838
import org.elasticsearch.common.settings.Setting;
3939
import org.elasticsearch.common.settings.Settings;
40+
import org.elasticsearch.common.settings.SettingsException;
4041
import org.elasticsearch.common.transport.TransportAddress;
4142
import org.elasticsearch.common.unit.ByteSizeValue;
4243
import org.elasticsearch.common.util.MockBigArrays;
@@ -65,6 +66,7 @@
6566
import java.util.HashSet;
6667
import java.util.Set;
6768
import java.util.concurrent.atomic.AtomicReference;
69+
import java.util.regex.PatternSyntaxException;
6870
import java.util.stream.Collectors;
6971

7072
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_CREDENTIALS;
@@ -139,6 +141,17 @@ public void testCorsConfigWithDefaults() {
139141
assertFalse(corsConfig.isCredentialsAllowed());
140142
}
141143

144+
public void testCorsConfigWithBadRegex() {
145+
final Settings settings = Settings.builder()
146+
.put(SETTING_CORS_ENABLED.getKey(), true)
147+
.put(SETTING_CORS_ALLOW_ORIGIN.getKey(), "/[*/")
148+
.put(SETTING_CORS_ALLOW_CREDENTIALS.getKey(), true)
149+
.build();
150+
SettingsException e = expectThrows(SettingsException.class, () -> NioHttpServerTransport.buildCorsConfig(settings));
151+
assertThat(e.getMessage(), containsString("Bad regex in [http.cors.allow-origin]: [/[*/]"));
152+
assertThat(e.getCause(), instanceOf(PatternSyntaxException.class));
153+
}
154+
142155
/**
143156
* Test that {@link NioHttpServerTransport} supports the "Expect: 100-continue" HTTP header
144157
* @throws InterruptedException if the client communication with the server is interrupted

0 commit comments

Comments
 (0)