-
Notifications
You must be signed in to change notification settings - Fork 0
[Detail Bug] Geocoding requests crash or allow query-parameter injection when location hint fields contain special characters #72
Description
Detail Bug Report
Summary
- Context:
GeocodeInputis a record used to build geocoding requests for the Apple Maps Server API, converting its fields into a URL query string. - Bug: The location-related fields (
searchLocation,searchRegion, anduserLocation) are appended to the query string without URL encoding. - Actual vs. expected: These fields are appended as raw strings, whereas they should be URL-encoded to handle special characters like spaces and ampersands.
- Impact: If these fields contain spaces, the application crashes with an
IllegalArgumentExceptionwhen attempting to create ajava.net.URI. If they contain ampersands or equals signs, it can lead to query parameter injection, potentially breaking the request logic.
Code with Bug
// src/main/java/com/williamcallahan/applemaps/domain/request/GeocodeInput.java
public String toQueryString() {
List<String> parameters = new ArrayList<>();
parameters.add(formatParameter(PARAMETER_QUERY, encode(address)));
if (!limitToCountries.isEmpty()) {
parameters.add(formatParameter(PARAMETER_LIMIT_TO_COUNTRIES, joinEncoded(limitToCountries)));
}
language.ifPresent(value -> parameters.add(formatParameter(PARAMETER_LANGUAGE, encode(value))));
searchLocation.ifPresent(value -> parameters.add(formatParameter(PARAMETER_SEARCH_LOCATION, value.toQueryString()))); // <-- BUG 🔴 not URL-encoded
searchRegion.ifPresent(value -> parameters.add(formatParameter(PARAMETER_SEARCH_REGION, value.toQueryString()))); // <-- BUG 🔴 not URL-encoded
userLocation.ifPresent(value -> parameters.add(formatParameter(PARAMETER_USER_LOCATION, value.toQueryString()))); // <-- BUG 🔴 not URL-encoded
return QUERY_PREFIX + String.join(PARAMETER_SEPARATOR, parameters);
}Explanation
GeocodeInput.toQueryString() correctly encodes some user-provided fields (e.g., address, language) via encode(), but directly concatenates searchLocation, searchRegion, and userLocation using value.toQueryString().
Because toQueryString() returns a raw string, spaces produce an invalid URI query (triggering IllegalArgumentException when building a java.net.URI), and reserved characters like & / = can alter the overall query string by injecting additional parameters.
Codebase Inconsistency
Within the same method, other fields are URL-encoded:
parameters.add(formatParameter(PARAMETER_QUERY, encode(address)));
language.ifPresent(value -> parameters.add(formatParameter(PARAMETER_LANGUAGE, encode(value))));But the location-hint parameters are not.
Failing Test
import org.junit.jupiter.api.Test;
class GeocodeInputTest {
@Test
void toQueryStringProducesUriCompatibleString() {
GeocodeInput geocodeInput = GeocodeInput.builder("test")
.searchLocation(new SearchLocation("37.33, -122.03")) // Note the space after the comma
.build();
String queryString = geocodeInput.toQueryString();
// This throws java.lang.IllegalArgumentException: Illegal character in query at index ...
java.net.URI.create("https://maps-api.apple.com/v1/geocode" + queryString);
}
}Recommended Fix
Wrap the call to value.toQueryString() with encode() for all location-hint parameters:
searchLocation.ifPresent(value -> parameters.add(formatParameter(PARAMETER_SEARCH_LOCATION, encode(value.toQueryString()))));
searchRegion.ifPresent(value -> parameters.add(formatParameter(PARAMETER_SEARCH_REGION, encode(value.toQueryString()))));
userLocation.ifPresent(value -> parameters.add(formatParameter(PARAMETER_USER_LOCATION, encode(value.toQueryString()))));History
This bug was introduced in commit 84b4c69. This commit added builder-based request inputs and centralized query serialization, but it failed to URL-encode the values returned by toQueryString() for location-based hint parameters.