x402-surface-check 0.2.3 → 0.2.4

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 CHANGED
@@ -24,6 +24,7 @@ npx --yes x402-surface-check --endpoint --method POST https://x402.rpc.ankr.com/
24
24
  - HTTPS resource URLs and stable resource metadata
25
25
  - Browser CORS allowance for `X-PAYMENT`
26
26
  - Over-broad public method surfaces
27
+ - Auth, validation, and free/trial responses that appear before a payment challenge, without piling on missing-field findings when no challenge was actually returned
27
28
 
28
29
  ## Options
29
30
 
@@ -373,6 +373,11 @@ function challengeAccepts(result) {
373
373
  return Array.isArray(result.body.json?.accepts) ? result.body.json.accepts : []
374
374
  }
375
375
 
376
+ function hasPaymentChallenge(result) {
377
+ const challenge = result.body.json
378
+ return challengeAccepts(result).length > 0 || Boolean(challenge?.resource || challenge?.payment || result.headers?.['www-authenticate'])
379
+ }
380
+
376
381
  function challengeSummary(result) {
377
382
  const challenge = result.body.json
378
383
  const firstAccept = challenge?.accepts?.[0] ?? {}
@@ -427,10 +432,27 @@ function findingList(documentResult, challengeResults, preflightResults, entries
427
432
  for (const result of challengeResults) {
428
433
  const summary = challengeSummary(result)
429
434
  if (summary.network) challengeNetworks.add(summary.network)
435
+ const hasChallenge = hasPaymentChallenge(result)
430
436
 
431
437
  if (result.status !== 402) {
432
- findings.push(`P1 - ${result.name} returned ${result.status}, not 402, for a no-payment ${result.method ?? 'POST'} probe.`)
438
+ if (result.status >= 200 && result.status < 300) {
439
+ findings.push(`P3 - ${result.name} returned ${result.status} without a payment challenge for a no-payment ${result.method ?? 'POST'} probe; document this as free/trial access or move the 402 challenge before content.`)
440
+ }
441
+ else if (result.status === 400 || result.status === 422) {
442
+ findings.push(`P1 - ${result.name} returned validation HTTP ${result.status} before a payment challenge for a no-payment ${result.method ?? 'POST'} probe.`)
443
+ }
444
+ else if (result.status === 401 || result.status === 403) {
445
+ findings.push(`P2 - ${result.name} returned auth HTTP ${result.status} before a payment challenge for a no-payment ${result.method ?? 'POST'} probe; document the auth/free-tier order if this is intentional.`)
446
+ }
447
+ else {
448
+ findings.push(`P1 - ${result.name} returned ${result.status}, not 402, for a no-payment ${result.method ?? 'POST'} probe.`)
449
+ }
433
450
  }
451
+
452
+ if (!hasChallenge) {
453
+ continue
454
+ }
455
+
434
456
  if (summary.resourceUrl.startsWith('http://') || summary.extraResource.startsWith('http://')) {
435
457
  findings.push(`P1 - ${result.name} challenge uses a non-HTTPS resource URL: ${summary.resourceUrl || summary.extraResource}.`)
436
458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x402-surface-check",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "No-payment x402 public-surface checker for manifests, OpenAPI specs, and HTTP 402 challenges.",
5
5
  "type": "module",
6
6
  "bin": {