@@ -12,23 +12,19 @@ const workspaceRoot = "/workspace";
1212const settingsPath = path . join ( appRoot , "settings.json" ) ;
1313
1414function safeWorkspaceResolve ( uri : string ) : string {
15- if ( ! uri || typeof uri !== "string" ) {
16- throw new Error ( "Invalid path" ) ;
17- }
15+ const absPath = path . isAbsolute ( uri )
16+ ? path . resolve ( uri )
17+ : path . resolve ( workspaceRoot , uri ) ;
1818
19- // uri should be an absolute path
20- if ( ! path . isAbsolute ( uri ) ) {
21- throw new Error ( "Path must be absolute" ) ;
22- }
19+ // Resolve symlinks to their actual paths
20+ const realPath = fs . existsSync ( absPath ) ? fs . realpathSync ( absPath ) : absPath ;
2321
24- // Check that candidate is strictly under rootPath (or equal to rootPath)
25- const rel = path . relative ( workspaceRoot , uri ) ;
26- // Allow if candidate is rootPath itself, or a subpath (not escaping via '..', not absolute)
27- if ( rel === "" || ( ! rel . startsWith ( ".." ) && ! path . isAbsolute ( rel ) ) ) {
28- return uri ;
22+ // Ensure it’s inside the workspace root
23+ if ( ! realPath . startsWith ( workspaceRoot + path . sep ) ) {
24+ throw new Error ( "Cannot access path outside of workspace path." ) ;
2925 }
3026
31- throw new Error ( "Can only access paths within the project home directory." ) ;
27+ return realPath ;
3228}
3329
3430export async function handlePlatformAPIRequest (
@@ -50,20 +46,20 @@ export async function handlePlatformAPIRequest(
5046 throw new Error ( "Method not implemented." ) ;
5147 case "list-projects" : {
5248 const { uri } : { uri : string } = args ;
53- return await handleListProjects ( uri ) ;
49+ return await handleListProjects ( safeWorkspaceResolve ( uri ) ) ;
5450 }
5551 case "list-path-content" : {
5652 const { uri, options } : { uri : string ; options ?: any } = args ;
57- return await handleListPathContent ( uri , options ) ;
53+ return await handleListPathContent ( safeWorkspaceResolve ( uri ) , options ) ;
5854 }
5955 case "create-project" : {
6056 const { uri } : { uri : string } = args ;
61- await handleCreateProject ( uri ) ;
57+ await handleCreateProject ( safeWorkspaceResolve ( uri ) ) ;
6258 return ;
6359 }
6460 case "delete-project" : {
6561 const { uri } : { uri : string } = args ;
66- await handleDeleteProject ( uri ) ;
62+ await handleDeleteProject ( safeWorkspaceResolve ( uri ) ) ;
6763 return ;
6864 }
6965 case "update-project" : {
@@ -77,45 +73,51 @@ export async function handlePlatformAPIRequest(
7773 ctime ?: Date ;
7874 } ;
7975 } = args ;
80- await handleUpdateProject ( uri , updatedInfo ) ;
76+ await handleUpdateProject ( safeWorkspaceResolve ( uri ) , updatedInfo ) ;
8177 return ;
8278 }
8379 case "create-folder" : {
8480 const { uri } : { uri : string } = args ;
85- await handleCreateFolder ( uri ) ;
81+ await handleCreateFolder ( safeWorkspaceResolve ( uri ) ) ;
8682 return ;
8783 }
8884 case "create-file" : {
8985 const { uri } : { uri : string } = args ;
90- await handleCreateFile ( uri ) ;
86+ await handleCreateFile ( safeWorkspaceResolve ( uri ) ) ;
9187 return ;
9288 }
9389 case "rename" : {
9490 const { oldUri, newUri } : { oldUri : string ; newUri : string } = args ;
95- await handleRename ( oldUri , newUri ) ;
91+ await handleRename (
92+ safeWorkspaceResolve ( oldUri ) ,
93+ safeWorkspaceResolve ( newUri ) ,
94+ ) ;
9695 return ;
9796 }
9897 case "delete" : {
9998 const { uri } : { uri : string } = args ;
100- await handleDelete ( uri ) ;
99+ await handleDelete ( safeWorkspaceResolve ( uri ) ) ;
101100 return ;
102101 }
103102 case "has-path" : {
104103 const { uri } : { uri : string } = args ;
105- return await handleHasPath ( uri ) ;
104+ return await handleHasPath ( safeWorkspaceResolve ( uri ) ) ;
106105 }
107106 case "read-file" : {
108107 const { uri } : { uri : string } = args ;
109- return await handleReadFile ( uri ) ;
108+ return await handleReadFile ( safeWorkspaceResolve ( uri ) ) ;
110109 }
111110 case "write-file" : {
112111 const { data, uri } : { data : any ; uri : string } = args ;
113- await handleWriteFile ( data , uri ) ;
112+ await handleWriteFile ( data , safeWorkspaceResolve ( uri ) ) ;
114113 return ;
115114 }
116115 case "copy-files" : {
117116 const { from, to } : { from : string ; to : string } = args ;
118- await handleCopyFiles ( from , to ) ;
117+ await handleCopyFiles (
118+ safeWorkspaceResolve ( from ) ,
119+ safeWorkspaceResolve ( to ) ,
120+ ) ;
119121 return ;
120122 }
121123 case "get-persistent-settings" :
@@ -137,14 +139,13 @@ export async function handlePlatformAPIRequest(
137139
138140// List all folders in a path
139141async function handleListProjects ( uri : string ) {
140- const rootPath = safeWorkspaceResolve ( uri ) ;
141- const files = await fs . promises . readdir ( rootPath , { withFileTypes : true } ) ;
142+ const files = await fs . promises . readdir ( uri , { withFileTypes : true } ) ;
142143 const folders = files
143144 . filter ( ( file ) => file . isDirectory ( ) )
144145 . map ( ( file ) => file . name )
145146 . map ( ( projectName ) => ( {
146147 name : projectName ,
147- ctime : fs . statSync ( path . join ( rootPath , projectName ) ) . ctime ,
148+ ctime : fs . statSync ( path . join ( uri , projectName ) ) . ctime ,
148149 } ) ) ;
149150
150151 return folders ;
@@ -155,8 +156,7 @@ async function listPathContent(
155156 options : any ,
156157 baseUri : string | undefined = undefined ,
157158) {
158- const rootPath = safeWorkspaceResolve ( uri ) ;
159- const files = await fs . promises . readdir ( rootPath , { withFileTypes : true } ) ;
159+ const files = await fs . promises . readdir ( uri , { withFileTypes : true } ) ;
160160
161161 const promise : Promise < any > [ ] = files
162162 // Filter by file type
@@ -183,7 +183,7 @@ async function listPathContent(
183183 } )
184184 . map ( async ( file ) => {
185185 const name = file . name ;
186- const absoluteUri = path . join ( rootPath , name ) ;
186+ const absoluteUri = path . join ( uri , name ) ;
187187 if ( file . isDirectory ( ) ) {
188188 return {
189189 name : name ,
@@ -212,14 +212,12 @@ async function handleListPathContent(uri: string, options: any) {
212212
213213async function handleCreateProject ( uri : string ) {
214214 // Create a folder at the validated path
215- const safe = safeWorkspaceResolve ( uri ) ;
216- await fs . promises . mkdir ( safe , { recursive : true } ) ;
215+ await fs . promises . mkdir ( uri , { recursive : true } ) ;
217216}
218217
219218async function handleDeleteProject ( uri : string ) {
220219 // Delete the folder at the validated path
221- const safe = safeWorkspaceResolve ( uri ) ;
222- await fs . promises . rm ( safe , { recursive : true , force : true } ) ;
220+ await fs . promises . rm ( uri , { recursive : true , force : true } ) ;
223221}
224222
225223async function handleUpdateProject (
@@ -229,73 +227,67 @@ async function handleUpdateProject(
229227 ctime ?: Date ;
230228 } ,
231229) {
232- const safeOld = safeWorkspaceResolve ( uri ) ;
233- const newPathCandidate = path . join ( path . dirname ( safeOld ) , updatedInfo . name ) ;
234- const safeNew = safeWorkspaceResolve ( newPathCandidate ) ;
235- await fs . promises . rename ( safeOld , safeNew ) ;
230+ // Make sure updatedInfo.name is valid name, not a path
231+ if ( path . basename ( updatedInfo . name ) !== updatedInfo . name ) {
232+ throw new Error ( "Invalid project name" ) ;
233+ }
234+
235+ // Rename the project folder
236+ const newUri = path . join ( path . dirname ( uri ) , updatedInfo . name ) ;
237+ await fs . promises . rename ( uri , newUri ) ;
236238}
237239
238240async function handleCreateFolder ( uri : string ) {
239241 // Create a folder at the validated path
240- const safe = safeWorkspaceResolve ( uri ) ;
241- await fs . promises . mkdir ( safe , { recursive : true } ) ;
242+ await fs . promises . mkdir ( uri , { recursive : true } ) ;
242243}
243244
244245async function handleCreateFile ( uri : string ) {
245246 // Create a file at the validated path
246- const safe = safeWorkspaceResolve ( uri ) ;
247247 // ensure parent exists
248- await fs . promises . mkdir ( path . dirname ( safe ) , { recursive : true } ) ;
249- await fs . promises . writeFile ( safe , "" ) ;
248+ await fs . promises . mkdir ( path . dirname ( uri ) , { recursive : true } ) ;
249+ await fs . promises . writeFile ( uri , "" ) ;
250250}
251251
252252async function handleRename ( oldUri : string , newUri : string ) {
253- const safeOld = safeWorkspaceResolve ( oldUri ) ;
254- const safeNew = safeWorkspaceResolve ( newUri ) ;
255- await fs . promises . rename ( safeOld , safeNew ) ;
253+ await fs . promises . rename ( oldUri , newUri ) ;
256254}
257255
258256async function handleDelete ( uri : string ) {
259- const safe = safeWorkspaceResolve ( uri ) ;
260- await fs . promises . rm ( safe , {
257+ await fs . promises . rm ( uri , {
261258 recursive : true ,
262259 force : true ,
263260 } ) ;
264261}
265262
266263async function handleHasPath ( uri : string ) {
267264 try {
268- const safe = safeWorkspaceResolve ( uri ) ;
269- return fs . existsSync ( safe ) ;
265+ return fs . existsSync ( uri ) ;
270266 } catch ( err ) {
271267 return false ;
272268 }
273269}
274270
275271async function handleReadFile ( uri : string ) {
276272 // Read the file at validated path
277- const safe = safeWorkspaceResolve ( uri ) ;
278- const data = await fs . promises . readFile ( safe , "utf-8" ) ;
273+ const data = await fs . promises . readFile ( uri , "utf-8" ) ;
279274 return data ;
280275}
281276
282277async function handleWriteFile ( data : any , uri : string ) {
283278 // Write the data at validated path
284- const safePath = safeWorkspaceResolve ( uri ) ;
285279 // create parent directory if it doesn't exist
286- const dir = path . dirname ( safePath ) ;
280+ const dir = path . dirname ( uri ) ;
287281 if ( ! fs . existsSync ( dir ) ) {
288282 fs . mkdirSync ( dir , { recursive : true } ) ;
289283 }
290284
291- fs . writeFileSync ( safePath , data ) ;
285+ fs . writeFileSync ( uri , data ) ;
292286}
293287
294288async function handleCopyFiles ( from : string , to : string ) {
295289 // Copy the files from the validated from path to the validated to path
296- const safeFrom = safeWorkspaceResolve ( from ) ;
297- const safeTo = safeWorkspaceResolve ( to ) ;
298- await fs . promises . cp ( safeFrom , safeTo , { recursive : true } ) ;
290+ await fs . promises . cp ( from , to , { recursive : true } ) ;
299291}
300292
301293async function handleLoadSettings ( ) {
0 commit comments