You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
app.get(\"/verdict/:transaction/payload\", ...) in x402r-ai-garbage-detector/src/arbiter.ts:237-271 gates the stored response body behind a payer signature. The scheme as written has three defensible but non-production-grade weaknesses. Threat surface is narrow today (the payer already received the content at payment time, so replay mostly buys "re-fetching what you could have cached"), but the scheme wouldn't pass a review as-is, and the pattern is likely to get copy-pasted into arbiters that gate more sensitive content.
Issues
1. No replay protection / no freshness
Signed message is literally x402r:payload:{txHash}. That signature is valid forever. Any leak of the Authorization header (browser devtools, server logs, HTTP proxy, exfiltrated backup) grants indefinite re-request access. No nonce, no timestamp, no rotation path.
2. No domain binding
The message excludes chain ID, arbiter address, and endpoint path. A signature made for arbiter A's endpoint would verify against arbiter B's if B copies the same format. A rogue arbiter could passively observe a payer signature in logs and then use it against its own copy of the same code.
3. Non-standard Authorization header
Bare hex, no scheme prefix — no Bearer, no Sig. HTTP RFC 7235 expects Authorization: <scheme> <credentials>. A caller who sends Authorization: Bearer 0xabc... (the RFC-conformant form) will have the Bearer prefix included in signature, verifyMessage throws, the catch returns 403 \"Invalid signature\" with no guidance. A caller who follows the README sends bare hex, which works but isn't standards-compliant.
Severity
Not broken-exploitable today. Becomes real when:
(a) VERDICTS_DIR persists across more than the current in-memory lifetime (e.g., mounted volume),
(b) this auth pattern is reused for content more sensitive than a weather blurb,
(c) log pipelines retain Authorization headers (common default in many observability stacks).
Proposed fix (~2-3 hours + tests)
Message format
Replace x402r:payload:{txHash} with a structured, versioned, domain-bound message:
Context
app.get(\"/verdict/:transaction/payload\", ...)inx402r-ai-garbage-detector/src/arbiter.ts:237-271gates the stored response body behind a payer signature. The scheme as written has three defensible but non-production-grade weaknesses. Threat surface is narrow today (the payer already received the content at payment time, so replay mostly buys "re-fetching what you could have cached"), but the scheme wouldn't pass a review as-is, and the pattern is likely to get copy-pasted into arbiters that gate more sensitive content.Issues
1. No replay protection / no freshness
Signed message is literally
x402r:payload:{txHash}. That signature is valid forever. Any leak of theAuthorizationheader (browser devtools, server logs, HTTP proxy, exfiltrated backup) grants indefinite re-request access. No nonce, no timestamp, no rotation path.2. No domain binding
The message excludes chain ID, arbiter address, and endpoint path. A signature made for arbiter A's endpoint would verify against arbiter B's if B copies the same format. A rogue arbiter could passively observe a payer signature in logs and then use it against its own copy of the same code.
3. Non-standard Authorization header
Bare hex, no scheme prefix — no
Bearer, noSig. HTTP RFC 7235 expectsAuthorization: <scheme> <credentials>. A caller who sendsAuthorization: Bearer 0xabc...(the RFC-conformant form) will have theBearerprefix included insignature,verifyMessagethrows, thecatchreturns 403\"Invalid signature\"with no guidance. A caller who follows the README sends bare hex, which works but isn't standards-compliant.Severity
Not broken-exploitable today. Becomes real when:
VERDICTS_DIRpersists across more than the current in-memory lifetime (e.g., mounted volume),Authorizationheaders (common default in many observability stacks).Proposed fix (~2-3 hours + tests)
Message format
Replace
x402r:payload:{txHash}with a structured, versioned, domain-bound message:Server-side checks
abs(now - created) < 300seconds (±5 min skew tolerance; reject if outside window).chainmatches a supported chain,arbitermatchesclients.account.address,txmatchesreq.params.transaction.Authorizationheadercreatedoutside freshness windowstored.payerHeader format
Switch to an RFC-conformant custom scheme:
Server parses
Authorization: X402rSig <hex>, strips prefix beforeverifyMessage.Acceptance criteria
createdtimestamparbiter.tsupdated to reflect the new schemex402-frontend/apps/web/content/blog/open-sourcing-error-detector-arbiter.md:187updated to document the new formatOut of scope
/verify(separate concern — inference cost exposure)app.use(cors())is wide-open by design for a public arbiter)