Skip to content

Commit

Permalink
Properly handle opaque origin ("null") in CORS processing (#8537)
Browse files Browse the repository at this point in the history
* Add logic to detect opaque origin and treat as normal (not CORS) request

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>

* Do not assume opaque origin is normal req; abstract the check for opaque origin; expand test

---------

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>
  • Loading branch information
tjquinno authored Mar 25, 2024
1 parent 34ab56c commit 5730a16
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
15 changes: 13 additions & 2 deletions cors/src/main/java/io/helidon/cors/CorsSupportHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ public class CorsSupportHelper<Q, R> {

static final Logger LOGGER = Logger.getLogger(CorsSupportHelper.class.getName());

static final String OPAQUE_ORIGIN = "null"; // browsers might send this as Origin header if origin info is untrusted

private static final Supplier<Optional<CrossOriginConfig>> EMPTY_SECONDARY_SUPPLIER = Optional::empty;


private final String name;

/**
Expand Down Expand Up @@ -392,7 +395,7 @@ static RequestTypeInfo create(String originHeader, UriInfo requestedHostUri) {

return new RequestTypeInfo(originLocation,
hostLocation,
originLocation.equals(hostLocation));
originLocation.equals(hostLocation) || originLocation.equals(OPAQUE_ORIGIN));
}
}

Expand All @@ -405,6 +408,10 @@ private static boolean isRequestTypeNormal(CorsRequestAdapter<?> requestAdapter,
LogHelper.logIsRequestTypeNormalNoOrigin(silent, requestAdapter);
return true;
}
if (isOriginOpaque(originOpt.get())) {
LogHelper.logOpaqueOrigin(silent, requestAdapter);
// Do not return. Continue processing having noted the opaque origin.
}

RequestTypeInfo result = requestType(originOpt.get(), requestAdapter.requestedUri());
LogHelper.logIsRequestTypeNormal(result.isNormal,
Expand All @@ -416,12 +423,16 @@ private static boolean isRequestTypeNormal(CorsRequestAdapter<?> requestAdapter,
return result.isNormal;
}

static boolean isOriginOpaque(String origin) {
return origin.equals(OPAQUE_ORIGIN);
}

private static String originLocation(String origin) {
int originEndOfScheme = origin.indexOf(':');
int originLastColon = origin.lastIndexOf(':');

return origin + (
(originEndOfScheme == originLastColon)
(originEndOfScheme == originLastColon && originEndOfScheme >= 0)
? ":" + portForScheme(origin.substring(0, originEndOfScheme))
: "");
}
Expand Down
10 changes: 10 additions & 0 deletions cors/src/main/java/io/helidon/cors/LogHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ static <T> void logIsRequestTypeNormalNoOrigin(boolean silent, CorsRequestAdapte
List.of("header " + HeaderNames.ORIGIN + " is absent")));
}

static <T> void logOpaqueOrigin(boolean silent, CorsRequestAdapter<T> requestAdapter) {
if (silent || !CorsSupportHelper.LOGGER.isLoggable(DECISION_LEVEL)) {
return;
}
CorsSupportHelper.LOGGER.log(DECISION_LEVEL,
String.format("Request %s specifies opaque origin: %s",
requestAdapter,
List.of("header " + HeaderNames.ORIGIN)));
}

static <T> void logIsRequestTypeNormal(boolean result, boolean silent, CorsRequestAdapter<T> requestAdapter,
Optional<String> originOpt, String effectiveOrigin, String host) {
if (silent || !CorsSupportHelper.LOGGER.isLoggable(DECISION_LEVEL)) {
Expand Down
11 changes: 11 additions & 0 deletions cors/src/test/java/io/helidon/cors/CorsSupportHelperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ void sameNodeDifferentPorts() {
is(false));
}

@Test
void opaqueOrigin() {
assertThat("Opaque origin",
CorsSupportHelper.isOriginOpaque(CorsSupportHelper.OPAQUE_ORIGIN),
is(true));

assertThat("Non-opaque origin",
CorsSupportHelper.isOriginOpaque("http://ok.com"),
is(false));
}

@Test
void sameNodeSamePort() {
assertThat("Default origin port",
Expand Down

0 comments on commit 5730a16

Please sign in to comment.