@@ -878,6 +878,88 @@ Call<ResponseBody> method(@Path(value = "ping", encoded = true) String ping) {
878878 assertThat (request .body ()).isNull ();
879879 }
880880
881+ @ Test public void pathParametersAndPathTraversal () {
882+ class Example {
883+ @ GET ("/foo/bar/{ping}/" ) //
884+ Call <ResponseBody > method (@ Path (value = "ping" ) String ping ) {
885+ return null ;
886+ }
887+ }
888+
889+ assertMalformedRequest (Example .class , "." );
890+ assertMalformedRequest (Example .class , ".." );
891+
892+ assertThat (buildRequest (Example .class , "./a" ).url ().encodedPath ())
893+ .isEqualTo ("/foo/bar/.%2Fa/" );
894+ assertThat (buildRequest (Example .class , "a/." ).url ().encodedPath ())
895+ .isEqualTo ("/foo/bar/a%2F./" );
896+ assertThat (buildRequest (Example .class , "a/.." ).url ().encodedPath ())
897+ .isEqualTo ("/foo/bar/a%2F../" );
898+ assertThat (buildRequest (Example .class , "../a" ).url ().encodedPath ())
899+ .isEqualTo ("/foo/bar/..%2Fa/" );
900+ assertThat (buildRequest (Example .class , "..\\ .." ).url ().encodedPath ())
901+ .isEqualTo ("/foo/bar/..%5C../" );
902+
903+ assertThat (buildRequest (Example .class , "%2E" ).url ().encodedPath ())
904+ .isEqualTo ("/foo/bar/%252E/" );
905+ assertThat (buildRequest (Example .class , "%2E%2E" ).url ().encodedPath ())
906+ .isEqualTo ("/foo/bar/%252E%252E/" );
907+ }
908+
909+ @ Test public void encodedPathParametersAndPathTraversal () {
910+ class Example {
911+ @ GET ("/foo/bar/{ping}/" ) //
912+ Call <ResponseBody > method (@ Path (value = "ping" , encoded = true ) String ping ) {
913+ return null ;
914+ }
915+ }
916+
917+ assertMalformedRequest (Example .class , "." );
918+ assertMalformedRequest (Example .class , "%2E" );
919+ assertMalformedRequest (Example .class , "%2e" );
920+ assertMalformedRequest (Example .class , ".." );
921+ assertMalformedRequest (Example .class , "%2E." );
922+ assertMalformedRequest (Example .class , "%2e." );
923+ assertMalformedRequest (Example .class , ".%2E" );
924+ assertMalformedRequest (Example .class , ".%2e" );
925+ assertMalformedRequest (Example .class , "%2E%2e" );
926+ assertMalformedRequest (Example .class , "%2e%2E" );
927+ assertMalformedRequest (Example .class , "./a" );
928+ assertMalformedRequest (Example .class , "a/." );
929+ assertMalformedRequest (Example .class , "../a" );
930+ assertMalformedRequest (Example .class , "a/.." );
931+ assertMalformedRequest (Example .class , "a/../b" );
932+ assertMalformedRequest (Example .class , "a/%2e%2E/b" );
933+
934+ assertThat (buildRequest (Example .class , "..." ).url ().encodedPath ())
935+ .isEqualTo ("/foo/bar/.../" );
936+ assertThat (buildRequest (Example .class , "a..b" ).url ().encodedPath ())
937+ .isEqualTo ("/foo/bar/a..b/" );
938+ assertThat (buildRequest (Example .class , "a.." ).url ().encodedPath ())
939+ .isEqualTo ("/foo/bar/a../" );
940+ assertThat (buildRequest (Example .class , "a..b" ).url ().encodedPath ())
941+ .isEqualTo ("/foo/bar/a..b/" );
942+ assertThat (buildRequest (Example .class , "..b" ).url ().encodedPath ())
943+ .isEqualTo ("/foo/bar/..b/" );
944+ assertThat (buildRequest (Example .class , "..\\ .." ).url ().encodedPath ())
945+ .isEqualTo ("/foo/bar/..%5C../" );
946+ }
947+
948+ @ Test public void dotDotsOkayWhenNotFullPathSegment () {
949+ class Example {
950+ @ GET ("/foo{ping}bar/" ) //
951+ Call <ResponseBody > method (@ Path (value = "ping" , encoded = true ) String ping ) {
952+ return null ;
953+ }
954+ }
955+
956+ assertMalformedRequest (Example .class , "/./" );
957+ assertMalformedRequest (Example .class , "/../" );
958+
959+ assertThat (buildRequest (Example .class , "." ).url ().encodedPath ()).isEqualTo ("/foo.bar/" );
960+ assertThat (buildRequest (Example .class , ".." ).url ().encodedPath ()).isEqualTo ("/foo..bar/" );
961+ }
962+
881963 @ Test public void pathParamRequired () {
882964 class Example {
883965 @ GET ("/foo/bar/{ping}/" ) //
@@ -2783,4 +2865,12 @@ static <T> Request buildRequest(Class<T> cls, Object... args) {
27832865
27842866 return buildRequest (cls , retrofitBuilder , args );
27852867 }
2868+
2869+ static void assertMalformedRequest (Class <?> cls , Object ... args ) {
2870+ try {
2871+ Request request = buildRequest (cls , args );
2872+ fail ("expected a malformed request but was " + request );
2873+ } catch (IllegalArgumentException expected ) {
2874+ }
2875+ }
27862876}
0 commit comments