Skip to content

/api/contracts/escrow/refund missing object-level authorization — any authenticated user can refund any agreement #42

Description

@pplmaverick

Body

Hi team,

POST /api/contracts/escrow/refund takes a client-supplied circleContractId, checks that the caller is authenticated, and then calls Circle's refundByRecipient against the matching escrow agreement. The route doesn't check that the caller is actually a party to that agreement — there's no comparison between the caller's wallet and the agreement's depositor_wallet_id / beneficiary_wallet_id before the refund goes through.

In a deployed setting with real users, that means any authenticated user could trigger a refund on an escrow agreement between two other parties, without either party's involvement. That undermines the two-party guarantee escrow is supposed to provide, and it would also attribute the resulting transaction record to the wrong profile.

Flagging this as a hardening suggestion rather than a vulnerability report — no exploit steps here, just pointing at the missing check in the route logic.

Ask

Add an ownership check in the refund route that compares the caller's wallet against depositor_wallet_id and beneficiary_wallet_id on the target agreement, and reject with a 403 if neither matches, before calling refundByRecipient.

Happy to open a PR if useful.

Context: noticed this while evaluating Arc reference implementations for a project I'm building (circlefin/arc-node#268).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions