Skip to content

fix(agent_registry): authenticate transaction registration/completion and forbid self-rating (#77) - #211

Open
Vyacheslav-Tomashevskiy wants to merge 1 commit into
vespera-labs:mainfrom
Vyacheslav-Tomashevskiy:fix/agent-registry-auth-77
Open

fix(agent_registry): authenticate transaction registration/completion and forbid self-rating (#77)#211
Vyacheslav-Tomashevskiy wants to merge 1 commit into
vespera-labs:mainfrom
Vyacheslav-Tomashevskiy:fix/agent-registry-auth-77

Conversation

@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown

Issue

Fixes #77[Security] agent_registry register_transaction and complete_transaction are unauthenticated, letting reputation be fabricated.

Problem

In contracts/agent_registry/src/agent.rs:

  • register_transaction never called require_auth on anyone, so any caller could create AgentTransaction records with an attacker-chosen agent and parties.
  • complete_transaction only compared the supplied agent to stored state but never called agent.require_auth(), so anyone could complete on the agent's behalf and bump completed_agreements. It also re-incremented completed_agreements on every repeated call.
  • rate_agent had no rater != agent guard.

Combined, one actor could manufacture transactions, complete them, and rate any verified agent at will.

Fix

  • register_transaction now takes a caller: Address, calls caller.require_auth(), and requires the caller to be the agent or one of the listed parties. parties must be non-empty, all distinct, and must not include the agent — parties are the counterparties who may later rate, so excluding the agent forecloses self-rating at the source (InvalidParties).
  • complete_transaction now calls agent.require_auth() and rejects double-completion with TransactionAlreadyCompleted, so completed_agreements can be bumped at most once per transaction and only by the agent.
  • rate_agent rejects rater == agent with SelfRatingNotAllowed (defense-in-depth alongside the register-time exclusion). The existing party / completed / already-rated checks are kept.

New errors: SelfRatingNotAllowed = 14, InvalidParties = 15, TransactionAlreadyCompleted = 16.

Acceptance criteria

  • register_transaction authenticates a legitimate party and validates parties are distinct/real (non-empty, no duplicates, not the agent)
  • complete_transaction calls require_auth on the agent
  • rate_agent rejects self-rating and only allows a real party of a completed transaction to rate, once
  • Tests assert a non-party cannot register, complete, or rate, and an agent cannot rate itself

Tests

8 new adversarial tests (caller auth required for register/complete; non-participant caller rejected; agent-in-parties / duplicate / empty parties rejected; party caller allowed; double-completion rejected); existing transaction tests updated to the new register_transaction signature.

cargo test -p agent_registry → 31 passed; 0 failed
cargo fmt --check → clean
cargo clippy --tests → no warnings on changed files

Scope / breaking change

register_transaction gains a leading caller: Address parameter (deliberate — required to authenticate the registrant). Out of scope per the issue: weighting reputation by transaction value, cross-contract verification.

RTC payout wallet: RTCd1554f0f35576faf01d386a6be1c947f560dd0b7

… and forbid self-rating (vespera-labs#77)

register_transaction was unauthenticated, letting anyone fabricate
transaction records for arbitrary agents and parties. complete_transaction
never called require_auth on the agent, so anyone could complete on the
agent's behalf and inflate completed_agreements; it also re-counted on
repeated calls. rate_agent had no self-rating guard.

- register_transaction now takes a caller, requires its auth, and only
  accepts the agent or a listed party; parties must be non-empty, distinct,
  and must not include the agent (which also forecloses self-rating).
- complete_transaction now calls agent.require_auth() and rejects
  double-completion (TransactionAlreadyCompleted).
- rate_agent rejects rater == agent (SelfRatingNotAllowed).
- 8 new adversarial tests; existing transaction tests updated to the new
  register_transaction signature. cargo test 31 passed; fmt + clippy clean.
@Vyacheslav-Tomashevskiy

Vyacheslav-Tomashevskiy commented Jun 30, 2026

Copy link
Copy Markdown
Author

Rebased onto latest main and resolved the conflicts that appeared after the recent merges:

  • errors.rs: renumbered the new variants to SelfRatingNotAllowed = 19, InvalidParties = 20, TransactionAlreadyCompleted = 21 so they no longer collide with the pause/admin variants (14-18) that landed on main.
  • agent.rs: kept both check_paused(env)? and the new caller.require_auth() in register_transaction/complete_transaction.
  • Updated the corresponding should_panic codes in the tests.

cargo test -p agent_registry is green (31 passed). PR is now mergeable: clean.

RTC wallet for payout: RTCd1554f0f35576faf01d386a6be1c947f560dd0b7

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.

[Security] agent_registry register_transaction and complete_transaction are unauthenticated, letting reputation be fabricated

1 participant