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
TRST-H-2 to H-6: Consolidated fixes from Trust Security audit (#1010)
* fix(service): TRST-H-2 -- reject V2 receipts with non-zero collection_id prefix
The AllocationEligible check only examines the trailing 20 bytes of a
32-byte collection_id, while storage persists all 32 bytes. The tap-agent
reconstructs collection_id with zero-padded prefix, so receipts with
non-zero prefix bytes pass validation but are invisible to RAV aggregation,
enabling theft of service.
Reject any V2 receipt where collection_id[0..12] is not all zeros.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-3 -- add collector filter to V2 escrow account query
The V2 escrow query did not filter by collector, allowing an attacker to
inflate a payer's perceived balance by depositing to a fake collector
contract. Adds a required graph_tally_collector_address config field and
passes it as a collector filter in the GraphQL query.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-4 -- add pagination and balance filter to V2 escrow account query
The V2 escrow accounts GraphQL query omitted pagination parameters,
defaulting to first: 100. An attacker could deposit 1 wei from hundreds
of fake payer addresses to crowd out legitimate payers, blinding the
indexer to all real balances and signer mappings.
Add skip/first pagination with a loop that accumulates all pages, pin
to block hash from the first page for consistent reads, filter out
accounts below 0.1 GRT at the subgraph level, and cap nested signers
at 1000 per payer. Log page and account counts after pagination and
warn when pages exceed 5 or any payer hits the signer cap.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(tap-agent): TRST-H-5 -- apply rav_request_timeout to gRPC Endpoint
The rav_request_timeout config field was defined and validated but never
applied to the tonic Endpoint. A malicious aggregator could hang the
AggregateReceipts RPC indefinitely, permanently blocking the
SenderAllocation actor and bypassing sender denial checks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(tap-agent): TRST-H-6 -- use strict signer set for RAV signature verification
The tap-agent was using a single escrow accounts watcher with thawing
signers included for both receipt processing and RAV verification. A payer
could sign RAVs with a thawing signer, then revoke it before the indexer
redeems. The RAV becomes unredeemable on-chain but the tap-agent has
already removed receipt values from its funds-at-risk tracker.
Create a second escrow accounts watcher with reject_thawing_signers=true
and thread it through to TapAgentContext for RAV signature verification.
Receipt processing continues using the permissive watcher.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-3 -- use scalar collector filter in V2 escrow query
The collector_ nested relationship filter is rejected by the live
subgraph. Switch to the scalar collector: $collector form, which is
confirmed working against the deployed network subgraph.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(tap-agent): TRST-H-4 -- persist signers locally and replace startup panic
The nested signers sub-query in the V2 escrow account query caps at
first: 1000. A malicious payer can authorize enough signers to crowd
out a legitimate one, causing get_pending_sender_allocation_id_v2() to
panic via .expect() and crash the entire tap-agent process.
Add a tap_escrow_signers cache table that is upserted on every escrow
accounts poll. When a signer lookup against the live subgraph data
fails, both the startup path and the receipt notification handler fall
back to the local cache. If neither source resolves the signer, skip
it with a warning and increment tap_signer_lookup_failures_total.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-4 -- use cursor-based pagination for V2 escrow query
Graph Node caps skip at 5000, so the previous skip-based pagination
would fail after 25 pages (5000 / 200 page size). Replace with
cursor-based pagination using id_gt, which has no upper bound. This
matches the existing pattern used by allocations.query.graphql.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(tap-agent): TRST-H-6 -- pass both escrow watchers through TapAgentContext
TapAgentContext previously received only the strict escrow watcher
(excluding thawing signers), but receipt retrieval and deletion also
used it. This caused receipts from thawing signers to become invisible
to the TAP manager. Now the context carries both watchers: the full
set for receipt operations and the strict set for RAV signature
verification only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-4 -- replace signer cache with nested signer pagination
The database cache (tap_escrow_signers) was only consulted in two places in
sender_accounts_manager, while all downstream consumers still used the raw
EscrowAccounts watcher. This left crowded-out signers invisible for fee
calculations, RAV aggregation, and cleanup. Replace the cache with cursor-based
follow-up pagination so EscrowAccounts is complete at the source. Also makes the
0.1 GRT balance filter configurable via escrow_min_balance_grt_wei.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-4 -- default to unlimited signer pagination
The previous default of max_signers_per_payer = 1000 silently truncated
signers beyond the cap, enabling the same free-queries attack as the
original vulnerability at a marginally higher cost to the attacker.
Default to 0 (no limit) so all signers are fetched and no receipts are
orphaned. A warning fires when any payer exceeds 1000 signers. The cap
remains configurable for operators who accept the trade-off.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(monitor): TRST-H-4 -- tighten signer pagination cap and ordering
Three follow-ups to 28f3b10:
- router.rs fallback default was still 1000 when no network subgraph is
configured; align with the unlimited (0) default introduced in 28f3b10.
- Nested signers selection in the V2 escrow query lacked explicit ordering,
so the 1000-item page cap returned a non-deterministic prefix and the
follow-up SignersByPayerQuery cursor could skip or duplicate signers. Add
orderBy: id, orderDirection: asc.
- The max_signers_per_payer truncation ran after the "fewer than 1000
returned, skip pagination" shortcut, so an operator cap below 1000 was
silently ignored when the initial query already exceeded it (e.g. cap=200,
returned=500). Swap the two checks so the cap is enforced first.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: fix missing fields
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
---------
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
Co-authored-by: MoonBoi9001 <samuelametcalfe@yahoo.co.uk>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 commit comments