x402-surface-check 0.2.40 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/x402-surface-check.mjs +7 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ npx --yes x402-surface-check --strict-proof https://api.example.com/openapi.json
|
|
|
38
38
|
- Placeholder recipients such as zero addresses and Solana system-program values
|
|
39
39
|
- Testnet or staging rails such as Base Sepolia and Solana devnet
|
|
40
40
|
- HTTPS resource URLs and stable resource metadata
|
|
41
|
-
- Resource binding across top-level `resource.url
|
|
41
|
+
- Resource binding across top-level `resource.url`; legacy/v1 accept-leg resource echoes; and localhost/private-development resource URLs that should not ship in production
|
|
42
42
|
- Timeout/expiry metadata on challenges, so payment capabilities have an explicit bounded freshness window
|
|
43
43
|
- Payment-metadata privacy checks for sensitive resource query context, email/SSN/token-like values, prompt/private-context strings, and credential-like URLs in body or header-carried challenges
|
|
44
44
|
- Browser CORS allowance for the requesting origin, common x402/MPP retry headers, and exposed challenge/session headers on the actual 402 response
|
|
@@ -993,6 +993,10 @@ function challengeResourceValue(challenge) {
|
|
|
993
993
|
?? ''
|
|
994
994
|
}
|
|
995
995
|
|
|
996
|
+
function isX402V2Challenge(challenge) {
|
|
997
|
+
return Number(challenge?.x402Version) === 2
|
|
998
|
+
}
|
|
999
|
+
|
|
996
1000
|
function hasFreshnessMetadata(challenge, accept) {
|
|
997
1001
|
return [
|
|
998
1002
|
challenge?.expires,
|
|
@@ -1016,8 +1020,9 @@ function usesDecimalAmount(accept, result) {
|
|
|
1016
1020
|
const amount = String(rawAmount)
|
|
1017
1021
|
if (amount.includes('.')) return true
|
|
1018
1022
|
if (accept.maxAmountRequired !== undefined || accept.maxAmount !== undefined) return false
|
|
1023
|
+
if (accept.asset) return false
|
|
1019
1024
|
if (!accept.asset && (accept.token || result.headers?.['x-payment-token'])) return true
|
|
1020
|
-
return
|
|
1025
|
+
return false
|
|
1021
1026
|
}
|
|
1022
1027
|
|
|
1023
1028
|
function challengePrice(accept, result) {
|
|
@@ -1404,7 +1409,7 @@ function findingList(documentResult, challengeResults, preflightResults, entries
|
|
|
1404
1409
|
if (!topResource && populatedAcceptResources.length === 0) {
|
|
1405
1410
|
findings.push(`P2 - ${result.name} challenge does not expose a signed/intended resource URL at the top level or in any accept leg.`)
|
|
1406
1411
|
}
|
|
1407
|
-
else if (accepts.length > 0 && populatedAcceptResources.length < accepts.length) {
|
|
1412
|
+
else if (!isX402V2Challenge(result.body.json) && accepts.length > 0 && populatedAcceptResources.length < accepts.length) {
|
|
1408
1413
|
findings.push(`P2 - ${result.name} challenge does not repeat the resource URL in every accept leg for spend-map and replay binding.`)
|
|
1409
1414
|
}
|
|
1410
1415
|
if (topResource && populatedAcceptResources.some(resource => resource !== topResource)) {
|