@@ -3,8 +3,6 @@ package zio.http.security
3
3
import zio ._
4
4
import zio .test ._
5
5
6
- import zio .schema ._
7
-
8
6
import zio .http ._
9
7
import zio .http .codec ._
10
8
import zio .http .endpoint ._
@@ -40,16 +38,16 @@ object UserDataSpec extends ZIOSpecDefault {
40
38
41
39
val spec = suite(" UserDataSpec" )(
42
40
test(" No sanitation and write to server" ) {
41
+ val endpoint = Endpoint (Method .GET / " test" )
42
+ .query(HttpCodec .query[String ](" data" ))
43
+ .out[String ]
44
+ val route = endpoint.implementHandler(Handler .fromFunction { (s : String ) =>
45
+ // writeToServer or other actions
46
+ s
47
+ })
43
48
// this is not a bug but could be a vulnerability used wrong
44
49
check(tuples.zip(functions)) { case (_, msg, expectedResponse, _) =>
45
- val endpoint = Endpoint (Method .GET / " test" )
46
- .query(HttpCodec .query[String ](" data" ))
47
- .out[String ]
48
- val route = endpoint.implementHandler(Handler .fromFunction { case (s : String ) =>
49
- // writeToServer or other actions
50
- s
51
- })
52
- val request =
50
+ val request =
53
51
Request .get(URL (Path .root / " test" , queryParams = QueryParams ((" data" , msg))))
54
52
for {
55
53
response <- route.toRoutes.runZIO(request)
@@ -58,13 +56,13 @@ object UserDataSpec extends ZIOSpecDefault {
58
56
}
59
57
} @@ TestAspect .failing,
60
58
test(" No sanitation using Dom" ) {
59
+ val endpoint = Endpoint (Method .GET / " test" )
60
+ .in[Dom ]
61
+ .out[Dom ]
62
+ val route = endpoint.implementHandler(Handler .fromFunction(identity))
61
63
// this is not a bug but could be a vulnerability used wrong
62
64
check(tuples.zip(functions)) { case (_, msg, expectedResponse, _) =>
63
- val endpoint = Endpoint (Method .GET / " test" )
64
- .in[Dom ]
65
- .out[Dom ]
66
- val route = endpoint.implementHandler(Handler .fromFunction(identity))
67
- val request =
65
+ val request =
68
66
Request .post(URL (Path .root / " test" ), Body .fromString(msg))
69
67
for {
70
68
response <- route.toRoutes.runZIO(request)
@@ -73,28 +71,29 @@ object UserDataSpec extends ZIOSpecDefault {
73
71
}
74
72
} @@ TestAspect .failing,
75
73
test(" Header injection" ) {
76
- check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, f) =>
77
- val endpoint = Endpoint (Method .GET / " test" )
78
- .query(HttpCodec .query[String ](" data" ))
79
- .out[Dom ]
80
- val route = endpoint.implementHandler(Handler .fromFunction { case (s : String ) => f(s) })
81
- val request =
82
- Request
83
- .get(URL (Path .root / " test" , queryParams = QueryParams ((" data" , msg))))
84
- .addHeader(Header .Accept (mediaType))
85
- for {
86
- response <- route.toRoutes.runZIO(request)
87
- body <- response.body.asString
88
- } yield assertTrue(body.contains(expectedResponse))
74
+ check(tuples.zip(functions).zip(Gen .alphaNumericStringBounded(1 , 50 ))) {
75
+ case (mediaType, msg, expectedResponse, f, suffix) =>
76
+ val endpoint = Endpoint (Method .GET / " test" / suffix)
77
+ .query(HttpCodec .query[String ](" data" ))
78
+ .out[Dom ]
79
+ val route = endpoint.implementHandler(Handler .fromFunction { (s : String ) => f(s) })
80
+ val request =
81
+ Request
82
+ .get(URL (Path .root / " test" / suffix, queryParams = QueryParams ((" data" , msg))))
83
+ .addHeader(Header .Accept (mediaType))
84
+ for {
85
+ response <- route.toRoutes.runZIO(request)
86
+ body <- response.body.asString
87
+ } yield assertTrue(body.contains(expectedResponse))
89
88
}
90
89
},
91
90
test(" Header injection DOM" ) {
91
+ val endpoint = Endpoint (Method .GET / " test" )
92
+ .query(HttpCodec .query[Dom ](" data" ))
93
+ .out[Dom ]
94
+ val route = endpoint.implementHandler(Handler .fromFunction(s => s))
92
95
check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, _) =>
93
- val endpoint = Endpoint (Method .GET / " test" )
94
- .query(HttpCodec .query[Dom ](" data" ))
95
- .out[Dom ]
96
- val route = endpoint.implementHandler(Handler .fromFunction(s => s))
97
- val request =
96
+ val request =
98
97
Request
99
98
.get(URL (Path .root / " test" , queryParams = QueryParams ((" data" , msg))))
100
99
.addHeader(Header .Accept (mediaType))
@@ -105,52 +104,57 @@ object UserDataSpec extends ZIOSpecDefault {
105
104
}
106
105
} @@ TestAspect .failing,
107
106
test(" Path injection" ) {
108
- check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, f) =>
109
- val request = Request .get(URL (Path .root / " test" / msg)).addHeader(Header .Accept (mediaType))
110
- val route = Routes (
111
- Endpoint (Method .GET / " test" / string(" message" ))
112
- .out[Dom ]
113
- .implementHandler(Handler .fromFunction { case (s : String ) =>
114
- f(s)
115
- }),
116
- )
117
- for {
118
- response <- route.runZIO(request)
119
- body <- response.body.asString
120
- } yield assertTrue(body.contains(expectedResponse))
107
+ check(tuples.zip(functions).zip(Gen .alphaNumericStringBounded(1 , 50 ))) {
108
+ case (mediaType, msg, expectedResponse, f, suffix) =>
109
+ val request = Request .get(URL (Path .root / " test" / suffix / msg)).addHeader(Header .Accept (mediaType))
110
+ val route = Routes (
111
+ Endpoint (Method .GET / " test" / suffix / string(" message" ))
112
+ .out[Dom ]
113
+ .implementHandler(Handler .fromFunction { (s : String ) =>
114
+ f(s)
115
+ }),
116
+ )
117
+ for {
118
+ response <- route.runZIO(request)
119
+ body <- response.body.asString
120
+ } yield assertTrue(body.contains(expectedResponse))
121
121
}
122
122
},
123
123
test(" Body injection" ) {
124
- check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, f) =>
125
- val body = Body .fromArray(msg.getBytes())
126
- val request = Request .post(" /test" , body).addHeader(Header .Accept (mediaType))
127
- val route = Routes (Method .POST / " test" -> handler { (req : Request ) =>
124
+ check(tuples.zip(functions).zip(Gen .alphaNumericStringBounded(1 , 50 ))) {
125
+ case (mediaType, msg, expectedResponse, f, suffix) =>
126
+ val body = Body .fromArray(msg.getBytes())
127
+ val request = Request .post(url " /test/ $suffix" , body).addHeader(Header .Accept (mediaType))
128
+ val route = Routes (Method .POST / " test" / suffix -> handler { (req : Request ) =>
129
+ for {
130
+ msg <- req.body.asString.orDie
131
+ } yield Response .text(f(msg).encode)
132
+ })
128
133
for {
129
- msg <- req.body.asString.orDie
130
- } yield Response .text(f(msg).encode)
131
- })
132
- for {
133
- response <- route.runZIO(request)
134
- body <- response.body.asString
135
- } yield assertTrue(body.contains(expectedResponse))
134
+ response <- route.runZIO(request)
135
+ body <- response.body.asString
136
+ } yield assertTrue(body.contains(expectedResponse))
136
137
}
137
138
},
138
139
test(" Error injection" ) {
139
- check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, _) =>
140
- val routes = Routes (Method .POST / " test" -> handler { (req : Request ) =>
141
- req.body.asString.orDie.map(msg => Response .error(Status .InternalServerError , msg))
142
- })
143
- val body = Body .fromString(msg)
144
- val request = Request .post(" /test" , body).addHeader(Header .Accept (mediaType))
145
- for {
146
- port <- Server .install(routes)
147
- response <- ZIO .scoped {
148
- Client
149
- .batched(request.updateURL(_ => URL .decode(s " http://localhost: $port/test " ).toOption.get))
150
- }
151
- body <- response.body.asString
152
- } yield assertTrue(body == expectedResponse)
153
- }
140
+ val routes = Routes (Method .POST / " test" -> handler { (req : Request ) =>
141
+ req.body.asString.orDie.map(msg => Response .error(Status .InternalServerError , msg))
142
+ })
143
+ for {
144
+ port <- Server .install(routes)
145
+ result <- check(tuples.zip(functions)) { case (mediaType, msg, expectedResponse, _) =>
146
+
147
+ val body = Body .fromString(msg)
148
+ val request = Request .post(" /test" , body).addHeader(Header .Accept (mediaType))
149
+ for {
150
+ response <- ZIO .scoped {
151
+ Client
152
+ .batched(request.updateURL(_ => URL .decode(s " http://localhost: $port/test " ).toOption.get))
153
+ }
154
+ body <- response.body.asString
155
+ } yield assertTrue(body == expectedResponse)
156
+ }
157
+ } yield result
154
158
},
155
159
).provide(
156
160
Scope .default,
@@ -160,6 +164,6 @@ object UserDataSpec extends ZIOSpecDefault {
160
164
),
161
165
ZLayer .succeed(NettyConfig .defaultWithFastShutdown),
162
166
Client .default,
163
- )
167
+ ) @@ TestAspect .sequential
164
168
165
169
}
0 commit comments