@@ -3010,6 +3010,92 @@ describe('(GHSA-fjxm-vhvc-gcmj) LiveQuery Operator Type Confusion', () => {
30103010 } ) ;
30113011 } ) ;
30123012
3013+ describe ( '(GHSA-g55g-hrp7-h6vq) Dotted authData provider injection' , ( ) => {
3014+ it ( 'rejects dotted update key that targets authData sub-field' , async ( ) => {
3015+ const user = new Parse . User ( ) ;
3016+ user . setUsername ( 'dotuser' ) ;
3017+ user . setPassword ( 'pass1234' ) ;
3018+ await user . signUp ( ) ;
3019+
3020+ const res = await request ( {
3021+ method : 'PUT' ,
3022+ url : `http://localhost:8378/1/users/${ user . id } ` ,
3023+ headers : {
3024+ 'Content-Type' : 'application/json' ,
3025+ 'X-Parse-Application-Id' : 'test' ,
3026+ 'X-Parse-REST-API-Key' : 'rest' ,
3027+ 'X-Parse-Session-Token' : user . getSessionToken ( ) ,
3028+ } ,
3029+ body : JSON . stringify ( { 'authData.anonymous".id' : 'injected' } ) ,
3030+ } ) . catch ( e => e ) ;
3031+ expect ( res . status ) . toBe ( 400 ) ;
3032+ } ) ;
3033+
3034+ it ( 'login does not crash when stored authData has unknown provider' , async ( ) => {
3035+ const user = new Parse . User ( ) ;
3036+ user . setUsername ( 'dotuser2' ) ;
3037+ user . setPassword ( 'pass1234' ) ;
3038+ await user . signUp ( ) ;
3039+ await Parse . User . logOut ( ) ;
3040+
3041+ // Inject unknown provider directly in database to simulate corrupted data
3042+ const config = Config . get ( 'test' ) ;
3043+ await config . database . update (
3044+ '_User' ,
3045+ { objectId : user . id } ,
3046+ { authData : { unknown_provider : { id : 'bad' } } }
3047+ ) ;
3048+
3049+ // Login should not crash with 500
3050+ const login = await request ( {
3051+ method : 'GET' ,
3052+ url : `http://localhost:8378/1/login?username=dotuser2&password=pass1234` ,
3053+ headers : {
3054+ 'X-Parse-Application-Id' : 'test' ,
3055+ 'X-Parse-REST-API-Key' : 'rest' ,
3056+ } ,
3057+ } ) . catch ( e => e ) ;
3058+ expect ( login . status ) . toBe ( 200 ) ;
3059+ expect ( login . data . sessionToken ) . toBeDefined ( ) ;
3060+ } ) ;
3061+ } ) ;
3062+
3063+ describe ( '(GHSA-2c6m-7356-pw67) Challenge null authData dereference' , ( ) => {
3064+ it ( 'rejects challenge request with null provider value without 500' , async ( ) => {
3065+ const res = await request ( {
3066+ method : 'POST' ,
3067+ url : 'http://localhost:8378/1/challenge' ,
3068+ headers : {
3069+ 'Content-Type' : 'application/json' ,
3070+ 'X-Parse-Application-Id' : 'test' ,
3071+ 'X-Parse-REST-API-Key' : 'rest' ,
3072+ } ,
3073+ body : JSON . stringify ( {
3074+ authData : { anonymous : null } ,
3075+ challengeData : { anonymous : { token : '123456' } } ,
3076+ } ) ,
3077+ } ) . catch ( e => e ) ;
3078+ expect ( res . status ) . toBeLessThan ( 500 ) ;
3079+ } ) ;
3080+
3081+ it ( 'rejects challenge request with non-object provider value without 500' , async ( ) => {
3082+ const res = await request ( {
3083+ method : 'POST' ,
3084+ url : 'http://localhost:8378/1/challenge' ,
3085+ headers : {
3086+ 'Content-Type' : 'application/json' ,
3087+ 'X-Parse-Application-Id' : 'test' ,
3088+ 'X-Parse-REST-API-Key' : 'rest' ,
3089+ } ,
3090+ body : JSON . stringify ( {
3091+ authData : { anonymous : 'string_value' } ,
3092+ challengeData : { anonymous : { token : '123456' } } ,
3093+ } ) ,
3094+ } ) . catch ( e => e ) ;
3095+ expect ( res . status ) . toBeLessThan ( 500 ) ;
3096+ } ) ;
3097+ } ) ;
3098+
30133099 describe ( '(GHSA-r3xq-68wh-gwvh) Password reset single-use token bypass via concurrent requests' , ( ) => {
30143100 let sendPasswordResetEmail ;
30153101
0 commit comments