Skip to content

security: audit wave 2 — x402 underpayment guard, SSRF DNS-rebinding pin - #314

Merged
kh0ra merged 1 commit into
mainfrom
security/audit-wave2
Jun 21, 2026
Merged

kh0ra merged 1 commit into
mainfrom
security/audit-wave2

Conversation

@kh0ra

@kh0ra kh0ra commented Jun 21, 2026

Copy link
Copy Markdown
Member

Audit wave 2 — two contained, high-value off-chain fixes

x402 facilitator underpayment guard (app/lib/x402-server.ts)

On the optional facilitator verification path, when the facilitator echoes the paid amount we now re-check server-side that it covers the required amount. A misconfigured/compromised facilitator can no longer approve an underpayment. The default (no-facilitator) path already does full on-chain parsing (amount/mint/recipient/confirmed).

SSRF DNS-rebinding / TOCTOU pin (app/lib/ssrf.ts, app/app/api/agents/register/route.ts)

assertPublicUrl now returns the validated resolved addresses, and a new safeFetch() pins the connection to a vetted IP via an undici dispatcher whose lookup ignores DNS. This closes the gap where a hostname validated as public could rebind to 127.0.0.1 / 169.254.169.254 between the check and the fetch. Agent registration's endpoint health-check now uses safeFetch, so it can't be used as an SSRF probe into internal services.

Deferred (tracked in docs/SECURITY_AUDIT.md / SEC issues)

  • Wallet-signature replay nonce cache
  • Off-chain dispute griefing guard
  • Reputation self-dealing mitigation

Both become meaningful once AUTH_ENFORCED=true; they need a durable store / redesign and are scoped to the frontend-signing milestone.

Test plan

  • Facilitator path: a response reporting amountAtomic < required is rejected with underpaid: ….
  • safeFetch to a hostname that resolves public but rebinds to a private IP connects only to the pinned public address.
  • Agent register with an endpoint that DNS-rebinds to internal is blocked.

…S-rebinding pin

- x402-server: on the optional facilitator path, when the facilitator echoes
  the paid amount, re-check it covers the required amount server-side. A
  misconfigured/compromised facilitator can no longer approve an underpayment;
  the default (no-facilitator) path already does full on-chain parsing.
- ssrf: assertPublicUrl now returns the validated resolved addresses, and a
  new safeFetch() pins the connection to a vetted IP via an undici dispatcher
  whose lookup ignores DNS. This closes the TOCTOU/DNS-rebinding gap where a
  hostname validated as public could rebind to 127.0.0.1 / 169.254.169.254 at
  fetch time.
- agents/register: the endpoint health-check fetch now uses safeFetch with the
  addresses validated by assertPublicUrl, so registration can no longer be used
  as an SSRF probe into internal services.

Deferred (tracked in docs/SECURITY_AUDIT.md): wallet-signature replay nonce
cache and off-chain dispute griefing — both meaningful once AUTH_ENFORCED is on
and need a durable store / redesign.
@changeset-bot

changeset-bot Bot commented Jun 21, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7c3d244

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
covenant Ready Ready Preview, Comment Jun 21, 2026 12:51am

@kh0ra
kh0ra merged commit c293036 into main Jun 21, 2026
10 of 12 checks passed
@kh0ra
kh0ra deleted the security/audit-wave2 branch June 21, 2026 10:23

This branch was successfully deployed

1 active deployment
Preview — 7c3d244d Deployed Jun 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant