@@ -653,6 +653,79 @@ describe('Parse.File testing', () => {
653653 done ( ) ;
654654 } ) ;
655655 } ) ;
656+
657+ describe ( 'URI-backed file upload is disabled to prevent SSRF attack' , ( ) => {
658+ const express = require ( 'express' ) ;
659+ let testServer ;
660+ let testServerPort ;
661+ let requestsMade ;
662+
663+ beforeEach ( async ( ) => {
664+ requestsMade = [ ] ;
665+ const app = express ( ) ;
666+ app . use ( ( req , res ) => {
667+ requestsMade . push ( { url : req . url , method : req . method } ) ;
668+ res . status ( 200 ) . send ( 'test file content' ) ;
669+ } ) ;
670+ testServer = app . listen ( 0 ) ;
671+ testServerPort = testServer . address ( ) . port ;
672+ } ) ;
673+
674+ afterEach ( async ( ) => {
675+ if ( testServer ) {
676+ await new Promise ( resolve => testServer . close ( resolve ) ) ;
677+ }
678+ } ) ;
679+
680+ it ( 'does not access URI when file upload attempted over REST' , async ( ) => {
681+ const response = await request ( {
682+ method : 'POST' ,
683+ url : 'http://localhost:8378/1/classes/TestClass' ,
684+ headers : {
685+ 'Content-Type' : 'application/json' ,
686+ 'X-Parse-Application-Id' : 'test' ,
687+ 'X-Parse-REST-API-Key' : 'rest' ,
688+ } ,
689+ body : {
690+ file : {
691+ __type : 'File' ,
692+ name : 'test.txt' ,
693+ _source : {
694+ format : 'uri' ,
695+ uri : `http://127.0.0.1:${ testServerPort } /secret-file.txt` ,
696+ } ,
697+ } ,
698+ } ,
699+ } ) ;
700+ expect ( response . status ) . toBe ( 201 ) ;
701+ // Verify no HTTP request was made to the URI
702+ expect ( requestsMade . length ) . toBe ( 0 ) ;
703+ } ) ;
704+
705+ it ( 'does not access URI when file created in beforeSave trigger' , async ( ) => {
706+ Parse . Cloud . beforeSave ( Parse . File , ( ) => {
707+ return new Parse . File ( 'trigger-file.txt' , {
708+ uri : `http://127.0.0.1:${ testServerPort } /secret-file.txt` ,
709+ } ) ;
710+ } ) ;
711+ try {
712+ await request ( {
713+ method : 'POST' ,
714+ headers : {
715+ 'Content-Type' : 'application/octet-stream' ,
716+ 'X-Parse-Application-Id' : 'test' ,
717+ 'X-Parse-REST-API-Key' : 'rest' ,
718+ } ,
719+ url : 'http://localhost:8378/1/files/test.txt' ,
720+ body : 'test content' ,
721+ } ) ;
722+ } catch ( error ) {
723+ expect ( error . status ) . toBe ( 400 ) ;
724+ }
725+ // Verify no HTTP request was made to the URI
726+ expect ( requestsMade . length ) . toBe ( 0 ) ;
727+ } ) ;
728+ } ) ;
656729 } ) ;
657730
658731 describe ( 'deleting files' , ( ) => {
0 commit comments