@@ -4497,4 +4497,107 @@ describe('(GHSA-p2w6-rmh7-w8q3) SQL Injection via aggregate and distinct field n
44974497 expect ( response . data ?. results ) . toEqual ( [ 'Alice' ] ) ;
44984498 } ) ;
44994499 } ) ;
4500+
4501+ describe ( '(GHSA-37mj-c2wf-cx96) /users/me leaks raw authData via master context' , ( ) => {
4502+ const headers = {
4503+ 'X-Parse-Application-Id' : 'test' ,
4504+ 'X-Parse-REST-API-Key' : 'rest' ,
4505+ 'Content-Type' : 'application/json' ,
4506+ } ;
4507+
4508+ it ( 'does not leak raw MFA authData via /users/me' , async ( ) => {
4509+ await reconfigureServer ( {
4510+ auth : {
4511+ mfa : {
4512+ enabled : true ,
4513+ options : [ 'TOTP' ] ,
4514+ algorithm : 'SHA1' ,
4515+ digits : 6 ,
4516+ period : 30 ,
4517+ } ,
4518+ } ,
4519+ } ) ;
4520+ const user = await Parse . User . signUp ( 'username' , 'password' ) ;
4521+ const sessionToken = user . getSessionToken ( ) ;
4522+ const OTPAuth = require ( 'otpauth' ) ;
4523+ const secret = new OTPAuth . Secret ( ) ;
4524+ const totp = new OTPAuth . TOTP ( {
4525+ algorithm : 'SHA1' ,
4526+ digits : 6 ,
4527+ period : 30 ,
4528+ secret,
4529+ } ) ;
4530+ const token = totp . generate ( ) ;
4531+ // Enable MFA
4532+ await user . save (
4533+ { authData : { mfa : { secret : secret . base32 , token } } } ,
4534+ { sessionToken }
4535+ ) ;
4536+ // Verify MFA data is stored (master key)
4537+ await user . fetch ( { useMasterKey : true } ) ;
4538+ expect ( user . get ( 'authData' ) . mfa . secret ) . toBe ( secret . base32 ) ;
4539+ expect ( user . get ( 'authData' ) . mfa . recovery ) . toBeDefined ( ) ;
4540+ // GET /users/me should NOT include raw MFA data
4541+ const response = await request ( {
4542+ headers : {
4543+ ...headers ,
4544+ 'X-Parse-Session-Token' : sessionToken ,
4545+ } ,
4546+ method : 'GET' ,
4547+ url : 'http://localhost:8378/1/users/me' ,
4548+ } ) ;
4549+ expect ( response . data . authData ?. mfa ?. secret ) . toBeUndefined ( ) ;
4550+ expect ( response . data . authData ?. mfa ?. recovery ) . toBeUndefined ( ) ;
4551+ expect ( response . data . authData ?. mfa ) . toEqual ( { status : 'enabled' } ) ;
4552+ } ) ;
4553+
4554+ it ( 'returns same authData from /users/me and /users/:id' , async ( ) => {
4555+ await reconfigureServer ( {
4556+ auth : {
4557+ mfa : {
4558+ enabled : true ,
4559+ options : [ 'TOTP' ] ,
4560+ algorithm : 'SHA1' ,
4561+ digits : 6 ,
4562+ period : 30 ,
4563+ } ,
4564+ } ,
4565+ } ) ;
4566+ const user = await Parse . User . signUp ( 'username' , 'password' ) ;
4567+ const sessionToken = user . getSessionToken ( ) ;
4568+ const OTPAuth = require ( 'otpauth' ) ;
4569+ const secret = new OTPAuth . Secret ( ) ;
4570+ const totp = new OTPAuth . TOTP ( {
4571+ algorithm : 'SHA1' ,
4572+ digits : 6 ,
4573+ period : 30 ,
4574+ secret,
4575+ } ) ;
4576+ await user . save (
4577+ { authData : { mfa : { secret : secret . base32 , token : totp . generate ( ) } } } ,
4578+ { sessionToken }
4579+ ) ;
4580+ // Fetch via /users/me
4581+ const meResponse = await request ( {
4582+ headers : {
4583+ ...headers ,
4584+ 'X-Parse-Session-Token' : sessionToken ,
4585+ } ,
4586+ method : 'GET' ,
4587+ url : 'http://localhost:8378/1/users/me' ,
4588+ } ) ;
4589+ // Fetch via /users/:id
4590+ const idResponse = await request ( {
4591+ headers : {
4592+ ...headers ,
4593+ 'X-Parse-Session-Token' : sessionToken ,
4594+ } ,
4595+ method : 'GET' ,
4596+ url : `http://localhost:8378/1/users/${ user . id } ` ,
4597+ } ) ;
4598+ // Both should return the same sanitized authData
4599+ expect ( meResponse . data . authData ) . toEqual ( idResponse . data . authData ) ;
4600+ expect ( meResponse . data . authData ?. mfa ) . toEqual ( { status : 'enabled' } ) ;
4601+ } ) ;
4602+ } ) ;
45004603} ) ;
0 commit comments