@@ -50,11 +50,26 @@ <h2>Denied</h2>
5050 import '../../entry'
5151 import json , { msg } from '../../safe.json'
5252
53+ function joinUrlSegments ( a , b ) {
54+ if ( ! a || ! b ) {
55+ return a || b || ''
56+ }
57+ if ( a [ a . length - 1 ] === '/' ) {
58+ a = a . substring ( 0 , a . length - 1 )
59+ }
60+ if ( b [ 0 ] !== '/' ) {
61+ b = '/' + b
62+ }
63+ return a + b
64+ }
65+
5366 text ( '.full' , JSON . stringify ( json ) )
5467 text ( '.named' , msg )
5568
69+ const base = typeof BASE !== 'undefined' ? BASE : ''
70+
5671 // inside allowed dir, safe fetch
57- fetch ( '/src/safe.txt' )
72+ fetch ( joinUrlSegments ( base , '/src/safe.txt' ) )
5873 . then ( ( r ) => {
5974 text ( '.safe-fetch-status' , r . status )
6075 return r . text ( )
@@ -64,7 +79,7 @@ <h2>Denied</h2>
6479 } )
6580
6681 // inside allowed dir with query, safe fetch
67- fetch ( '/src/safe.txt?query' )
82+ fetch ( joinUrlSegments ( base , '/src/safe.txt?query' ) )
6883 . then ( ( r ) => {
6984 text ( '.safe-fetch-query-status' , r . status )
7085 return r . text ( )
@@ -74,7 +89,7 @@ <h2>Denied</h2>
7489 } )
7590
7691 // inside allowed dir, safe fetch
77- fetch ( '/src/subdir/safe.txt' )
92+ fetch ( joinUrlSegments ( base , '/src/subdir/safe.txt' ) )
7893 . then ( ( r ) => {
7994 text ( '.safe-fetch-subdir-status' , r . status )
8095 return r . text ( )
@@ -84,7 +99,12 @@ <h2>Denied</h2>
8499 } )
85100
86101 // inside allowed dir, with special characters, safe fetch
87- fetch ( '/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.txt' )
102+ fetch (
103+ joinUrlSegments (
104+ base ,
105+ '/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.txt' ,
106+ ) ,
107+ )
88108 . then ( ( r ) => {
89109 text ( '.safe-fetch-subdir-special-characters-status' , r . status )
90110 return r . text ( )
@@ -94,7 +114,7 @@ <h2>Denied</h2>
94114 } )
95115
96116 // outside of allowed dir, treated as unsafe
97- fetch ( '/unsafe.txt' )
117+ fetch ( joinUrlSegments ( base , '/unsafe.txt' ) )
98118 . then ( ( r ) => {
99119 text ( '.unsafe-fetch-status' , r . status )
100120 return r . text ( )
@@ -107,7 +127,7 @@ <h2>Denied</h2>
107127 } )
108128
109129 // outside of allowed dir with special characters #8498
110- fetch ( '/src/%2e%2e%2funsafe%2etxt' )
130+ fetch ( joinUrlSegments ( base , '/src/%2e%2e%2funsafe%2etxt' ) )
111131 . then ( ( r ) => {
112132 text ( '.unsafe-fetch-8498-status' , r . status )
113133 return r . text ( )
@@ -120,7 +140,7 @@ <h2>Denied</h2>
120140 } )
121141
122142 // outside of allowed dir with special characters 2 #8498
123- fetch ( '/src/%252e%252e%252funsafe%252etxt' )
143+ fetch ( joinUrlSegments ( base , '/src/%252e%252e%252funsafe%252etxt' ) )
124144 . then ( ( r ) => {
125145 text ( '.unsafe-fetch-8498-2-status' , r . status )
126146 return r . text ( )
@@ -133,7 +153,7 @@ <h2>Denied</h2>
133153 } )
134154
135155 // imported before, should be treated as safe
136- fetch ( '/@fs/' + ROOT + '/safe.json' )
156+ fetch ( joinUrlSegments ( base , joinUrlSegments ( '/@fs/' , ROOT ) + '/safe.json' ) )
137157 . then ( ( r ) => {
138158 text ( '.safe-fs-fetch-status' , r . status )
139159 return r . json ( )
@@ -143,7 +163,9 @@ <h2>Denied</h2>
143163 } )
144164
145165 // imported before with query, should be treated as safe
146- fetch ( '/@fs/' + ROOT + '/safe.json?query' )
166+ fetch (
167+ joinUrlSegments ( base , joinUrlSegments ( '/@fs/' , ROOT ) + '/safe.json?query' ) ,
168+ )
147169 . then ( ( r ) => {
148170 text ( '.safe-fs-fetch-query-status' , r . status )
149171 return r . json ( )
@@ -153,7 +175,7 @@ <h2>Denied</h2>
153175 } )
154176
155177 // not imported before, outside of root, treated as unsafe
156- fetch ( '/@fs/' + ROOT + '/unsafe.json' )
178+ fetch ( joinUrlSegments ( base , joinUrlSegments ( '/@fs/' , ROOT ) + '/unsafe.json' ) )
157179 . then ( ( r ) => {
158180 text ( '.unsafe-fs-fetch-status' , r . status )
159181 return r . json ( )
@@ -166,7 +188,13 @@ <h2>Denied</h2>
166188 } )
167189
168190 // outside root with special characters #8498
169- fetch ( '/@fs/' + ROOT + '/root/src/%2e%2e%2f%2e%2e%2funsafe%2ejson' )
191+ fetch (
192+ joinUrlSegments (
193+ base ,
194+ joinUrlSegments ( '/@fs/' , ROOT ) +
195+ '/root/src/%2e%2e%2f%2e%2e%2funsafe%2ejson' ,
196+ ) ,
197+ )
170198 . then ( ( r ) => {
171199 text ( '.unsafe-fs-fetch-8498-status' , r . status )
172200 return r . json ( )
@@ -177,7 +205,11 @@ <h2>Denied</h2>
177205
178206 // outside root with special characters 2 #8498
179207 fetch (
180- '/@fs/' + ROOT + '/root/src/%252e%252e%252f%252e%252e%252funsafe%252ejson' ,
208+ joinUrlSegments (
209+ base ,
210+ joinUrlSegments ( '/@fs/' , ROOT ) +
211+ '/root/src/%252e%252e%252f%252e%252e%252funsafe%252ejson' ,
212+ ) ,
181213 )
182214 . then ( ( r ) => {
183215 text ( '.unsafe-fs-fetch-8498-2-status' , r . status )
@@ -189,9 +221,11 @@ <h2>Denied</h2>
189221
190222 // not imported before, inside root with special characters, treated as safe
191223 fetch (
192- '/@fs/' +
193- ROOT +
194- '/root/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.json' ,
224+ joinUrlSegments (
225+ base ,
226+ joinUrlSegments ( '/@fs/' , ROOT ) +
227+ '/root/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.json' ,
228+ ) ,
195229 )
196230 . then ( ( r ) => {
197231 text ( '.safe-fs-fetch-special-characters-status' , r . status )
@@ -202,7 +236,7 @@ <h2>Denied</h2>
202236 } )
203237
204238 // .env, denied by default
205- fetch ( '/@fs/' + ROOT + '/root/.env' )
239+ fetch ( joinUrlSegments ( base , joinUrlSegments ( '/@fs/' , ROOT ) + '/root/.env' ) )
206240 . then ( ( r ) => {
207241 text ( '.unsafe-dotenv' , r . status )
208242 } )
0 commit comments