Skip to content

Commit 4c74190

Browse files
authored
Merge pull request #1820 from AndySpaven/ISSUE-1745
ISSUE-1745 - Change the buildUrl to handle more cases of path traversal
2 parents 4b3863c + 75a21d5 commit 4c74190

File tree

2 files changed

+22
-42
lines changed

2 files changed

+22
-42
lines changed

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RefUtils.java

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.io.FileInputStream;
1212
import java.io.IOException;
1313
import java.io.InputStream;
14+
import java.net.URL;
1415
import java.nio.file.Files;
1516
import java.nio.file.Path;
1617
import java.util.List;
@@ -150,48 +151,20 @@ public static String readExternalClasspathRef(String file, RefFormat refFormat,
150151
}
151152

152153
public static String buildUrl(String rootPath, String relativePath) {
153-
String[] rootPathParts = rootPath.split("/");
154-
String [] relPathParts = relativePath.split("/");
155-
156-
if(rootPath == null || relativePath == null) {
157-
return null;
158-
}
159-
160-
int trimRoot = 0;
161-
int trimRel = 0;
162-
163-
if(!"".equals(rootPathParts[rootPathParts.length - 1])) {
164-
trimRoot = 1;
165-
}
166-
if("".equals(relPathParts[0])) {
167-
trimRel = 1; trimRoot = rootPathParts.length-3;
168-
}
169-
for(int i = 0; i < rootPathParts.length; i++) {
170-
if("".equals(rootPathParts[i])) {
171-
trimRel += 1;
172-
}
173-
else {
174-
break;
175-
}
176-
}
177-
for(int i = 0; i < relPathParts.length; i ++) {
178-
if(".".equals(relPathParts[i])) {
179-
trimRel += 1;
180-
}
181-
else if ("..".equals(relPathParts[i])) {
182-
trimRel += 1; trimRoot += 1;
183-
}
184-
}
185-
186-
String [] outputParts = new String[rootPathParts.length + relPathParts.length - trimRoot - trimRel];
187-
System.arraycopy(rootPathParts, 0, outputParts, 0, rootPathParts.length - trimRoot);
188-
System.arraycopy(relPathParts,
189-
trimRel,
190-
outputParts,
191-
rootPathParts.length - trimRoot,
192-
relPathParts.length - trimRel);
193-
194-
return StringUtils.join(outputParts, "/");
154+
if(rootPath == null || relativePath == null) {
155+
return null;
156+
}
157+
158+
try {
159+
int until = rootPath.lastIndexOf("/")+1;
160+
String root = rootPath.substring(0, until);
161+
URL rootUrl = new URL(root);
162+
URL finalUrl = new URL(rootUrl, relativePath);
163+
return finalUrl.toString();
164+
}
165+
catch(Exception e) {
166+
throw new RuntimeException(e);
167+
}
195168
}
196169

197170
public static String readExternalRef(String file, RefFormat refFormat, List<AuthorizationValue> auths,

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/RefUtilsTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ public void testPathJoin2() {
312312
assertEquals(RefUtils.buildUrl("http://foo.bar.com/my/dir/file.yaml", "/my/newFile.yaml"), "http://foo.bar.com/my/newFile.yaml");
313313
}
314314

315+
@Test
316+
public void testPathJoinIssue1745() {
317+
assertEquals(RefUtils.buildUrl("http://foo.bar.com/my/dir/file.yaml", "./second/../newFile.yaml"), "http://foo.bar.com/my/dir/newFile.yaml");
318+
assertEquals(RefUtils.buildUrl("http://foo.bar.com/my/dir/", "./second/../newFile.yaml"), "http://foo.bar.com/my/dir/newFile.yaml");
319+
// This is a little strange in the output (beacuse it has not completely eliminated the ..) but is still correct - paste a similar url into a browser and it resolves it correctly.
320+
assertEquals(RefUtils.buildUrl("http://foo.bar.com/my/dir/file.yaml", "/second/../newFile.yaml"), "http://foo.bar.com/second/../newFile.yaml");
321+
}
315322

316323
@Test
317324
public void shouldReturnEmptyExternalPathForInternalReference() {

0 commit comments

Comments
 (0)