@@ -1084,6 +1084,17 @@ function hasMppRetryChallenge(result) {
10841084 return challengeAccepts ( result ) . some ( accept => String ( accept . scheme ?? '' ) . toLowerCase ( ) === 'mpp' )
10851085}
10861086
1087+ function mppDiscoveryHeaders ( headers = { } ) {
1088+ return [
1089+ 'x-mpp-descriptor' ,
1090+ 'x-agent-card' ,
1091+ ] . filter ( name => headers [ name ] !== undefined && headers [ name ] !== '' )
1092+ }
1093+
1094+ function advertisesMppDiscovery ( result ) {
1095+ return mppDiscoveryHeaders ( result . headers ) . length > 0
1096+ }
1097+
10871098function allowsAnyHeader ( headerValue = '' , names = [ ] ) {
10881099 return names . some ( name => headerListAllows ( headerValue , name ) )
10891100}
@@ -1160,6 +1171,10 @@ function findingList(documentResult, challengeResults, preflightResults, entries
11601171 }
11611172
11621173 if ( ! hasChallenge ) {
1174+ const descriptorHeaders = mppDiscoveryHeaders ( result . headers )
1175+ if ( result . status === 402 && descriptorHeaders . length > 0 ) {
1176+ findings . push ( `P1 - ${ result . name } returns 402 and advertises MPP discovery via ${ descriptorHeaders . join ( ', ' ) } , but does not include a WWW-Authenticate: Payment challenge or machine-readable body challenge; autonomous callers cannot construct a paid retry from this response alone.` )
1177+ }
11631178 continue
11641179 }
11651180
@@ -1238,7 +1253,7 @@ function findingList(documentResult, challengeResults, preflightResults, entries
12381253
12391254 for ( const result of preflightResults ) {
12401255 const challengeResult = challengesByEntry . get ( entryKey ( result ) )
1241- if ( ! challengeResult || ( ! hasPaymentChallenge ( challengeResult ) && ! advertisesPaymentEnforcement ( challengeResult . headers ) ) ) continue
1256+ if ( ! challengeResult || ( ! hasPaymentChallenge ( challengeResult ) && ! advertisesPaymentEnforcement ( challengeResult . headers ) && ! advertisesMppDiscovery ( challengeResult ) ) ) continue
12421257 const allowedOrigin = result . headers [ 'access-control-allow-origin' ] ?? ''
12431258 if ( ! allowedOrigin ) {
12441259 findings . push ( `P1 - ${ result . name } CORS preflight does not allow the requesting origin; observed allow-origin: none.` )
@@ -1250,7 +1265,7 @@ function findingList(documentResult, challengeResults, preflightResults, entries
12501265 : `allow headers: ${ allowed || 'none' } `
12511266 findings . push ( `P1 - ${ result . name } CORS preflight does not allow a known x402 retry header (X-PAYMENT or PAYMENT-SIGNATURE); observed ${ observed } .` )
12521267 }
1253- if ( hasMppRetryChallenge ( challengeResult ) && ! headerListAllows ( allowed , 'authorization' ) ) {
1268+ if ( ( hasMppRetryChallenge ( challengeResult ) || advertisesMppDiscovery ( challengeResult ) ) && ! headerListAllows ( allowed , 'authorization' ) ) {
12541269 const observed = result . status >= 400
12551270 ? `HTTP ${ result . status } ; allow headers: ${ allowed || 'none' } `
12561271 : `allow headers: ${ allowed || 'none' } `
0 commit comments