Skip to content

Commit 8615ddc

Browse files
author
noel-enquanta
committed
URL-encode userId, groupId, contentLanguage, subAccountAPIKey path params
Add private static enc() helper backed by URLEncoder. Defense in depth: caller-supplied IDs containing '/' or '?' can no longer change the endpoint or inject query parameters. Same fix as the morning pass for python/ruby/php/scala/perl/cpp; java was deferred and is now done.
1 parent bc7f31a commit 8615ddc

2 files changed

Lines changed: 27 additions & 17 deletions

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>org.voiceit</groupId>
88
<artifactId>voiceit3-java</artifactId>
9-
<version>3.0.4</version>
9+
<version>3.0.5</version>
1010

1111
<dependencies>
1212

src/main/java/voiceit/java/VoiceIt3.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class VoiceIt3 {
2626
private static String BASE_URL = "https://api.voiceit.io";
2727
private String notificationUrl = "";
2828
private HttpClient httpClient;
29-
public static final String VERSION = "3.0.4";
29+
public static final String VERSION = "3.0.5";
3030

3131
public VoiceIt3(String apiKey, String apiToken){
3232
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
@@ -60,6 +60,16 @@ public VoiceIt3(String apiKey, String apiToken, String customBaseURL, SSLContext
6060
httpClient = clientBuilder.build();
6161
}
6262

63+
// URL-encode a path segment so caller-supplied IDs containing '/'
64+
// or '?' cannot change the endpoint or inject query parameters.
65+
private static String enc(String s) {
66+
try {
67+
return URLEncoder.encode(s, "UTF-8");
68+
} catch (java.io.UnsupportedEncodingException e) {
69+
throw new RuntimeException("UTF-8 not supported", e);
70+
}
71+
}
72+
6373
private void setup(HttpClientBuilder clientBuilder, String apiKey, String apiToken) {
6474
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
6575
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(apiKey, apiToken));
@@ -83,7 +93,7 @@ public void removeNotificationUrl() {
8393
public String getPhrases(String contentLanguage) {
8494
try {
8595
return EntityUtils.toString(httpClient.execute(
86-
new HttpGet(BASE_URL + "/phrases/" + contentLanguage + notificationUrl)).getEntity());
96+
new HttpGet(BASE_URL + "/phrases/" + enc(contentLanguage) + notificationUrl)).getEntity());
8797
} catch (Exception e) {
8898
return e.getMessage();
8999
}
@@ -110,7 +120,7 @@ public String createUser() {
110120
public String checkUserExists(String userId) {
111121
try {
112122
return EntityUtils.toString(httpClient.execute(
113-
new HttpGet(BASE_URL + "/users/" + userId + notificationUrl)).getEntity());
123+
new HttpGet(BASE_URL + "/users/" + enc(userId) + notificationUrl)).getEntity());
114124
} catch (Exception e) {
115125
return e.getMessage();
116126
}
@@ -119,7 +129,7 @@ public String checkUserExists(String userId) {
119129
public String deleteUser(String userId) {
120130
try {
121131
return EntityUtils.toString(httpClient.execute(
122-
new HttpDelete(BASE_URL + "/users/" + userId + notificationUrl)).getEntity());
132+
new HttpDelete(BASE_URL + "/users/" + enc(userId) + notificationUrl)).getEntity());
123133
} catch (Exception e) {
124134
return e.getMessage();
125135
}
@@ -128,7 +138,7 @@ public String deleteUser(String userId) {
128138
public String getGroupsForUser(String userId) {
129139
try {
130140
return EntityUtils.toString(httpClient.execute(
131-
new HttpGet(BASE_URL + "/users/" + userId + "/groups" + notificationUrl)).getEntity());
141+
new HttpGet(BASE_URL + "/users/" + enc(userId) + "/groups" + notificationUrl)).getEntity());
132142
} catch (Exception e) {
133143
return e.getMessage();
134144
}
@@ -146,7 +156,7 @@ public String getAllGroups() {
146156
public String getGroup(String groupId) {
147157
try {
148158
return EntityUtils.toString(httpClient.execute(
149-
new HttpGet(BASE_URL + "/groups/" + groupId + notificationUrl)).getEntity());
159+
new HttpGet(BASE_URL + "/groups/" + enc(groupId) + notificationUrl)).getEntity());
150160
} catch (Exception e) {
151161
return e.getMessage();
152162
}
@@ -155,7 +165,7 @@ public String getGroup(String groupId) {
155165
public String groupExists(String groupId) {
156166
try {
157167
return EntityUtils.toString(httpClient.execute(
158-
new HttpGet(BASE_URL + "/groups/" + groupId + "/exists" + notificationUrl)).getEntity());
168+
new HttpGet(BASE_URL + "/groups/" + enc(groupId) + "/exists" + notificationUrl)).getEntity());
159169
} catch (Exception e) {
160170
return e.getMessage();
161171
}
@@ -210,7 +220,7 @@ public String removeUserFromGroup(String groupId, String userId) {
210220
public String deleteGroup(String groupId) {
211221
try {
212222
return EntityUtils.toString(httpClient.execute(
213-
new HttpDelete(BASE_URL + "/groups/" + groupId + notificationUrl)).getEntity());
223+
new HttpDelete(BASE_URL + "/groups/" + enc(groupId) + notificationUrl)).getEntity());
214224
} catch (Exception e) {
215225
return e.getMessage();
216226
}
@@ -219,7 +229,7 @@ public String deleteGroup(String groupId) {
219229
public String getAllVoiceEnrollments(String userId) {
220230
try {
221231
return EntityUtils.toString(httpClient.execute(
222-
new HttpGet(BASE_URL + "/enrollments/voice/" + userId + notificationUrl)).getEntity());
232+
new HttpGet(BASE_URL + "/enrollments/voice/" + enc(userId) + notificationUrl)).getEntity());
223233
} catch (Exception e) {
224234
return e.getMessage();
225235
}
@@ -228,7 +238,7 @@ public String getAllVoiceEnrollments(String userId) {
228238
public String getAllFaceEnrollments(String userId) {
229239
try {
230240
return EntityUtils.toString(httpClient.execute(
231-
new HttpGet(BASE_URL + "/enrollments/face/" + userId + notificationUrl)).getEntity());
241+
new HttpGet(BASE_URL + "/enrollments/face/" + enc(userId) + notificationUrl)).getEntity());
232242
} catch (Exception e) {
233243
return e.getMessage();
234244
}
@@ -237,7 +247,7 @@ public String getAllFaceEnrollments(String userId) {
237247
public String getAllVideoEnrollments(String userId) {
238248
try {
239249
return EntityUtils.toString(httpClient.execute(
240-
new HttpGet(BASE_URL + "/enrollments/video/" + userId + notificationUrl)).getEntity());
250+
new HttpGet(BASE_URL + "/enrollments/video/" + enc(userId) + notificationUrl)).getEntity());
241251
} catch (Exception e) {
242252
return e.getMessage();
243253
}
@@ -368,7 +378,7 @@ public String createVideoEnrollmentByUrl(String userId, String contentLanguage,
368378
public String deleteAllEnrollments(String userId) {
369379
try {
370380
return EntityUtils.toString(httpClient.execute(
371-
new HttpDelete(BASE_URL + "/enrollments/" + userId + "/all" + notificationUrl)).getEntity());
381+
new HttpDelete(BASE_URL + "/enrollments/" + enc(userId) + "/all" + notificationUrl)).getEntity());
372382
} catch (Exception e) {
373383
return e.getMessage();
374384
}
@@ -621,7 +631,7 @@ public String videoIdentificationByUrl(String groupId, String contentLanguage, S
621631
public String createUserToken(String userId, int secondsToTimeout) {
622632
try {
623633
return EntityUtils.toString(httpClient.execute(
624-
new HttpPost(BASE_URL + "/users/" + userId + "/token?timeOut=" + Integer.toString(secondsToTimeout))).getEntity());
634+
new HttpPost(BASE_URL + "/users/" + enc(userId) + "/token?timeOut=" + Integer.toString(secondsToTimeout))).getEntity());
625635
} catch (Exception e) {
626636
return e.getMessage();
627637
}
@@ -630,7 +640,7 @@ public String createUserToken(String userId, int secondsToTimeout) {
630640
public String expireUserTokens(String userId) {
631641
try {
632642
return EntityUtils.toString(httpClient.execute(
633-
new HttpPost(BASE_URL + "/users/" + userId + "/expireTokens" + notificationUrl)).getEntity());
643+
new HttpPost(BASE_URL + "/users/" + enc(userId) + "/expireTokens" + notificationUrl)).getEntity());
634644
} catch (Exception e) {
635645
return e.getMessage();
636646
}
@@ -680,7 +690,7 @@ public String createUnmanagedSubAccount(String firstName, String lastName, Strin
680690
public String regenerateSubAccountAPIToken(String subAccountAPIKey) {
681691
try {
682692
return EntityUtils.toString(httpClient.execute(
683-
new HttpPost(BASE_URL + "/subaccount/" + subAccountAPIKey + notificationUrl)).getEntity());
693+
new HttpPost(BASE_URL + "/subaccount/" + enc(subAccountAPIKey) + notificationUrl)).getEntity());
684694
} catch (Exception e) {
685695
return e.getMessage();
686696
}
@@ -689,7 +699,7 @@ public String regenerateSubAccountAPIToken(String subAccountAPIKey) {
689699
public String deleteSubAccount(String subAccountAPIKey) {
690700
try {
691701
return EntityUtils.toString(httpClient.execute(
692-
new HttpDelete(BASE_URL + "/subaccount/" + subAccountAPIKey + notificationUrl)).getEntity());
702+
new HttpDelete(BASE_URL + "/subaccount/" + enc(subAccountAPIKey) + notificationUrl)).getEntity());
693703
} catch (Exception e) {
694704
return e.getMessage();
695705
}

0 commit comments

Comments
 (0)